├── .gitattributes ├── .github └── workflows │ ├── testAndbuildResults.yml │ └── tests.yml ├── .gitignore ├── .gitmodules ├── .prettierignore ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── foundry.toml ├── package.json ├── script └── runTest.js ├── src ├── BaseMarketConfig.sol ├── Types.sol └── marketplaces │ ├── X2Y2 │ ├── X2Y2Config.sol │ ├── interfaces │ │ ├── IX2Y2Marketplace.sol │ │ └── MarketConstants.sol │ └── lib │ │ ├── ECDSA.sol │ │ ├── Strings.sol │ │ └── X2Y2TypeHashes.sol │ ├── blur-2.0 │ ├── BlurV2Config.sol │ ├── interfaces │ │ └── IBlurExchangeV2.sol │ └── lib │ │ ├── BlurV2TypeHashes.sol │ │ ├── Merkle.sol │ │ ├── MurkyBase.sol │ │ ├── Oracle.sol │ │ └── Structs.sol │ ├── blur │ ├── BlurConfig.sol │ ├── interfaces │ │ └── IBlurExchange.sol │ └── lib │ │ ├── BlurTypeHashes.sol │ │ └── OrderStructs.sol │ ├── foundation │ ├── FoundationConfig.sol │ └── interfaces │ │ └── IFoundation.sol │ ├── looksRare-v2 │ ├── LooksRareV2Config.sol │ ├── interfaces │ │ ├── ILooksRareProtocol.sol │ │ └── ITransferManager.sol │ └── lib │ │ ├── CollectionType.sol │ │ ├── LooksRareV2TypeHashes.sol │ │ ├── OrderStructs.sol │ │ └── QuoteType.sol │ ├── looksRare │ ├── LooksRareConfig.sol │ ├── interfaces │ │ ├── ICurrencyManager.sol │ │ └── ILooksRareExchange.sol │ └── lib │ │ ├── LooksRareTypeHashes.sol │ │ └── OrderTypes.sol │ ├── seaport-1.1 │ ├── SeaportOnePointOneConfig.sol │ ├── interfaces │ │ └── ConsiderationInterface.sol │ └── lib │ │ ├── ConsiderationEnums.sol │ │ ├── ConsiderationStructs.sol │ │ └── ConsiderationTypeHashes.sol │ ├── seaport-1.5 │ ├── SeaportOnePointFiveConfig.sol │ ├── interfaces │ │ └── ConsiderationInterface.sol │ └── lib │ │ ├── ConsiderationEnums.sol │ │ ├── ConsiderationStructs.sol │ │ └── ConsiderationTypeHashes.sol │ ├── seaport-1.6 │ ├── SeaportOnePointSixConfig.sol │ ├── interfaces │ │ └── ConsiderationInterface.sol │ └── lib │ │ ├── ConsiderationEnums.sol │ │ ├── ConsiderationStructs.sol │ │ └── ConsiderationTypeHashes.sol │ ├── sudoswap │ ├── SudoswapConfig.sol │ └── interfaces │ │ ├── IPair.sol │ │ ├── IPairFactory.sol │ │ └── IRouter.sol │ ├── wyvern │ ├── WyvernConfig.sol │ ├── interfaces │ │ ├── IAtomicizer.sol │ │ ├── IERC1155.sol │ │ ├── IERC721.sol │ │ ├── IWyvernProxyRegistry.sol │ │ └── WyvernInterface.sol │ └── lib │ │ ├── ArrayUtils.sol │ │ ├── WyvernEnums.sol │ │ ├── WyvernStructs.sol │ │ └── WyvernTypeHashes.sol │ └── zeroEx │ ├── ZeroExConfig.sol │ ├── interfaces │ └── IZeroEx.sol │ └── lib │ ├── LibNFTOrder.sol │ └── LibSignature.sol ├── test ├── GenericMarketplaceTest.t.sol ├── tokens │ ├── TestERC1155.sol │ ├── TestERC20.sol │ ├── TestERC721.sol │ └── WETH.sol └── utils │ └── BaseOrderTest.sol └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | .gas-snapshot linguist-language=Julia -------------------------------------------------------------------------------- /.github/workflows/testAndbuildResults.yml: -------------------------------------------------------------------------------- 1 | name: Test and build results 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | 7 | jobs: 8 | tests: 9 | name: Run Tests 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | 14 | - name: Checkout results branch 15 | uses: actions/checkout@v3 16 | with: 17 | ref: results 18 | path: results 19 | 20 | - name: Install Foundry 21 | uses: onbjerg/foundry-toolchain@v1 22 | with: 23 | version: nightly 24 | 25 | - name: Install dependencies 26 | run: forge install 27 | - run: yarn install --frozen-lockfile 28 | 29 | - name: Run tests 30 | run: yarn test:generate ${{ secrets.ETH_RPC_URL }} 31 | 32 | - name: Process latex EOA 33 | uses: dante-ev/latex-action@latest 34 | with: 35 | root_file: results.tex 36 | compiler: lualatex 37 | working_directory: results 38 | args: -interaction=nonstopmode -shell-escape 39 | 40 | - name: Process latex direct 41 | uses: dante-ev/latex-action@latest 42 | with: 43 | root_file: results-direct.tex 44 | compiler: lualatex 45 | working_directory: results 46 | args: -interaction=nonstopmode -shell-escape 47 | 48 | - name: Save results 49 | run: | 50 | cd results 51 | if [[ `git status --porcelain` ]]; then 52 | git config --global user.name 'GitHub Actions Bot' 53 | git config --global user.email '<>' 54 | git add *.pdf 55 | git commit -m "Autogenerated pdf" 56 | git push 57 | fi 58 | 59 | lint: 60 | name: Run Lint 61 | runs-on: ubuntu-latest 62 | steps: 63 | - uses: actions/checkout@v3 64 | - uses: actions/setup-node@v2 65 | with: 66 | node-version: 12.x 67 | - run: yarn install --frozen-lockfile 68 | - run: yarn lint:check 69 | 70 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Test and lint 2 | permissions: read-all 3 | 4 | on: 5 | pull_request_target: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | tests: 11 | name: Run Tests 12 | runs-on: ubuntu-latest 13 | environment: build 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | ref: "refs/pull/${{ github.event.number }}/merge" 18 | 19 | - name: Install Foundry 20 | uses: onbjerg/foundry-toolchain@v1 21 | with: 22 | version: nightly 23 | 24 | - name: Install dependencies 25 | run: forge install 26 | 27 | - name: Run tests 28 | run: forge test --fork-url ${{ secrets.ETH_RPC_URL }} -vv 29 | lint: 30 | name: Run Lint 31 | runs-on: ubuntu-latest 32 | environment: build 33 | steps: 34 | - uses: actions/checkout@v3 35 | with: 36 | ref: "refs/pull/${{ github.event.number }}/merge" 37 | 38 | - uses: actions/setup-node@v2 39 | with: 40 | node-version: 12.x 41 | - run: yarn install --frozen-lockfile 42 | - run: yarn lint:check -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /cache 2 | /node_modules 3 | /out 4 | 5 | .DS_Store 6 | results/results.tex 7 | results/results-direct.tex 8 | 9 | *.env 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/forge-std"] 2 | path = lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | [submodule "lib/solmate"] 5 | path = lib/solmate 6 | url = https://github.com/rari-capital/solmate 7 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | lib/solmate 2 | lib/forge-std -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "solidity.packageDefaultDependenciesContractsDirectory": "src", 3 | "solidity.packageDefaultDependenciesDirectory": "lib", 4 | "solidity.compileUsingRemoteVersion": "v0.8.14", 5 | "search.exclude": { "lib": true }, 6 | "files.associations": { 7 | ".gas-snapshot": "julia" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 t11s 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Marketplace Benchmarks 2 | Marketplace Benchmarks is a repository which runs a variety of generalized tests on NFT marketplaces to benchmark them for gas efficiency. View benchmark results [here](../results/results.pdf) for EOA calls and [here](../results/results-direct.pdf) for direct calls. 3 | 4 | ### Setup 5 | 6 | #### Install Foundry 7 | To install Foundry (assuming a Linux or macOS system): 8 | 9 | ```bash 10 | curl -L https://foundry.paradigm.xyz | bash 11 | ``` 12 | 13 | This will download foundryup. To start Foundry, run: 14 | 15 | ```bash 16 | foundryup 17 | ``` 18 | 19 | To install dependencies: 20 | 21 | ```bash 22 | forge install 23 | ``` 24 | 25 | ### Run Tests 26 | Tests are all run against mainnet deployments of active marketplaces. As such, a Mainnet Ethereum RPC is required. This will log gas snapshots for each individual test operation. 27 | ```bash 28 | forge test --fork-url -vv 29 | ``` 30 | 31 | ### Adding A Marketplace 32 | 1. Create a marketplace config in `/src/marketplaces` 33 | 2. Integrate into [`GenericMarketplaceTest`](test/GenericMarketplaceTest.t.sol) 34 | - Import your marketplace config 35 | - Create a global variable for your marketpalce config 36 | - Deploy and set your marketplace config in the constructor 37 | - Create a new test named `test` which calls `benchmarkMarket(BaseMarketConfig config)` with your marketplace config. 38 | 39 | #### Marketplace Config 40 | A marketplace config must inherits [`BaseMarketConfig`](src/BaseMarketConfig.sol#L53-L254). See [`SeaportConfig`](src/marketplaces/seaport/SeaportConfig.sol) for reference. 41 | 42 | ##### *Required Functions* 43 | - `beforeAllPrepareMarketplace(address seller, address buyer)` - This function must set the [approval targets](src/BaseMarketConfig.sol#L14-L26) for the marketplace. These addresses will be used prior to each test to reset buyer/seller approvals. 44 | - `name()` - This function must return the name of the marketplace to use in benchmarking results 45 | - `market()` - This function must return the address of the marketplace. It is used to reset the marketplace storage between tests. 46 | 47 | ##### *Optional Functions* 48 | There are a variety of different types of tests which your market can support by implementing any of the functions defined in the `Test Payload Calls` section of [`BaseMarketConfig`](src/BaseMarketConfig.sol). Tests that use unimplemented payload calls will show up as incompatable with your marketplace. 49 | 50 | `beforeAllPrepareMarketplaceCall` is an optional setup function which allows for any arbitrary calls to be sent from any address. For example: it was used to deploy Wyvern proxies for the buyer and seller prior to benchmarking Wyvern. 51 | 52 | ### Adding A Test 53 | Anyone can add a generalized test to this repository which will enable for checkpointing different functionalities across marketplaces. 54 | 55 | #### Creating the Generalized Test 56 | Generalized tests are written in [`GenericMarketplaceTest`](test/GenericMarketplaceTest.t.sol). Use the simple [ERC721->Ether](test/GenericMarketplaceTest.t.sol#L78-L110) test as a reference. 57 | 58 | 1. Ensure that the buyer (Bob) and seller (Alice) have sufficient funds for the transaction. Each user is dealt enough ETH prior to the test. 59 | 2. Find an appropriate payload call in [`BaseMarketConfig`](src/BaseMarketConfig.sol). If none exists, you may create a new one. 60 | 3. Use `_benchmarkCallWithParams` to call the payload. 61 | 4. Add assertions throughout the test to ensure that the marketplace is actually doing what you expect it to. 62 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | bytecode_hash = "none" 3 | optimizer_runs = 9_999_999 4 | ignored_error_codes = [5574, 5667, 9302] 5 | evm_version='cancun' 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "marketplace-benchmarks", 3 | "license": "MIT", 4 | "version": "1.0.0", 5 | "description": "Marketplace Benchmarking for various NFT marketplaces", 6 | "files": [ 7 | "src/**/*.sol" 8 | ], 9 | "devDependencies": { 10 | "prettier": "^2.3.1", 11 | "prettier-plugin-solidity": "^1.0.0-beta.13" 12 | }, 13 | "scripts": { 14 | "lint:check": "prettier --check **.sol && prettier --check **.js", 15 | "lint:fix": "prettier --write **.sol && prettier --write **.js", 16 | "test:generate": "node script/runTest.js" 17 | }, 18 | "prettier": { 19 | "overrides": [ 20 | { 21 | "files": [ 22 | "*.sol", 23 | "*.js" 24 | ], 25 | "options": { 26 | "tabWidth": 4, 27 | "printWidth": 80, 28 | "bracketSpacing": true 29 | } 30 | } 31 | ] 32 | }, 33 | "dependencies": { 34 | "child_process": "^1.0.2", 35 | "color-interpolate": "^1.0.5", 36 | "color-parse": "^1.4.2" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /script/runTest.js: -------------------------------------------------------------------------------- 1 | const { exec } = require("child_process"); 2 | const interpolate = require("color-interpolate"); 3 | const parse = require("color-parse"); 4 | const colormap = interpolate(["green", "red"]); 5 | const fs = require("fs"); 6 | const RPC = process.argv[2]; 7 | 8 | if (RPC === undefined || RPC == "") throw Error("RPC not set"); 9 | 10 | // Execute forge tests and capture `stdout` 11 | exec( 12 | `forge clean && forge test --fork-url ${RPC} -vv`, 13 | (error, stdout, stderr) => { 14 | if (error) { 15 | throw Error("Forge test failed"); 16 | } 17 | 18 | /// {market:{testName:{actionName:{gas,direct}}}} 19 | let eoaTests = {}; 20 | eoaTests.results = {}; 21 | parseOutput(eoaTests, stdout, false); 22 | const eoaLatex = generateLatex( 23 | eoaTests.results, 24 | "Benchmark Tests (EOA)" 25 | ); 26 | 27 | // Create dir if needed 28 | if (!fs.existsSync("./results")) { 29 | fs.mkdirSync("./results"); 30 | } 31 | 32 | fs.writeFileSync("./results/results.tex", eoaLatex); 33 | 34 | /// {market:{testName:{actionName:{gas,direct}}}} 35 | let directTests = {}; 36 | directTests.results = {}; 37 | parseOutput(directTests, stdout, true); 38 | const directLatex = generateLatex( 39 | directTests.results, 40 | "Benchmark Tests (Direct)" 41 | ); 42 | fs.writeFileSync("./results/results-direct.tex", directLatex); 43 | } 44 | ); 45 | 46 | /** 47 | * Parses the entire `stdout` from forge. Sets the values in `tests` 48 | * @param {*} tests The variable which holds test results 49 | * @param {*} stdout The output from running forge on the market-benchmark tests 50 | * @param {*} showDirect Show direct contract interactions (as opposed to EOA) 51 | */ 52 | function parseOutput(tests, stdout, showDirect = false) { 53 | const outputLines = stdout.split("\n"); 54 | let doNextLine = false; 55 | for (let outputLine of outputLines) { 56 | outputLine = outputLine.trim(); 57 | 58 | if (outputLine == "") { 59 | doNextLine = false; 60 | } else if (doNextLine) { 61 | parseTestLine(tests, outputLine, showDirect); 62 | } else if (outputLine.includes("Logs:")) { 63 | doNextLine = true; 64 | } 65 | } 66 | } 67 | 68 | /** 69 | * Parses a line of text from the forge output. Sets corresponding keys in `tests` 70 | */ 71 | function parseTestLine(tests, testLine, showDirect) { 72 | const marketName = testLine.split("]")[0].substring(1); 73 | const testName = testLine.split(")")[0].split("(")[1]; 74 | const actionName = testLine 75 | .split(")")[1] 76 | .split("(")[0] 77 | .split("--")[0] 78 | .trim(); 79 | const direct = testLine.includes("(direct)"); 80 | const gasUsage = 81 | testLine.split("gas:").length > 1 82 | ? testLine.split("gas:")[1].trim() 83 | : 0; 84 | if ( 85 | (showDirect && !direct && gasUsage != 0) || 86 | (!showDirect && direct && gasUsage != 0) 87 | ) 88 | return; // Skip unwanted results 89 | addTestResults(tests, marketName, testName, actionName, gasUsage); 90 | } 91 | 92 | function addTestResults(tests, market, testName, actionName, gasUsage) { 93 | if (!tests.results.hasOwnProperty(market)) { 94 | tests.results[market] = {}; 95 | } 96 | if (!tests.results[market].hasOwnProperty(testName)) { 97 | tests.results[market][testName] = {}; 98 | } 99 | if (actionName == "") return; 100 | tests.results[market][testName][actionName] = { gasUsage }; 101 | } 102 | 103 | /** 104 | * Generates the latex from the global dictionary `tests` 105 | * @returns String containing latex 106 | */ 107 | function generateLatex(tests, title) { 108 | let latex = ""; 109 | const markets = Object.keys(tests); 110 | const testNames = Object.keys(tests[markets[0]]); 111 | 112 | latex += 113 | "\\documentclass[border = 4pt]{standalone}\n\\usepackage{emoji}\n\\usepackage{xcolor}\n\\usepackage{multirow}\n\\begin{document}" + 114 | `\n\\setemojifont{TwemojiMozilla}\n\\begin{tabular}{ |c|c|${"c|".repeat( 115 | markets.length 116 | )} } \n\\hline\n\\multicolumn{${ 117 | 2 + markets.length 118 | }}{|c|}{${title}} \\\\ \n` + 119 | "\\hline \n Test Name & Action Name "; 120 | 121 | for (const market of markets) { 122 | latex += `& ${market} `; 123 | } 124 | 125 | latex += "\\\\ \n\\hline\\hline\n"; 126 | 127 | for (const testName of testNames) { 128 | let actionNames = []; 129 | for (const market of markets) { 130 | const tempActionNames = Object.keys(tests[market][testName]); 131 | if (actionNames.length < tempActionNames.length) 132 | actionNames = tempActionNames; 133 | } 134 | if (actionNames.length == 0) { 135 | actionNames = [""]; 136 | } 137 | 138 | latex += `\\multirow{${actionNames.length}}{18em}{${testName}}`; 139 | for (const actionName of actionNames) { 140 | latex += `& ${actionName} `; 141 | 142 | let gasValues = []; 143 | for (const market of markets) { 144 | if (tests[market][testName][actionName] === undefined) { 145 | gasValues.push(0); 146 | } else { 147 | gasValues.push( 148 | parseInt(tests[market][testName][actionName].gasUsage) 149 | ); 150 | } 151 | } 152 | const maxGas = Math.max(...gasValues); 153 | const minGas = Math.min.apply(null, gasValues.filter(Boolean)); 154 | 155 | for (const gasValue of gasValues) { 156 | const color = getColor(minGas, maxGas, gasValue); 157 | if (gasValue == 0) { 158 | latex += `& \\emoji{cross-mark} `; 159 | } else { 160 | const percentChange = Math.round( 161 | ((gasValue - minGas) * 100.0) / minGas 162 | ); 163 | latex += 164 | `& \\color[RGB]{${color.values[0]},${color.values[1]},${color.values[2]}} ${gasValue}` + 165 | (percentChange != 0 ? `(+${percentChange}\\%)` : ``); // Only show percent change if not 0 166 | } 167 | } 168 | 169 | latex += "\\\\\n"; 170 | latex += `\\cline{2-${2 + markets.length}}`; 171 | } 172 | latex += "\\cline{0-1} \n"; 173 | } 174 | 175 | latex += "\\end{tabular}\n\\end{document}"; 176 | 177 | return latex; 178 | } 179 | 180 | /** 181 | * Generate interpolated color between green and red (green lowest gas, and red highest) 182 | * @param {*} minGas The minimum gas used for the test 183 | * @param {*} maxGas The maximum gas used for the test 184 | * @param {*} gas The gas used by a market for this test 185 | * @returns The color to display market results as for the test 186 | */ 187 | function getColor(minGas, maxGas, gas) { 188 | let color; 189 | if (minGas == maxGas) { 190 | color = colormap(0); 191 | } else if (!Number.isFinite(minGas)) { 192 | color = colormap(0); 193 | } else { 194 | color = colormap(((gas - minGas) * 1.0) / (maxGas - minGas)); 195 | } 196 | 197 | const parsed = parse(color); 198 | return parsed; 199 | } 200 | -------------------------------------------------------------------------------- /src/Types.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.7; 3 | 4 | struct TestItem721 { 5 | address token; 6 | uint256 identifier; 7 | } 8 | 9 | struct TestItem1155 { 10 | address token; 11 | uint256 identifier; 12 | uint256 amount; 13 | } 14 | 15 | struct TestItem20 { 16 | address token; 17 | uint256 amount; 18 | } 19 | 20 | struct TestCallParameters { 21 | address target; 22 | uint256 value; 23 | bytes data; 24 | } 25 | 26 | struct SetupCall { 27 | address sender; 28 | address target; 29 | bytes data; 30 | } 31 | 32 | struct TestOrderContext { 33 | bool listOnChain; 34 | address offerer; 35 | address fulfiller; 36 | } 37 | 38 | struct TestOrderPayload { 39 | // Call needed to submit order on-chain without signature 40 | TestCallParameters submitOrder; 41 | // Call needed to actually execute the order 42 | TestCallParameters executeOrder; 43 | } 44 | -------------------------------------------------------------------------------- /src/marketplaces/X2Y2/interfaces/IX2Y2Marketplace.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import { Market } from "./MarketConstants.sol"; 5 | 6 | interface IX2Y2Marketplace { 7 | function run1( 8 | Market.Order memory order, 9 | Market.SettleShared memory shared, 10 | Market.SettleDetail memory detail 11 | ) external returns (uint256); 12 | 13 | function run(Market.RunInput memory input) external payable; 14 | 15 | function updateSigners(address[] memory toAdd, address[] memory toRemove) 16 | external; 17 | } 18 | -------------------------------------------------------------------------------- /src/marketplaces/X2Y2/interfaces/MarketConstants.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicensed 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | library Market { 6 | uint256 constant INTENT_SELL = 1; 7 | uint256 constant INTENT_AUCTION = 2; 8 | uint256 constant INTENT_BUY = 3; 9 | 10 | uint8 constant SIGN_V1 = 1; 11 | uint8 constant SIGN_V3 = 3; 12 | 13 | struct OrderItem { 14 | uint256 price; 15 | bytes data; 16 | } 17 | 18 | struct Order { 19 | uint256 salt; 20 | address user; 21 | uint256 network; 22 | uint256 intent; 23 | uint256 delegateType; 24 | uint256 deadline; 25 | address currency; 26 | bytes dataMask; 27 | OrderItem[] items; 28 | // signature 29 | bytes32 r; 30 | bytes32 s; 31 | uint8 v; 32 | uint8 signVersion; 33 | } 34 | 35 | struct Fee { 36 | uint256 percentage; 37 | address to; 38 | } 39 | 40 | struct SettleDetail { 41 | Market.Op op; 42 | uint256 orderIdx; 43 | uint256 itemIdx; 44 | uint256 price; 45 | bytes32 itemHash; 46 | address executionDelegate; 47 | bytes dataReplacement; 48 | uint256 bidIncentivePct; 49 | uint256 aucMinIncrementPct; 50 | uint256 aucIncDurationSecs; 51 | Fee[] fees; 52 | } 53 | 54 | struct SettleShared { 55 | uint256 salt; 56 | uint256 deadline; 57 | uint256 amountToEth; 58 | uint256 amountToWeth; 59 | address user; 60 | bool canFail; 61 | } 62 | 63 | struct RunInput { 64 | Order[] orders; 65 | SettleDetail[] details; 66 | SettleShared shared; 67 | // signature 68 | bytes32 r; 69 | bytes32 s; 70 | uint8 v; 71 | } 72 | 73 | struct OngoingAuction { 74 | uint256 price; 75 | uint256 netPrice; 76 | uint256 endAt; 77 | address bidder; 78 | } 79 | 80 | enum InvStatus { 81 | NEW, 82 | AUCTION, 83 | COMPLETE, 84 | CANCELLED, 85 | REFUNDED 86 | } 87 | 88 | enum Op { 89 | INVALID, 90 | // off-chain 91 | COMPLETE_SELL_OFFER, 92 | COMPLETE_BUY_OFFER, 93 | CANCEL_OFFER, 94 | // auction 95 | BID, 96 | COMPLETE_AUCTION, 97 | REFUND_AUCTION, 98 | REFUND_AUCTION_STUCK_ITEM 99 | } 100 | 101 | enum DelegationType { 102 | INVALID, 103 | ERC721, 104 | ERC1155 105 | } 106 | 107 | struct Pair { 108 | address token; 109 | uint256 tokenId; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/marketplaces/X2Y2/lib/ECDSA.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (utils/cryptography/ECDSA.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "./Strings.sol"; 7 | 8 | /** 9 | * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. 10 | * 11 | * These functions can be used to verify that a message was signed by the holder 12 | * of the private keys of a given address. 13 | */ 14 | library ECDSA { 15 | enum RecoverError { 16 | NoError, 17 | InvalidSignature, 18 | InvalidSignatureLength, 19 | InvalidSignatureS, 20 | InvalidSignatureV 21 | } 22 | 23 | function _throwError(RecoverError error) private pure { 24 | if (error == RecoverError.NoError) { 25 | return; // no error: do nothing 26 | } else if (error == RecoverError.InvalidSignature) { 27 | revert("ECDSA: invalid signature"); 28 | } else if (error == RecoverError.InvalidSignatureLength) { 29 | revert("ECDSA: invalid signature length"); 30 | } else if (error == RecoverError.InvalidSignatureS) { 31 | revert("ECDSA: invalid signature 's' value"); 32 | } else if (error == RecoverError.InvalidSignatureV) { 33 | revert("ECDSA: invalid signature 'v' value"); 34 | } 35 | } 36 | 37 | /** 38 | * @dev Returns the address that signed a hashed message (`hash`) with 39 | * `signature` or error string. This address can then be used for verification purposes. 40 | * 41 | * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: 42 | * this function rejects them by requiring the `s` value to be in the lower 43 | * half order, and the `v` value to be either 27 or 28. 44 | * 45 | * IMPORTANT: `hash` _must_ be the result of a hash operation for the 46 | * verification to be secure: it is possible to craft signatures that 47 | * recover to arbitrary addresses for non-hashed data. A safe way to ensure 48 | * this is by receiving a hash of the original message (which may otherwise 49 | * be too long), and then calling {toEthSignedMessageHash} on it. 50 | * 51 | * Documentation for signature generation: 52 | * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] 53 | * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] 54 | * 55 | * _Available since v4.3._ 56 | */ 57 | function tryRecover(bytes32 hash, bytes memory signature) 58 | internal 59 | pure 60 | returns (address, RecoverError) 61 | { 62 | // Check the signature length 63 | // - case 65: r,s,v signature (standard) 64 | // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ 65 | if (signature.length == 65) { 66 | bytes32 r; 67 | bytes32 s; 68 | uint8 v; 69 | // ecrecover takes the signature parameters, and the only way to get them 70 | // currently is to use assembly. 71 | assembly { 72 | r := mload(add(signature, 0x20)) 73 | s := mload(add(signature, 0x40)) 74 | v := byte(0, mload(add(signature, 0x60))) 75 | } 76 | return tryRecover(hash, v, r, s); 77 | } else if (signature.length == 64) { 78 | bytes32 r; 79 | bytes32 vs; 80 | // ecrecover takes the signature parameters, and the only way to get them 81 | // currently is to use assembly. 82 | assembly { 83 | r := mload(add(signature, 0x20)) 84 | vs := mload(add(signature, 0x40)) 85 | } 86 | return tryRecover(hash, r, vs); 87 | } else { 88 | return (address(0), RecoverError.InvalidSignatureLength); 89 | } 90 | } 91 | 92 | /** 93 | * @dev Returns the address that signed a hashed message (`hash`) with 94 | * `signature`. This address can then be used for verification purposes. 95 | * 96 | * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: 97 | * this function rejects them by requiring the `s` value to be in the lower 98 | * half order, and the `v` value to be either 27 or 28. 99 | * 100 | * IMPORTANT: `hash` _must_ be the result of a hash operation for the 101 | * verification to be secure: it is possible to craft signatures that 102 | * recover to arbitrary addresses for non-hashed data. A safe way to ensure 103 | * this is by receiving a hash of the original message (which may otherwise 104 | * be too long), and then calling {toEthSignedMessageHash} on it. 105 | */ 106 | function recover(bytes32 hash, bytes memory signature) 107 | internal 108 | pure 109 | returns (address) 110 | { 111 | (address recovered, RecoverError error) = tryRecover(hash, signature); 112 | _throwError(error); 113 | return recovered; 114 | } 115 | 116 | /** 117 | * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. 118 | * 119 | * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] 120 | * 121 | * _Available since v4.3._ 122 | */ 123 | function tryRecover( 124 | bytes32 hash, 125 | bytes32 r, 126 | bytes32 vs 127 | ) internal pure returns (address, RecoverError) { 128 | bytes32 s; 129 | uint8 v; 130 | assembly { 131 | s := and( 132 | vs, 133 | 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 134 | ) 135 | v := add(shr(255, vs), 27) 136 | } 137 | return tryRecover(hash, v, r, s); 138 | } 139 | 140 | /** 141 | * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. 142 | * 143 | * _Available since v4.2._ 144 | */ 145 | function recover( 146 | bytes32 hash, 147 | bytes32 r, 148 | bytes32 vs 149 | ) internal pure returns (address) { 150 | (address recovered, RecoverError error) = tryRecover(hash, r, vs); 151 | _throwError(error); 152 | return recovered; 153 | } 154 | 155 | /** 156 | * @dev Overload of {ECDSA-tryRecover} that receives the `v`, 157 | * `r` and `s` signature fields separately. 158 | * 159 | * _Available since v4.3._ 160 | */ 161 | function tryRecover( 162 | bytes32 hash, 163 | uint8 v, 164 | bytes32 r, 165 | bytes32 s 166 | ) internal pure returns (address, RecoverError) { 167 | // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature 168 | // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines 169 | // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most 170 | // signatures from current libraries generate a unique signature with an s-value in the lower half order. 171 | // 172 | // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value 173 | // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or 174 | // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept 175 | // these malleable signatures as well. 176 | if ( 177 | uint256(s) > 178 | 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 179 | ) { 180 | return (address(0), RecoverError.InvalidSignatureS); 181 | } 182 | if (v != 27 && v != 28) { 183 | return (address(0), RecoverError.InvalidSignatureV); 184 | } 185 | 186 | // If the signature is valid (and not malleable), return the signer address 187 | address signer = ecrecover(hash, v, r, s); 188 | if (signer == address(0)) { 189 | return (address(0), RecoverError.InvalidSignature); 190 | } 191 | 192 | return (signer, RecoverError.NoError); 193 | } 194 | 195 | /** 196 | * @dev Overload of {ECDSA-recover} that receives the `v`, 197 | * `r` and `s` signature fields separately. 198 | */ 199 | function recover( 200 | bytes32 hash, 201 | uint8 v, 202 | bytes32 r, 203 | bytes32 s 204 | ) internal pure returns (address) { 205 | (address recovered, RecoverError error) = tryRecover(hash, v, r, s); 206 | _throwError(error); 207 | return recovered; 208 | } 209 | 210 | /** 211 | * @dev Returns an Ethereum Signed Message, created from a `hash`. This 212 | * produces hash corresponding to the one signed with the 213 | * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] 214 | * JSON-RPC method as part of EIP-191. 215 | * 216 | * See {recover}. 217 | */ 218 | function toEthSignedMessageHash(bytes32 hash) 219 | internal 220 | pure 221 | returns (bytes32) 222 | { 223 | // 32 is the length in bytes of hash, 224 | // enforced by the type signature above 225 | return 226 | keccak256( 227 | abi.encodePacked("\x19Ethereum Signed Message:\n32", hash) 228 | ); 229 | } 230 | 231 | /** 232 | * @dev Returns an Ethereum Signed Message, created from `s`. This 233 | * produces hash corresponding to the one signed with the 234 | * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] 235 | * JSON-RPC method as part of EIP-191. 236 | * 237 | * See {recover}. 238 | */ 239 | function toEthSignedMessageHash(bytes memory s) 240 | internal 241 | pure 242 | returns (bytes32) 243 | { 244 | return 245 | keccak256( 246 | abi.encodePacked( 247 | "\x19Ethereum Signed Message:\n", 248 | Strings.toString(s.length), 249 | s 250 | ) 251 | ); 252 | } 253 | 254 | /** 255 | * @dev Returns an Ethereum Signed Typed Data, created from a 256 | * `domainSeparator` and a `structHash`. This produces hash corresponding 257 | * to the one signed with the 258 | * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] 259 | * JSON-RPC method as part of EIP-712. 260 | * 261 | * See {recover}. 262 | */ 263 | function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) 264 | internal 265 | pure 266 | returns (bytes32) 267 | { 268 | return 269 | keccak256( 270 | abi.encodePacked("\x19\x01", domainSeparator, structHash) 271 | ); 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /src/marketplaces/X2Y2/lib/Strings.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev String operations. 8 | */ 9 | library Strings { 10 | bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; 11 | 12 | /** 13 | * @dev Converts a `uint256` to its ASCII `string` decimal representation. 14 | */ 15 | function toString(uint256 value) internal pure returns (string memory) { 16 | // Inspired by OraclizeAPI's implementation - MIT licence 17 | // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol 18 | 19 | if (value == 0) { 20 | return "0"; 21 | } 22 | uint256 temp = value; 23 | uint256 digits; 24 | while (temp != 0) { 25 | digits++; 26 | temp /= 10; 27 | } 28 | bytes memory buffer = new bytes(digits); 29 | while (value != 0) { 30 | digits -= 1; 31 | buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); 32 | value /= 10; 33 | } 34 | return string(buffer); 35 | } 36 | 37 | /** 38 | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. 39 | */ 40 | function toHexString(uint256 value) internal pure returns (string memory) { 41 | if (value == 0) { 42 | return "0x00"; 43 | } 44 | uint256 temp = value; 45 | uint256 length = 0; 46 | while (temp != 0) { 47 | length++; 48 | temp >>= 8; 49 | } 50 | return toHexString(value, length); 51 | } 52 | 53 | /** 54 | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. 55 | */ 56 | function toHexString(uint256 value, uint256 length) 57 | internal 58 | pure 59 | returns (string memory) 60 | { 61 | bytes memory buffer = new bytes(2 * length + 2); 62 | buffer[0] = "0"; 63 | buffer[1] = "x"; 64 | for (uint256 i = 2 * length + 1; i > 1; --i) { 65 | buffer[i] = _HEX_SYMBOLS[value & 0xf]; 66 | value >>= 4; 67 | } 68 | require(value == 0, "Strings: hex length insufficient"); 69 | return string(buffer); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/marketplaces/X2Y2/lib/X2Y2TypeHashes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import { Market } from "../interfaces/MarketConstants.sol"; 5 | import { ECDSA } from "./ECDSA.sol"; 6 | 7 | contract X2Y2TypeHashes { 8 | function _deriveOrderDigest(Market.Order memory order) 9 | internal 10 | pure 11 | returns (bytes32) 12 | { 13 | bytes32 orderHash = keccak256( 14 | abi.encode( 15 | order.salt, 16 | order.user, 17 | order.network, 18 | order.intent, 19 | order.delegateType, 20 | order.deadline, 21 | order.currency, 22 | order.dataMask, 23 | order.items.length, 24 | order.items 25 | ) 26 | ); 27 | return ECDSA.toEthSignedMessageHash(orderHash); 28 | } 29 | 30 | function _deriveInputDigest(Market.RunInput memory input) 31 | internal 32 | pure 33 | returns (bytes32) 34 | { 35 | return 36 | keccak256( 37 | abi.encode(input.shared, input.details.length, input.details) 38 | ); 39 | } 40 | 41 | function _hashItem(Market.Order memory order, Market.OrderItem memory item) 42 | internal 43 | view 44 | virtual 45 | returns (bytes32) 46 | { 47 | return 48 | keccak256( 49 | abi.encode( 50 | order.salt, 51 | order.user, 52 | order.network, 53 | order.intent, 54 | order.delegateType, 55 | order.deadline, 56 | order.currency, 57 | order.dataMask, 58 | item 59 | ) 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/marketplaces/blur-2.0/interfaces/IBlurExchangeV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.14; 3 | 4 | import "../lib/Structs.sol"; 5 | 6 | interface IBlurExchangeV2 { 7 | error InsufficientFunds(); 8 | error TokenTransferFailed(); 9 | error InvalidOrder(); 10 | error ProtocolFeeTooHigh(); 11 | 12 | event NewProtocolFee(address indexed recipient, uint16 indexed rate); 13 | event NewGovernor(address indexed governor); 14 | event NewBlockRange(uint256 blockRange); 15 | event CancelTrade( 16 | address indexed user, 17 | bytes32 hash, 18 | uint256 index, 19 | uint256 amount 20 | ); 21 | event NonceIncremented(address indexed user, uint256 newNonce); 22 | event SetOracle(address indexed user, bool approved); 23 | 24 | function owner() external view returns (address); 25 | 26 | function hashListing(Listing memory listing) 27 | external 28 | pure 29 | returns (bytes32); 30 | 31 | function hashOrder(Order memory order, OrderType orderType) 32 | external 33 | view 34 | returns (bytes32); 35 | 36 | function hashTakeAsk(TakeAsk memory inputs, address _caller) 37 | external 38 | pure 39 | returns (bytes32); 40 | 41 | function hashTakeBid(TakeBid memory inputs, address _caller) 42 | external 43 | pure 44 | returns (bytes32); 45 | 46 | function hashTakeAskSingle(TakeAskSingle memory inputs, address _caller) 47 | external 48 | pure 49 | returns (bytes32); 50 | 51 | function hashTakeBidSingle(TakeBidSingle memory inputs, address _caller) 52 | external 53 | pure 54 | returns (bytes32); 55 | 56 | function initialize() external; 57 | 58 | function setProtocolFee(address recipient, uint16 rate) external; 59 | 60 | function setGovernor(address _governor) external; 61 | 62 | function setOracle(address oracle, bool approved) external; 63 | 64 | function setBlockRange(uint256 _blockRange) external; 65 | 66 | function incrementNonce() external; 67 | 68 | /*////////////////////////////////////////////////////////////// 69 | EXECUTION WRAPPERS 70 | //////////////////////////////////////////////////////////////*/ 71 | 72 | function takeAsk(TakeAsk memory inputs, bytes calldata oracleSignature) 73 | external 74 | payable; 75 | 76 | function takeBid(TakeBid memory inputs, bytes calldata oracleSignature) 77 | external; 78 | 79 | function takeAskSingle( 80 | TakeAskSingle memory inputs, 81 | bytes calldata oracleSignature 82 | ) external payable; 83 | 84 | function takeBidSingle( 85 | TakeBidSingle memory inputs, 86 | bytes calldata oracleSignature 87 | ) external; 88 | 89 | /*////////////////////////////////////////////////////////////// 90 | EXECUTION POOL WRAPPERS 91 | //////////////////////////////////////////////////////////////*/ 92 | 93 | function takeAskSinglePool( 94 | TakeAskSingle memory inputs, 95 | bytes calldata oracleSignature, 96 | uint256 amountToWithdraw 97 | ) external payable; 98 | 99 | function takeAskPool( 100 | TakeAsk memory inputs, 101 | bytes calldata oracleSignature, 102 | uint256 amountToWithdraw 103 | ) external payable; 104 | } 105 | -------------------------------------------------------------------------------- /src/marketplaces/blur-2.0/lib/BlurV2TypeHashes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./Structs.sol"; 5 | 6 | contract BlurV2TypeHashes { 7 | mapping(address => uint256) public nonces; 8 | 9 | bytes32 public constant DOMAIN_SEPARATOR = 10 | 0xdd526a4e59bb74d0e4e4ab849ded32647b3bcf1df3acc01f4c21e76a8018c7c9; 11 | 12 | bytes32 public constant ORDER_TYPEHASH = 13 | keccak256( 14 | "Order(address trader,address collection,bytes32 listingsRoot,uint256 numberOfListings,uint256 expirationTime,uint8 assetType,FeeRate makerFee,uint256 salt,uint8 orderType,uint256 nonce)FeeRate(address recipient,uint16 rate)" 15 | ); 16 | 17 | bytes32 FEE_TYPEHASH = keccak256("FeeRate(address recipient,uint16 rate)"); 18 | } 19 | -------------------------------------------------------------------------------- /src/marketplaces/blur-2.0/lib/Merkle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | import "./MurkyBase.sol"; 5 | 6 | /// @notice Nascent, simple, kinda efficient (and improving!) Merkle proof generator and verifier 7 | /// @author dmfxyz 8 | /// @dev Note Generic Merkle Tree 9 | contract Merkle is MurkyBase { 10 | /******************** 11 | * HASHING FUNCTION * 12 | ********************/ 13 | 14 | /// ascending sort and concat prior to hashing 15 | function hashLeafPairs(bytes32 left, bytes32 right) 16 | public 17 | pure 18 | override 19 | returns (bytes32 _hash) 20 | { 21 | assembly { 22 | switch lt(left, right) 23 | case 0 { 24 | mstore(0x0, right) 25 | mstore(0x20, left) 26 | } 27 | default { 28 | mstore(0x0, left) 29 | mstore(0x20, right) 30 | } 31 | _hash := keccak256(0x0, 0x40) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/marketplaces/blur-2.0/lib/MurkyBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | abstract contract MurkyBase { 5 | /*************** 6 | * CONSTRUCTOR * 7 | ***************/ 8 | constructor() {} 9 | 10 | /******************** 11 | * VIRTUAL HASHING FUNCTIONS * 12 | ********************/ 13 | function hashLeafPairs(bytes32 left, bytes32 right) 14 | public 15 | pure 16 | virtual 17 | returns (bytes32 _hash); 18 | 19 | /********************** 20 | * PROOF VERIFICATION * 21 | **********************/ 22 | 23 | function verifyProof( 24 | bytes32 root, 25 | bytes32[] memory proof, 26 | bytes32 valueToProve 27 | ) external pure returns (bool) { 28 | // proof length must be less than max array size 29 | bytes32 rollingHash = valueToProve; 30 | uint256 length = proof.length; 31 | unchecked { 32 | for (uint256 i = 0; i < length; ++i) { 33 | rollingHash = hashLeafPairs(rollingHash, proof[i]); 34 | } 35 | } 36 | return root == rollingHash; 37 | } 38 | 39 | /******************** 40 | * PROOF GENERATION * 41 | ********************/ 42 | 43 | function getRoot(bytes32[] memory data) public pure returns (bytes32) { 44 | require(data.length > 1, "won't generate root for single leaf"); 45 | while (data.length > 1) { 46 | data = hashLevel(data); 47 | } 48 | return data[0]; 49 | } 50 | 51 | function getProof(bytes32[] memory data, uint256 node) 52 | public 53 | pure 54 | returns (bytes32[] memory) 55 | { 56 | require(data.length > 1, "won't generate proof for single leaf"); 57 | // The size of the proof is equal to the ceiling of log2(numLeaves) 58 | bytes32[] memory result = new bytes32[](log2ceilBitMagic(data.length)); 59 | uint256 pos = 0; 60 | 61 | // Two overflow risks: node, pos 62 | // node: max array size is 2**256-1. Largest index in the array will be 1 less than that. Also, 63 | // for dynamic arrays, size is limited to 2**64-1 64 | // pos: pos is bounded by log2(data.length), which should be less than type(uint256).max 65 | while (data.length > 1) { 66 | unchecked { 67 | if (node & 0x1 == 1) { 68 | result[pos] = data[node - 1]; 69 | } else if (node + 1 == data.length) { 70 | result[pos] = bytes32(0); 71 | } else { 72 | result[pos] = data[node + 1]; 73 | } 74 | ++pos; 75 | node /= 2; 76 | } 77 | data = hashLevel(data); 78 | } 79 | return result; 80 | } 81 | 82 | ///@dev function is private to prevent unsafe data from being passed 83 | function hashLevel(bytes32[] memory data) 84 | private 85 | pure 86 | returns (bytes32[] memory) 87 | { 88 | bytes32[] memory result; 89 | 90 | // Function is private, and all internal callers check that data.length >=2. 91 | // Underflow is not possible as lowest possible value for data/result index is 1 92 | // overflow should be safe as length is / 2 always. 93 | unchecked { 94 | uint256 length = data.length; 95 | if (length & 0x1 == 1) { 96 | result = new bytes32[](length / 2 + 1); 97 | result[result.length - 1] = hashLeafPairs( 98 | data[length - 1], 99 | bytes32(0) 100 | ); 101 | } else { 102 | result = new bytes32[](length / 2); 103 | } 104 | // pos is upper bounded by data.length / 2, so safe even if array is at max size 105 | uint256 pos = 0; 106 | for (uint256 i = 0; i < length - 1; i += 2) { 107 | result[pos] = hashLeafPairs(data[i], data[i + 1]); 108 | ++pos; 109 | } 110 | } 111 | return result; 112 | } 113 | 114 | /****************** 115 | * MATH "LIBRARY" * 116 | ******************/ 117 | 118 | /// @dev Note that x is assumed > 0 119 | function log2ceil(uint256 x) public pure returns (uint256) { 120 | uint256 ceil = 0; 121 | uint256 pOf2; 122 | // If x is a power of 2, then this function will return a ceiling 123 | // that is 1 greater than the actual ceiling. So we need to check if 124 | // x is a power of 2, and subtract one from ceil if so. 125 | assembly { 126 | // we check by seeing if x == (~x + 1) & x. This applies a mask 127 | // to find the lowest set bit of x and then checks it for equality 128 | // with x. If they are equal, then x is a power of 2. 129 | 130 | /* Example 131 | x has single bit set 132 | x := 0000_1000 133 | (~x + 1) = (1111_0111) + 1 = 1111_1000 134 | (1111_1000 & 0000_1000) = 0000_1000 == x 135 | 136 | x has multiple bits set 137 | x := 1001_0010 138 | (~x + 1) = (0110_1101 + 1) = 0110_1110 139 | (0110_1110 & x) = 0000_0010 != x 140 | */ 141 | 142 | // we do some assembly magic to treat the bool as an integer later on 143 | pOf2 := eq(and(add(not(x), 1), x), x) 144 | } 145 | 146 | // if x == type(uint256).max, than ceil is capped at 256 147 | // if x == 0, then pO2 == 0, so ceil won't underflow 148 | unchecked { 149 | while (x > 0) { 150 | x >>= 1; 151 | ceil++; 152 | } 153 | ceil -= pOf2; // see above 154 | } 155 | return ceil; 156 | } 157 | 158 | /// Original bitmagic adapted from https://github.com/paulrberg/prb-math/blob/main/contracts/PRBMath.sol 159 | /// @dev Note that x assumed > 1 160 | function log2ceilBitMagic(uint256 x) public pure returns (uint256) { 161 | if (x <= 1) { 162 | return 0; 163 | } 164 | uint256 msb = 0; 165 | uint256 _x = x; 166 | if (x >= 2**128) { 167 | x >>= 128; 168 | msb += 128; 169 | } 170 | if (x >= 2**64) { 171 | x >>= 64; 172 | msb += 64; 173 | } 174 | if (x >= 2**32) { 175 | x >>= 32; 176 | msb += 32; 177 | } 178 | if (x >= 2**16) { 179 | x >>= 16; 180 | msb += 16; 181 | } 182 | if (x >= 2**8) { 183 | x >>= 8; 184 | msb += 8; 185 | } 186 | if (x >= 2**4) { 187 | x >>= 4; 188 | msb += 4; 189 | } 190 | if (x >= 2**2) { 191 | x >>= 2; 192 | msb += 2; 193 | } 194 | if (x >= 2**1) { 195 | msb += 1; 196 | } 197 | 198 | uint256 lsb = (~_x + 1) & _x; 199 | if ((lsb == _x) && (msb > 0)) { 200 | return msb; 201 | } else { 202 | return msb + 1; 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /src/marketplaces/blur-2.0/lib/Oracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.14; 3 | 4 | import { Vm } from "forge-std/Vm.sol"; 5 | 6 | address constant VM_ADDRESS = address( 7 | uint160(uint256(keccak256("hevm cheat code"))) 8 | ); 9 | Vm constant vm = Vm(VM_ADDRESS); 10 | 11 | contract Oracle { 12 | error ExpiredOracleSignature(); 13 | error InvalidOracleSignature(); 14 | 15 | uint256 constant Bytes1_shift = 0xf8; 16 | uint256 constant Bytes4_shift = 0xe0; 17 | 18 | uint256 public oraclePk = 0x07ac1e; 19 | address payable internal oracle = payable(vm.addr(oraclePk)); 20 | 21 | function produceOracleSignature(bytes32 _hash, uint32 blockNumber) 22 | public 23 | view 24 | returns (bytes memory signature) 25 | { 26 | bytes32 digest = keccak256(abi.encodePacked(_hash, blockNumber)); 27 | 28 | bytes memory toBeSigned = abi.encodePacked(digest, blockNumber, oracle); 29 | 30 | (uint8 v, bytes32 r, bytes32 s) = vm.sign( 31 | oraclePk, 32 | bytes32(toBeSigned) 33 | ); 34 | 35 | signature = abi.encodePacked(r, s, v, blockNumber, oracle); 36 | 37 | verifyOracleSignature(_hash, signature); 38 | 39 | return signature; 40 | } 41 | 42 | function verifyOracleSignature(bytes32 _hash, bytes memory oracleSignature) 43 | public 44 | view 45 | { 46 | bytes32 r; 47 | bytes32 s; 48 | uint8 v; 49 | uint32 blockNumber; 50 | 51 | bytes memory signature = oracleSignature; 52 | assembly { 53 | r := mload(add(0x20, signature)) 54 | s := mload(add(0x40, signature)) 55 | v := shr(Bytes1_shift, mload(add(0x60, signature))) 56 | blockNumber := shr(Bytes4_shift, mload(add(0x61, signature))) 57 | } 58 | 59 | if (blockNumber + 0 < block.number) { 60 | revert ExpiredOracleSignature(); 61 | } 62 | 63 | if ( 64 | !_verify( 65 | oracle, 66 | keccak256(abi.encodePacked(_hash, blockNumber)), 67 | v, 68 | r, 69 | s 70 | ) 71 | ) { 72 | revert InvalidOracleSignature(); 73 | } 74 | } 75 | 76 | function _verify( 77 | address signer, 78 | bytes32 digest, 79 | uint8 v, 80 | bytes32 r, 81 | bytes32 s 82 | ) private pure returns (bool valid) { 83 | address recoveredSigner = ecrecover(digest, v, r, s); 84 | if (recoveredSigner != address(0) && recoveredSigner == signer) { 85 | valid = true; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/marketplaces/blur-2.0/lib/Structs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.14; 3 | 4 | struct TakeAsk { 5 | Order[] orders; 6 | Exchange[] exchanges; 7 | FeeRate takerFee; 8 | bytes signatures; 9 | address tokenRecipient; 10 | } 11 | 12 | struct TakeAskSingle { 13 | Order order; 14 | Exchange exchange; 15 | FeeRate takerFee; 16 | bytes signature; 17 | address tokenRecipient; 18 | } 19 | 20 | struct TakeBid { 21 | Order[] orders; 22 | Exchange[] exchanges; 23 | FeeRate takerFee; 24 | bytes signatures; 25 | } 26 | 27 | struct TakeBidSingle { 28 | Order order; 29 | Exchange exchange; 30 | FeeRate takerFee; 31 | bytes signature; 32 | } 33 | 34 | enum AssetType { 35 | ERC721, 36 | ERC1155 37 | } 38 | 39 | enum OrderType { 40 | ASK, 41 | BID 42 | } 43 | 44 | struct Exchange { 45 | // Size: 0x80 46 | uint256 index; // 0x00 47 | bytes32[] proof; // 0x20 48 | Listing listing; // 0x40 49 | Taker taker; // 0x60 50 | } 51 | 52 | struct Listing { 53 | // Size: 0x80 54 | uint256 index; // 0x00 55 | uint256 tokenId; // 0x20 56 | uint256 amount; // 0x40 57 | uint256 price; // 0x60 58 | } 59 | 60 | struct Taker { 61 | // Size: 0x40 62 | uint256 tokenId; // 0x00 63 | uint256 amount; // 0x20 64 | } 65 | 66 | struct Order { 67 | // Size: 0x100 68 | address trader; // 0x00 69 | address collection; // 0x20 70 | bytes32 listingsRoot; // 0x40 71 | uint256 numberOfListings; // 0x60 72 | uint256 expirationTime; // 0x80 73 | AssetType assetType; // 0xa0 74 | FeeRate makerFee; // 0xc0 75 | uint256 salt; // 0xe0 76 | } 77 | 78 | struct Fees { 79 | // Size: 0x40 80 | FeeRate protocolFee; // 0x00 81 | FeeRate takerFee; // 0x20 82 | } 83 | 84 | struct FeeRate { 85 | // Size: 0x40 86 | address recipient; // 0x00 87 | uint16 rate; // 0x20 88 | } 89 | -------------------------------------------------------------------------------- /src/marketplaces/blur/interfaces/IBlurExchange.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import { Input, Execution } from "../lib/OrderStructs.sol"; 5 | 6 | interface IBlurExchange { 7 | function open() external; 8 | 9 | function execute(Input calldata sell, Input calldata buy) external payable; 10 | 11 | function bulkExecute(Execution[] calldata executions) external payable; 12 | } 13 | -------------------------------------------------------------------------------- /src/marketplaces/blur/lib/BlurTypeHashes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./OrderStructs.sol"; 5 | 6 | contract BlurTypeHashes { 7 | bytes32 public constant DOMAIN_SEPARATOR = 8 | keccak256( 9 | abi.encode( 10 | keccak256( 11 | "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" 12 | ), 13 | keccak256("Blur Exchange"), 14 | keccak256("1.0"), // for versionId = 1 15 | 1, 16 | 0x000000000000Ad05Ccc4F10045630fb830B95127 // mainnet Blur exchange address 17 | ) 18 | ); 19 | 20 | // function _hashToSign(bytes32 orderHash) 21 | // internal 22 | // view 23 | // returns (bytes32 hash) 24 | // { 25 | // return keccak256(abi.encodePacked( 26 | // "\x19\x01", 27 | // DOMAIN_SEPARATOR, 28 | // orderHash 29 | // )); 30 | // } 31 | 32 | bytes32 public constant ORDER_TYPEHASH = 33 | keccak256( 34 | "Order(address trader,uint8 side,address matchingPolicy,address collection,uint256 tokenId,uint256 amount,address paymentToken,uint256 price,uint256 listingTime,uint256 expirationTime,Fee[] fees,uint256 salt,bytes extraParams,uint256 nonce)Fee(uint16 rate,address recipient)" 35 | ); 36 | 37 | bytes32 public constant FEE_TYPEHASH = 38 | keccak256("Fee(uint16 rate,address recipient)"); 39 | 40 | function _hashOrder(Order memory order, uint256 nonce) 41 | internal 42 | pure 43 | returns (bytes32) 44 | { 45 | return 46 | keccak256( 47 | bytes.concat( 48 | abi.encode( 49 | ORDER_TYPEHASH, 50 | order.trader, 51 | order.side, 52 | order.matchingPolicy, 53 | order.collection, 54 | order.tokenId, 55 | order.amount, 56 | order.paymentToken, 57 | order.price, 58 | order.listingTime, 59 | order.expirationTime, 60 | _packFees(order.fees), 61 | order.salt, 62 | keccak256(order.extraParams) 63 | ), 64 | abi.encode(nonce) 65 | ) 66 | ); 67 | } 68 | 69 | function _packFees(Fee[] memory fees) internal pure returns (bytes32) { 70 | bytes32[] memory feeHashes = new bytes32[](fees.length); 71 | for (uint256 i = 0; i < fees.length; i++) { 72 | feeHashes[i] = _hashFee(fees[i]); 73 | } 74 | return keccak256(abi.encodePacked(feeHashes)); 75 | } 76 | 77 | function _hashFee(Fee memory fee) internal pure returns (bytes32) { 78 | return keccak256(abi.encode(FEE_TYPEHASH, fee.rate, fee.recipient)); 79 | } 80 | 81 | // function _deriveOrderDigest( 82 | // Order memory order 83 | // ) internal pure returns (bytes32) { 84 | // bytes32 orderHash = keccak256( 85 | // abi.encode( 86 | // order.trader, 87 | // order.side, 88 | // order.matchingPolicy, 89 | // order.collection, 90 | // order.tokenId, 91 | // order.amount, 92 | // order.paymentToken, 93 | // order.price, 94 | // order.listingTime, 95 | // order.expirationTime, 96 | // order.fees.length, 97 | // order.fees, 98 | // order.salt, 99 | // order.extraParams 100 | // ) 101 | // ); 102 | // return 103 | // keccak256( 104 | // abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, orderHash) 105 | // ); 106 | // } 107 | } 108 | -------------------------------------------------------------------------------- /src/marketplaces/blur/lib/OrderStructs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | enum Side { 5 | Buy, 6 | Sell 7 | } 8 | 9 | enum SignatureVersion { 10 | Single, 11 | Bulk 12 | } 13 | 14 | enum AssetType { 15 | ERC721, 16 | ERC1155 17 | } 18 | 19 | struct Fee { 20 | uint16 rate; 21 | address payable recipient; 22 | } 23 | 24 | struct Order { 25 | address trader; 26 | Side side; 27 | address matchingPolicy; 28 | address collection; 29 | uint256 tokenId; 30 | uint256 amount; 31 | address paymentToken; 32 | uint256 price; 33 | uint256 listingTime; 34 | /* Order expiration timestamp - 0 for oracle cancellations. */ 35 | uint256 expirationTime; 36 | Fee[] fees; 37 | uint256 salt; 38 | bytes extraParams; 39 | } 40 | 41 | struct Input { 42 | Order order; 43 | uint8 v; 44 | bytes32 r; 45 | bytes32 s; 46 | bytes extraSignature; 47 | SignatureVersion signatureVersion; 48 | uint256 blockNumber; 49 | } 50 | 51 | struct Execution { 52 | Input sell; 53 | Input buy; 54 | } 55 | -------------------------------------------------------------------------------- /src/marketplaces/foundation/FoundationConfig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | pragma solidity >=0.8.7; 3 | 4 | import { BaseMarketConfig } from "../../BaseMarketConfig.sol"; 5 | import { IFoundation } from "./interfaces/IFoundation.sol"; 6 | import { TestCallParameters, TestOrderContext, TestOrderPayload, TestItem721, TestItem1155, TestItem20 } from "../../Types.sol"; 7 | 8 | contract FoundationConfig is BaseMarketConfig { 9 | function name() external pure override returns (string memory) { 10 | return "Foundation"; 11 | } 12 | 13 | function market() public pure override returns (address) { 14 | return address(foundation); 15 | } 16 | 17 | IFoundation internal constant foundation = 18 | IFoundation(0xcDA72070E455bb31C7690a170224Ce43623d0B6f); 19 | 20 | function beforeAllPrepareMarketplace(address, address) external override { 21 | // ERC-20 n/a but currently required by the test suite 22 | buyerNftApprovalTarget = sellerNftApprovalTarget = buyerErc20ApprovalTarget = sellerErc20ApprovalTarget = address( 23 | foundation 24 | ); 25 | } 26 | 27 | function getPayload_BuyOfferedERC721WithEther( 28 | TestOrderContext calldata context, 29 | TestItem721 calldata nft, 30 | uint256 ethAmount 31 | ) external pure override returns (TestOrderPayload memory execution) { 32 | if (!context.listOnChain) { 33 | _notImplemented(); 34 | } 35 | 36 | execution.submitOrder = TestCallParameters( 37 | address(foundation), 38 | 0, 39 | abi.encodeWithSelector( 40 | IFoundation.setBuyPrice.selector, 41 | nft.token, 42 | nft.identifier, 43 | ethAmount 44 | ) 45 | ); 46 | execution.executeOrder = TestCallParameters( 47 | address(foundation), 48 | ethAmount, 49 | abi.encodeWithSelector( 50 | IFoundation.buyV2.selector, 51 | nft.token, 52 | nft.identifier, 53 | ethAmount, 54 | address(0) 55 | ) 56 | ); 57 | } 58 | 59 | function getPayload_BuyOfferedERC721WithEtherOneFeeRecipient( 60 | TestOrderContext calldata context, 61 | TestItem721 memory nft, 62 | uint256 priceEthAmount, 63 | address feeRecipient, 64 | uint256 /* feeEthAmount */ 65 | ) external pure override returns (TestOrderPayload memory execution) { 66 | if (!context.listOnChain) { 67 | _notImplemented(); 68 | } 69 | 70 | execution.submitOrder = TestCallParameters( 71 | address(foundation), 72 | 0, 73 | abi.encodeWithSelector( 74 | IFoundation.setBuyPrice.selector, 75 | nft.token, 76 | nft.identifier, 77 | priceEthAmount 78 | ) 79 | ); 80 | execution.executeOrder = TestCallParameters( 81 | address(foundation), 82 | priceEthAmount, 83 | abi.encodeWithSelector( 84 | IFoundation.buyV2.selector, 85 | nft.token, 86 | nft.identifier, 87 | priceEthAmount, 88 | feeRecipient 89 | ) 90 | ); 91 | } 92 | 93 | function getPayload_BuyOfferedERC721WithEtherTwoFeeRecipient( 94 | TestOrderContext calldata context, 95 | TestItem721 memory, /* nft */ 96 | uint256, /* priceEthAmount */ 97 | address, /* feeRecipient1 */ 98 | uint256, /* feeEthAmount1 */ 99 | address, /* feeRecipient2 */ 100 | uint256 /* feeEthAmount2 */ 101 | ) 102 | external 103 | pure 104 | override 105 | returns ( 106 | TestOrderPayload memory /* execution */ 107 | ) 108 | { 109 | if (!context.listOnChain) { 110 | _notImplemented(); 111 | } 112 | 113 | // TODO: pending sell referrer support 114 | _notImplemented(); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/marketplaces/foundation/interfaces/IFoundation.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | interface IFoundation { 6 | function setBuyPrice( 7 | address nftContract, 8 | uint256 tokenId, 9 | uint256 price 10 | ) external; 11 | 12 | function buyV2( 13 | address nftContract, 14 | uint256 tokenId, 15 | uint256 maxPrice, 16 | address payable buyReferrer 17 | ) external payable; 18 | } 19 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare-v2/interfaces/ILooksRareProtocol.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | // Libraries 5 | import { OrderStructs } from "../lib/OrderStructs.sol"; 6 | 7 | /** 8 | * @title ILooksRareProtocol 9 | * @author LooksRare protocol team (👀,💎) 10 | */ 11 | interface ILooksRareProtocol { 12 | /** 13 | * @notice This struct contains an order nonce's invalidation status 14 | * and the order hash that triggered the status change. 15 | * @param orderHash Maker order hash 16 | * @param orderNonce Order nonce 17 | * @param isNonceInvalidated Whether this transaction invalidated the maker user's order nonce at the protocol level 18 | */ 19 | struct NonceInvalidationParameters { 20 | bytes32 orderHash; 21 | uint256 orderNonce; 22 | bool isNonceInvalidated; 23 | } 24 | 25 | /** 26 | * @notice It is emitted when there is an affiliate fee paid. 27 | * @param affiliate Affiliate address 28 | * @param currency Address of the currency 29 | * @param affiliateFee Affiliate fee (in the currency) 30 | */ 31 | event AffiliatePayment( 32 | address affiliate, 33 | address currency, 34 | uint256 affiliateFee 35 | ); 36 | 37 | /** 38 | * @notice It is emitted if there is a change in the domain separator. 39 | */ 40 | event NewDomainSeparator(); 41 | 42 | /** 43 | * @notice It is emitted when there is a new gas limit for a ETH transfer (before it is wrapped to WETH). 44 | * @param gasLimitETHTransfer Gas limit for an ETH transfer 45 | */ 46 | event NewGasLimitETHTransfer(uint256 gasLimitETHTransfer); 47 | 48 | /** 49 | * @notice It is emitted when a taker ask transaction is completed. 50 | * @param nonceInvalidationParameters Struct about nonce invalidation parameters 51 | * @param askUser Address of the ask user 52 | * @param bidUser Address of the bid user 53 | * @param strategyId Id of the strategy 54 | * @param currency Address of the currency 55 | * @param collection Address of the collection 56 | * @param itemIds Array of item ids 57 | * @param amounts Array of amounts (for item ids) 58 | * @param feeRecipients Array of fee recipients 59 | * feeRecipients[0] User who receives the proceeds of the sale (it can be the taker ask user or different) 60 | * feeRecipients[1] Creator fee recipient (if none, address(0)) 61 | * @param feeAmounts Array of fee amounts 62 | * feeAmounts[0] Fee amount for the user receiving sale proceeds 63 | * feeAmounts[1] Creator fee amount 64 | * feeAmounts[2] Protocol fee amount prior to adjustment for a potential affiliate payment 65 | */ 66 | event TakerAsk( 67 | NonceInvalidationParameters nonceInvalidationParameters, 68 | address askUser, // taker (initiates the transaction) 69 | address bidUser, // maker (receives the NFT) 70 | uint256 strategyId, 71 | address currency, 72 | address collection, 73 | uint256[] itemIds, 74 | uint256[] amounts, 75 | address[2] feeRecipients, 76 | uint256[3] feeAmounts 77 | ); 78 | 79 | /** 80 | * @notice It is emitted when a taker bid transaction is completed. 81 | * @param nonceInvalidationParameters Struct about nonce invalidation parameters 82 | * @param bidUser Address of the bid user 83 | * @param bidRecipient Address of the recipient of the bid 84 | * @param strategyId Id of the strategy 85 | * @param currency Address of the currency 86 | * @param collection Address of the collection 87 | * @param itemIds Array of item ids 88 | * @param amounts Array of amounts (for item ids) 89 | * @param feeRecipients Array of fee recipients 90 | * feeRecipients[0] User who receives the proceeds of the sale (it is the maker ask user) 91 | * feeRecipients[1] Creator fee recipient (if none, address(0)) 92 | * @param feeAmounts Array of fee amounts 93 | * feeAmounts[0] Fee amount for the user receiving sale proceeds 94 | * feeAmounts[1] Creator fee amount 95 | * feeAmounts[2] Protocol fee amount prior to adjustment for a potential affiliate payment 96 | */ 97 | event TakerBid( 98 | NonceInvalidationParameters nonceInvalidationParameters, 99 | address bidUser, // taker (initiates the transaction) 100 | address bidRecipient, // taker (receives the NFT) 101 | uint256 strategyId, 102 | address currency, 103 | address collection, 104 | uint256[] itemIds, 105 | uint256[] amounts, 106 | address[2] feeRecipients, 107 | uint256[3] feeAmounts 108 | ); 109 | 110 | /** 111 | * @notice It is returned if the gas limit for a standard ETH transfer is too low. 112 | */ 113 | error NewGasLimitETHTransferTooLow(); 114 | 115 | /** 116 | * @notice It is returned if the domain separator cannot be updated (i.e. the chainId is the same). 117 | */ 118 | error SameDomainSeparator(); 119 | 120 | /** 121 | * @notice It is returned if the domain separator should change. 122 | */ 123 | error ChainIdInvalid(); 124 | 125 | /** 126 | * @notice It is returned if the nonces are invalid. 127 | */ 128 | error NoncesInvalid(); 129 | 130 | /** 131 | * @notice This function allows a user to execute a taker ask (against a maker bid). 132 | * @param takerAsk Taker ask struct 133 | * @param makerBid Maker bid struct 134 | * @param makerSignature Maker signature 135 | * @param merkleTree Merkle tree struct (if the signature contains multiple maker orders) 136 | * @param affiliate Affiliate address 137 | */ 138 | function executeTakerAsk( 139 | OrderStructs.Taker calldata takerAsk, 140 | OrderStructs.Maker calldata makerBid, 141 | bytes calldata makerSignature, 142 | OrderStructs.MerkleTree calldata merkleTree, 143 | address affiliate 144 | ) external; 145 | 146 | /** 147 | * @notice This function allows a user to execute a taker bid (against a maker ask). 148 | * @param takerBid Taker bid struct 149 | * @param makerAsk Maker ask struct 150 | * @param makerSignature Maker signature 151 | * @param merkleTree Merkle tree struct (if the signature contains multiple maker orders) 152 | * @param affiliate Affiliate address 153 | */ 154 | function executeTakerBid( 155 | OrderStructs.Taker calldata takerBid, 156 | OrderStructs.Maker calldata makerAsk, 157 | bytes calldata makerSignature, 158 | OrderStructs.MerkleTree calldata merkleTree, 159 | address affiliate 160 | ) external payable; 161 | 162 | /** 163 | * @notice This function allows a user to batch buy with an array of taker bids (against an array of maker asks). 164 | * @param takerBids Array of taker bid structs 165 | * @param makerAsks Array of maker ask structs 166 | * @param makerSignatures Array of maker signatures 167 | * @param merkleTrees Array of merkle tree structs if the signature contains multiple maker orders 168 | * @param affiliate Affiliate address 169 | * @param isAtomic Whether the execution should be atomic 170 | * i.e. whether it should revert if 1 or more transactions fail 171 | */ 172 | function executeMultipleTakerBids( 173 | OrderStructs.Taker[] calldata takerBids, 174 | OrderStructs.Maker[] calldata makerAsks, 175 | bytes[] calldata makerSignatures, 176 | OrderStructs.MerkleTree[] calldata merkleTrees, 177 | address affiliate, 178 | bool isAtomic 179 | ) external payable; 180 | 181 | /** 182 | * @notice This function allows the owner to update the status of a currency. 183 | * @param currency Currency address (address(0) for ETH) 184 | * @param isAllowed Whether the currency should be allowed for trading 185 | * @dev Only callable by owner. 186 | */ 187 | function updateCurrencyStatus(address currency, bool isAllowed) external; 188 | 189 | /** 190 | * @notice This function allows the owner to update the protocol fee recipient. 191 | * @param newProtocolFeeRecipient New protocol fee recipient address 192 | * @dev Only callable by owner. 193 | */ 194 | function updateProtocolFeeRecipient(address newProtocolFeeRecipient) 195 | external; 196 | } 197 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare-v2/interfaces/ITransferManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | /** 5 | * @title ITransferManager 6 | * @author LooksRare protocol team (👀,💎) 7 | */ 8 | interface ITransferManager { 9 | /** 10 | * @notice This function allows an operator to be added for the shared transfer system. 11 | * Once the operator is allowed, users can grant NFT approvals to this operator. 12 | * @param operator Operator address to allow 13 | * @dev Only callable by owner. 14 | */ 15 | function allowOperator(address operator) external; 16 | 17 | /** 18 | * @notice This function allows a user to grant approvals for an array of operators. 19 | * Users cannot grant approvals if the operator is not allowed by this contract's owner. 20 | * @param operators Array of operator addresses 21 | * @dev Each operator address must be globally allowed to be approved. 22 | */ 23 | function grantApprovals(address[] calldata operators) external; 24 | } 25 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare-v2/lib/CollectionType.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | /** 5 | * @notice CollectionType is used in OrderStructs.Maker's collectionType to determine the collection type being traded. 6 | */ 7 | enum CollectionType { 8 | ERC721, 9 | ERC1155 10 | } 11 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare-v2/lib/LooksRareV2TypeHashes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import { OrderStructs } from "./OrderStructs.sol"; 5 | 6 | contract LooksRareV2TypeHashes { 7 | using OrderStructs for OrderStructs.Maker; 8 | 9 | bytes32 public constant DOMAIN_SEPARATOR = 10 | keccak256( 11 | abi.encode( 12 | 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f, // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") 13 | 0x9e6bc51ef68b436657c5fe7a273ea9121a02b234cc81ad1e04892649c9168c6a, // keccak256("LooksRareProtocol") 14 | 0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5, // keccak256(bytes("2")) 15 | 1, 16 | 0x0000000000E655fAe4d56241588680F86E3b2377 // mainnet LooksRare protocol address 17 | ) 18 | ); 19 | 20 | function _deriveOrderDigest(OrderStructs.Maker memory makerOrder) 21 | internal 22 | pure 23 | returns (bytes32) 24 | { 25 | bytes32 orderHash = makerOrder.hash(); 26 | return 27 | keccak256( 28 | abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, orderHash) 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare-v2/lib/OrderStructs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | // Enums 5 | import { CollectionType } from "./CollectionType.sol"; 6 | import { QuoteType } from "./QuoteType.sol"; 7 | 8 | /** 9 | * @title OrderStructs 10 | * @notice This library contains all order struct types for the LooksRare protocol (v2). 11 | * @author LooksRare protocol team (👀,💎) 12 | */ 13 | library OrderStructs { 14 | /** 15 | * 1. Maker struct 16 | */ 17 | 18 | /** 19 | * @notice Maker is the struct for a maker order. 20 | * @param quoteType Quote type (i.e. 0 = BID, 1 = ASK) 21 | * @param globalNonce Global user order nonce for maker orders 22 | * @param subsetNonce Subset nonce (shared across bid/ask maker orders) 23 | * @param orderNonce Order nonce (it can be shared across bid/ask maker orders) 24 | * @param strategyId Strategy id 25 | * @param collectionType Collection type (i.e. 0 = ERC721, 1 = ERC1155) 26 | * @param collection Collection address 27 | * @param currency Currency address (@dev address(0) = ETH) 28 | * @param signer Signer address 29 | * @param startTime Start timestamp 30 | * @param endTime End timestamp 31 | * @param price Minimum price for maker ask, maximum price for maker bid 32 | * @param itemIds Array of itemIds 33 | * @param amounts Array of amounts 34 | * @param additionalParameters Extra data specific for the order 35 | */ 36 | struct Maker { 37 | QuoteType quoteType; 38 | uint256 globalNonce; 39 | uint256 subsetNonce; 40 | uint256 orderNonce; 41 | uint256 strategyId; 42 | CollectionType collectionType; 43 | address collection; 44 | address currency; 45 | address signer; 46 | uint256 startTime; 47 | uint256 endTime; 48 | uint256 price; 49 | uint256[] itemIds; 50 | uint256[] amounts; 51 | bytes additionalParameters; 52 | } 53 | 54 | /** 55 | * 2. Taker struct 56 | */ 57 | 58 | /** 59 | * @notice Taker is the struct for a taker ask/bid order. It contains the parameters required for a direct purchase. 60 | * @dev Taker struct is matched against MakerAsk/MakerBid structs at the protocol level. 61 | * @param recipient Recipient address (to receive NFTs or non-fungible tokens) 62 | * @param additionalParameters Extra data specific for the order 63 | */ 64 | struct Taker { 65 | address recipient; 66 | bytes additionalParameters; 67 | } 68 | 69 | /** 70 | * 3. Merkle tree struct 71 | */ 72 | 73 | enum MerkleTreeNodePosition { 74 | Left, 75 | Right 76 | } 77 | 78 | /** 79 | * @notice MerkleTreeNode is a MerkleTree's node. 80 | * @param value It can be an order hash or a proof 81 | * @param position The node's position in its branch. 82 | * It can be left or right or none 83 | * (before the tree is sorted). 84 | */ 85 | struct MerkleTreeNode { 86 | bytes32 value; 87 | MerkleTreeNodePosition position; 88 | } 89 | 90 | /** 91 | * @notice MerkleTree is the struct for a merkle tree of order hashes. 92 | * @dev A Merkle tree can be computed with order hashes. 93 | * It can contain order hashes from both maker bid and maker ask structs. 94 | * @param root Merkle root 95 | * @param proof Array containing the merkle proof 96 | */ 97 | struct MerkleTree { 98 | bytes32 root; 99 | MerkleTreeNode[] proof; 100 | } 101 | 102 | /** 103 | * 4. Constants 104 | */ 105 | 106 | /** 107 | * @notice This is the type hash constant used to compute the maker order hash. 108 | */ 109 | bytes32 internal constant _MAKER_TYPEHASH = 110 | keccak256( 111 | "Maker(" 112 | "uint8 quoteType," 113 | "uint256 globalNonce," 114 | "uint256 subsetNonce," 115 | "uint256 orderNonce," 116 | "uint256 strategyId," 117 | "uint8 collectionType," 118 | "address collection," 119 | "address currency," 120 | "address signer," 121 | "uint256 startTime," 122 | "uint256 endTime," 123 | "uint256 price," 124 | "uint256[] itemIds," 125 | "uint256[] amounts," 126 | "bytes additionalParameters" 127 | ")" 128 | ); 129 | 130 | /** 131 | * 5. Hash functions 132 | */ 133 | 134 | /** 135 | * @notice This function is used to compute the order hash for a maker struct. 136 | * @param maker Maker order struct 137 | * @return makerHash Hash of the maker struct 138 | */ 139 | function hash(Maker memory maker) internal pure returns (bytes32) { 140 | // Encoding is done into two parts to avoid stack too deep issues 141 | return 142 | keccak256( 143 | bytes.concat( 144 | abi.encode( 145 | _MAKER_TYPEHASH, 146 | maker.quoteType, 147 | maker.globalNonce, 148 | maker.subsetNonce, 149 | maker.orderNonce, 150 | maker.strategyId, 151 | maker.collectionType, 152 | maker.collection, 153 | maker.currency 154 | ), 155 | abi.encode( 156 | maker.signer, 157 | maker.startTime, 158 | maker.endTime, 159 | maker.price, 160 | keccak256(abi.encodePacked(maker.itemIds)), 161 | keccak256(abi.encodePacked(maker.amounts)), 162 | keccak256(maker.additionalParameters) 163 | ) 164 | ) 165 | ); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare-v2/lib/QuoteType.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | /** 5 | * @notice QuoteType is used in OrderStructs.Maker's quoteType to determine whether the maker order is a bid or an ask. 6 | */ 7 | enum QuoteType { 8 | Bid, 9 | Ask 10 | } 11 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare/LooksRareConfig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import { LooksRareTypeHashes } from "./lib/LooksRareTypeHashes.sol"; 5 | import { OrderTypes } from "./lib/OrderTypes.sol"; 6 | import { ILooksRareExchange } from "./interfaces/ILooksRareExchange.sol"; 7 | import { ICurrencyManager } from "./interfaces/ICurrencyManager.sol"; 8 | import { BaseMarketConfig } from "../../BaseMarketConfig.sol"; 9 | import { TestCallParameters, TestOrderContext, TestOrderPayload, TestItem721, TestItem1155, TestItem20, SetupCall } from "../../Types.sol"; 10 | 11 | contract LooksRareConfig is BaseMarketConfig, LooksRareTypeHashes { 12 | function name() external pure override returns (string memory) { 13 | return "LooksRare"; 14 | } 15 | 16 | function market() public pure override returns (address) { 17 | return address(looksRare); 18 | } 19 | 20 | address internal constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; 21 | 22 | ILooksRareExchange internal constant looksRare = 23 | ILooksRareExchange(0x59728544B08AB483533076417FbBB2fD0B17CE3a); 24 | address internal constant looksRareOwner = 25 | 0xBfb6669Ef4C4c71ae6E722526B1B8d7d9ff9a019; 26 | 27 | address internal constant fixedPriceStrategy = 28 | 0x56244Bb70CbD3EA9Dc8007399F61dFC065190031; 29 | 30 | ICurrencyManager internal constant currencyManager = 31 | ICurrencyManager(0xC881ADdf409eE2C4b6bBc8B607c2C5CAFaB93d25); 32 | address internal constant currencyManagerOwner = 33 | 0xB624e4148ef395458D361547C9Fdb59B62a84bd2; 34 | 35 | /*////////////////////////////////////////////////////////////// 36 | Generic Helpers 37 | //////////////////////////////////////////////////////////////*/ 38 | 39 | function buildMakerOrder( 40 | bool isOrderAsk, 41 | address maker, 42 | address fungibleToken, 43 | uint256 fungibleAmount, 44 | address nftToken, 45 | uint256 nftAmount, 46 | uint256 nftTokenId 47 | ) internal view returns (OrderTypes.MakerOrder memory makerOrder) { 48 | makerOrder = OrderTypes.MakerOrder( 49 | isOrderAsk, 50 | maker, 51 | nftToken, 52 | fungibleAmount, 53 | nftTokenId, 54 | nftAmount, 55 | fixedPriceStrategy, 56 | fungibleToken, 57 | 0, 58 | block.timestamp, 59 | block.timestamp + 1, 60 | 0, 61 | "", 62 | 0, 63 | 0, 64 | 0 65 | ); 66 | (uint8 v, bytes32 r, bytes32 s) = _sign( 67 | maker, 68 | _deriveOrderDigest(makerOrder) 69 | ); 70 | makerOrder.v = v; 71 | makerOrder.r = r; 72 | makerOrder.s = s; 73 | } 74 | 75 | function buildTakerOrder( 76 | address taker, 77 | OrderTypes.MakerOrder memory makerOrder 78 | ) internal pure returns (OrderTypes.TakerOrder memory) { 79 | return 80 | OrderTypes.TakerOrder( 81 | !makerOrder.isOrderAsk, 82 | taker, 83 | makerOrder.price, 84 | makerOrder.tokenId, 85 | 0, 86 | "" 87 | ); 88 | } 89 | 90 | /*////////////////////////////////////////////////////////////// 91 | Setup 92 | //////////////////////////////////////////////////////////////*/ 93 | 94 | function beforeAllPrepareMarketplace(address, address) external override { 95 | buyerNftApprovalTarget = sellerNftApprovalTarget = 0xf42aa99F011A1fA7CDA90E5E98b277E306BcA83e; // ERC721 transfer manager 96 | buyerErc1155ApprovalTarget = sellerErc1155ApprovalTarget = 0xFED24eC7E22f573c2e08AEF55aA6797Ca2b3A051; // ERC1155 transfer manager 97 | buyerErc20ApprovalTarget = sellerErc20ApprovalTarget = address( 98 | looksRare 99 | ); 100 | } 101 | 102 | function beforeAllPrepareMarketplaceCall( 103 | address, 104 | address, 105 | address[] calldata erc20Tokens, 106 | address[] calldata 107 | ) external pure override returns (SetupCall[] memory) { 108 | SetupCall[] memory setupCalls = new SetupCall[](erc20Tokens.length + 1); 109 | for (uint256 i = 0; i < erc20Tokens.length; i++) { 110 | // Whitelist necessary ERC-20 tokens 111 | setupCalls[i] = SetupCall( 112 | currencyManagerOwner, 113 | address(currencyManager), 114 | abi.encodeWithSelector( 115 | ICurrencyManager.addCurrency.selector, 116 | erc20Tokens[i] 117 | ) 118 | ); 119 | } 120 | 121 | // Remove protocol fee 122 | setupCalls[erc20Tokens.length] = SetupCall( 123 | looksRareOwner, 124 | address(looksRare), 125 | abi.encodeWithSelector( 126 | ILooksRareExchange.updateProtocolFeeRecipient.selector, 127 | address(0) 128 | ) 129 | ); 130 | 131 | return setupCalls; 132 | } 133 | 134 | /*////////////////////////////////////////////////////////////// 135 | Test Payload Calls 136 | //////////////////////////////////////////////////////////////*/ 137 | 138 | function getPayload_BuyOfferedERC721WithEther( 139 | TestOrderContext calldata context, 140 | TestItem721 memory nft, 141 | uint256 ethAmount 142 | ) external view override returns (TestOrderPayload memory execution) { 143 | OrderTypes.MakerOrder memory makerOrder = buildMakerOrder( 144 | true, 145 | context.offerer, 146 | WETH, 147 | ethAmount, 148 | nft.token, 149 | 1, 150 | nft.identifier 151 | ); 152 | OrderTypes.TakerOrder memory takerOrder = buildTakerOrder( 153 | context.fulfiller, 154 | makerOrder 155 | ); 156 | 157 | if (context.listOnChain) { 158 | _notImplemented(); 159 | } 160 | execution.executeOrder = TestCallParameters( 161 | address(looksRare), 162 | ethAmount, 163 | abi.encodeWithSelector( 164 | ILooksRareExchange.matchAskWithTakerBidUsingETHAndWETH.selector, 165 | takerOrder, 166 | makerOrder 167 | ) 168 | ); 169 | } 170 | 171 | function getPayload_BuyOfferedERC1155WithEther( 172 | TestOrderContext calldata context, 173 | TestItem1155 calldata nft, 174 | uint256 ethAmount 175 | ) external view override returns (TestOrderPayload memory execution) { 176 | OrderTypes.MakerOrder memory makerOrder = buildMakerOrder( 177 | true, 178 | context.offerer, 179 | WETH, 180 | ethAmount, 181 | nft.token, 182 | nft.amount, 183 | nft.identifier 184 | ); 185 | OrderTypes.TakerOrder memory takerOrder = buildTakerOrder( 186 | context.fulfiller, 187 | makerOrder 188 | ); 189 | 190 | if (context.listOnChain) { 191 | _notImplemented(); 192 | } 193 | execution.executeOrder = TestCallParameters( 194 | address(looksRare), 195 | ethAmount, 196 | abi.encodeWithSelector( 197 | ILooksRareExchange.matchAskWithTakerBidUsingETHAndWETH.selector, 198 | takerOrder, 199 | makerOrder 200 | ) 201 | ); 202 | } 203 | 204 | function getPayload_BuyOfferedERC721WithERC20( 205 | TestOrderContext calldata context, 206 | TestItem721 calldata nft, 207 | TestItem20 calldata erc20 208 | ) external view override returns (TestOrderPayload memory execution) { 209 | OrderTypes.MakerOrder memory makerOrder = buildMakerOrder( 210 | true, 211 | context.offerer, 212 | erc20.token, 213 | erc20.amount, 214 | nft.token, 215 | 1, 216 | nft.identifier 217 | ); 218 | OrderTypes.TakerOrder memory takerOrder = buildTakerOrder( 219 | context.fulfiller, 220 | makerOrder 221 | ); 222 | 223 | if (context.listOnChain) { 224 | _notImplemented(); 225 | } 226 | 227 | execution.executeOrder = TestCallParameters( 228 | address(looksRare), 229 | 0, 230 | abi.encodeWithSelector( 231 | ILooksRareExchange.matchAskWithTakerBid.selector, 232 | takerOrder, 233 | makerOrder 234 | ) 235 | ); 236 | } 237 | 238 | function getPayload_BuyOfferedERC721WithWETH( 239 | TestOrderContext calldata context, 240 | TestItem721 calldata nft, 241 | TestItem20 calldata erc20 242 | ) external view override returns (TestOrderPayload memory execution) { 243 | OrderTypes.MakerOrder memory makerOrder = buildMakerOrder( 244 | true, 245 | context.offerer, 246 | erc20.token, 247 | erc20.amount, 248 | nft.token, 249 | 1, 250 | nft.identifier 251 | ); 252 | OrderTypes.TakerOrder memory takerOrder = buildTakerOrder( 253 | context.fulfiller, 254 | makerOrder 255 | ); 256 | 257 | if (context.listOnChain) { 258 | _notImplemented(); 259 | } 260 | 261 | execution.executeOrder = TestCallParameters( 262 | address(looksRare), 263 | 0, 264 | abi.encodeWithSelector( 265 | ILooksRareExchange.matchAskWithTakerBid.selector, 266 | takerOrder, 267 | makerOrder 268 | ) 269 | ); 270 | } 271 | 272 | function getPayload_BuyOfferedERC1155WithERC20( 273 | TestOrderContext calldata context, 274 | TestItem1155 calldata nft, 275 | TestItem20 calldata erc20 276 | ) external view override returns (TestOrderPayload memory execution) { 277 | OrderTypes.MakerOrder memory makerOrder = buildMakerOrder( 278 | true, 279 | context.offerer, 280 | erc20.token, 281 | erc20.amount, 282 | nft.token, 283 | nft.amount, 284 | nft.identifier 285 | ); 286 | OrderTypes.TakerOrder memory takerOrder = buildTakerOrder( 287 | context.fulfiller, 288 | makerOrder 289 | ); 290 | 291 | if (context.listOnChain) { 292 | _notImplemented(); 293 | } 294 | 295 | execution.executeOrder = TestCallParameters( 296 | address(looksRare), 297 | 0, 298 | abi.encodeWithSelector( 299 | ILooksRareExchange.matchAskWithTakerBid.selector, 300 | takerOrder, 301 | makerOrder 302 | ) 303 | ); 304 | } 305 | 306 | function getPayload_BuyOfferedERC20WithERC721( 307 | TestOrderContext calldata context, 308 | TestItem20 calldata erc20, 309 | TestItem721 calldata nft 310 | ) external view override returns (TestOrderPayload memory execution) { 311 | OrderTypes.MakerOrder memory makerOrder = buildMakerOrder( 312 | false, 313 | context.offerer, 314 | erc20.token, 315 | erc20.amount, 316 | nft.token, 317 | 1, 318 | nft.identifier 319 | ); 320 | OrderTypes.TakerOrder memory takerOrder = buildTakerOrder( 321 | context.fulfiller, 322 | makerOrder 323 | ); 324 | 325 | if (context.listOnChain) { 326 | _notImplemented(); 327 | } 328 | 329 | execution.executeOrder = TestCallParameters( 330 | address(looksRare), 331 | 0, 332 | abi.encodeWithSelector( 333 | ILooksRareExchange.matchBidWithTakerAsk.selector, 334 | takerOrder, 335 | makerOrder 336 | ) 337 | ); 338 | } 339 | 340 | function getPayload_BuyOfferedWETHWithERC721( 341 | TestOrderContext calldata context, 342 | TestItem20 calldata erc20, 343 | TestItem721 calldata nft 344 | ) external view override returns (TestOrderPayload memory execution) { 345 | OrderTypes.MakerOrder memory makerOrder = buildMakerOrder( 346 | false, 347 | context.offerer, 348 | erc20.token, 349 | erc20.amount, 350 | nft.token, 351 | 1, 352 | nft.identifier 353 | ); 354 | OrderTypes.TakerOrder memory takerOrder = buildTakerOrder( 355 | context.fulfiller, 356 | makerOrder 357 | ); 358 | 359 | if (context.listOnChain) { 360 | _notImplemented(); 361 | } 362 | 363 | execution.executeOrder = TestCallParameters( 364 | address(looksRare), 365 | 0, 366 | abi.encodeWithSelector( 367 | ILooksRareExchange.matchBidWithTakerAsk.selector, 368 | takerOrder, 369 | makerOrder 370 | ) 371 | ); 372 | } 373 | 374 | function getPayload_BuyOfferedERC20WithERC1155( 375 | TestOrderContext calldata context, 376 | TestItem20 calldata erc20, 377 | TestItem1155 calldata nft 378 | ) external view override returns (TestOrderPayload memory execution) { 379 | OrderTypes.MakerOrder memory makerOrder = buildMakerOrder( 380 | false, 381 | context.offerer, 382 | erc20.token, 383 | erc20.amount, 384 | nft.token, 385 | nft.amount, 386 | nft.identifier 387 | ); 388 | OrderTypes.TakerOrder memory takerOrder = buildTakerOrder( 389 | context.fulfiller, 390 | makerOrder 391 | ); 392 | 393 | if (context.listOnChain) { 394 | _notImplemented(); 395 | } 396 | 397 | execution.executeOrder = TestCallParameters( 398 | address(looksRare), 399 | 0, 400 | abi.encodeWithSelector( 401 | ILooksRareExchange.matchBidWithTakerAsk.selector, 402 | takerOrder, 403 | makerOrder 404 | ) 405 | ); 406 | } 407 | } 408 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare/interfaces/ICurrencyManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | interface ICurrencyManager { 5 | function addCurrency(address currency) external; 6 | 7 | function removeCurrency(address currency) external; 8 | 9 | function isCurrencyWhitelisted(address currency) 10 | external 11 | view 12 | returns (bool); 13 | 14 | function viewWhitelistedCurrencies(uint256 cursor, uint256 size) 15 | external 16 | view 17 | returns (address[] memory, uint256); 18 | 19 | function viewCountWhitelistedCurrencies() external view returns (uint256); 20 | } 21 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare/interfaces/ILooksRareExchange.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import { OrderTypes } from "../lib/OrderTypes.sol"; 5 | 6 | interface ILooksRareExchange { 7 | function matchAskWithTakerBidUsingETHAndWETH( 8 | OrderTypes.TakerOrder calldata takerBid, 9 | OrderTypes.MakerOrder calldata makerAsk 10 | ) external payable; 11 | 12 | function matchAskWithTakerBid( 13 | OrderTypes.TakerOrder calldata takerBid, 14 | OrderTypes.MakerOrder calldata makerAsk 15 | ) external; 16 | 17 | function matchBidWithTakerAsk( 18 | OrderTypes.TakerOrder calldata takerAsk, 19 | OrderTypes.MakerOrder calldata makerBid 20 | ) external; 21 | 22 | function updateProtocolFeeRecipient(address _protocolFeeRecipient) external; 23 | } 24 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare/lib/LooksRareTypeHashes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import { OrderTypes } from "./OrderTypes.sol"; 5 | 6 | contract LooksRareTypeHashes { 7 | using OrderTypes for OrderTypes.MakerOrder; 8 | using OrderTypes for OrderTypes.TakerOrder; 9 | 10 | bytes32 public constant DOMAIN_SEPARATOR = 11 | keccak256( 12 | abi.encode( 13 | 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f, // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") 14 | 0xda9101ba92939daf4bb2e18cd5f942363b9297fbc3232c9dd964abb1fb70ed71, // keccak256("LooksRareExchange") 15 | 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6, // keccak256(bytes("1")) for versionId = 1 16 | 1, 17 | 0x59728544B08AB483533076417FbBB2fD0B17CE3a // mainnet LooksRare exchange address 18 | ) 19 | ); 20 | 21 | function _deriveOrderDigest(OrderTypes.MakerOrder memory makerOrder) 22 | internal 23 | pure 24 | returns (bytes32) 25 | { 26 | bytes32 orderHash = makerOrder.hash(); 27 | return 28 | keccak256( 29 | abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, orderHash) 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/marketplaces/looksRare/lib/OrderTypes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | /** 5 | * @title OrderTypes 6 | * @notice This library contains order types for the LooksRare exchange. 7 | */ 8 | library OrderTypes { 9 | // keccak256("MakerOrder(bool isOrderAsk,address signer,address collection,uint256 price,uint256 tokenId,uint256 amount,address strategy,address currency,uint256 nonce,uint256 startTime,uint256 endTime,uint256 minPercentageToAsk,bytes params)") 10 | bytes32 internal constant MAKER_ORDER_HASH = 11 | 0x40261ade532fa1d2c7293df30aaadb9b3c616fae525a0b56d3d411c841a85028; 12 | 13 | struct MakerOrder { 14 | bool isOrderAsk; // true --> ask / false --> bid 15 | address signer; // signer of the maker order 16 | address collection; // collection address 17 | uint256 price; // price (used as ) 18 | uint256 tokenId; // id of the token 19 | uint256 amount; // amount of tokens to sell/purchase (must be 1 for ERC721, 1+ for ERC1155) 20 | address strategy; // strategy for trade execution (e.g., DutchAuction, StandardSaleForFixedPrice) 21 | address currency; // currency (e.g., WETH) 22 | uint256 nonce; // order nonce (must be unique unless new maker order is meant to override existing one e.g., lower ask price) 23 | uint256 startTime; // startTime in timestamp 24 | uint256 endTime; // endTime in timestamp 25 | uint256 minPercentageToAsk; // slippage protection (9000 --> 90% of the final price must return to ask) 26 | bytes params; // additional parameters 27 | uint8 v; // v: parameter (27 or 28) 28 | bytes32 r; // r: parameter 29 | bytes32 s; // s: parameter 30 | } 31 | 32 | struct TakerOrder { 33 | bool isOrderAsk; // true --> ask / false --> bid 34 | address taker; // msg.sender 35 | uint256 price; // final price for the purchase 36 | uint256 tokenId; 37 | uint256 minPercentageToAsk; // // slippage protection (9000 --> 90% of the final price must return to ask) 38 | bytes params; // other params (e.g., tokenId) 39 | } 40 | 41 | function hash(MakerOrder memory makerOrder) 42 | internal 43 | pure 44 | returns (bytes32) 45 | { 46 | return 47 | keccak256( 48 | abi.encode( 49 | MAKER_ORDER_HASH, 50 | makerOrder.isOrderAsk, 51 | makerOrder.signer, 52 | makerOrder.collection, 53 | makerOrder.price, 54 | makerOrder.tokenId, 55 | makerOrder.amount, 56 | makerOrder.strategy, 57 | makerOrder.currency, 58 | makerOrder.nonce, 59 | makerOrder.startTime, 60 | makerOrder.endTime, 61 | makerOrder.minPercentageToAsk, 62 | keccak256(makerOrder.params) 63 | ) 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/marketplaces/seaport-1.1/lib/ConsiderationEnums.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.7; 3 | 4 | // prettier-ignore 5 | enum OrderType { 6 | // 0: no partial fills, anyone can execute 7 | FULL_OPEN, 8 | 9 | // 1: partial fills supported, anyone can execute 10 | PARTIAL_OPEN, 11 | 12 | // 2: no partial fills, only offerer or zone can execute 13 | FULL_RESTRICTED, 14 | 15 | // 3: partial fills supported, only offerer or zone can execute 16 | PARTIAL_RESTRICTED 17 | } 18 | 19 | // prettier-ignore 20 | enum BasicOrderType { 21 | // 0: no partial fills, anyone can execute 22 | ETH_TO_ERC721_FULL_OPEN, 23 | 24 | // 1: partial fills supported, anyone can execute 25 | ETH_TO_ERC721_PARTIAL_OPEN, 26 | 27 | // 2: no partial fills, only offerer or zone can execute 28 | ETH_TO_ERC721_FULL_RESTRICTED, 29 | 30 | // 3: partial fills supported, only offerer or zone can execute 31 | ETH_TO_ERC721_PARTIAL_RESTRICTED, 32 | 33 | // 4: no partial fills, anyone can execute 34 | ETH_TO_ERC1155_FULL_OPEN, 35 | 36 | // 5: partial fills supported, anyone can execute 37 | ETH_TO_ERC1155_PARTIAL_OPEN, 38 | 39 | // 6: no partial fills, only offerer or zone can execute 40 | ETH_TO_ERC1155_FULL_RESTRICTED, 41 | 42 | // 7: partial fills supported, only offerer or zone can execute 43 | ETH_TO_ERC1155_PARTIAL_RESTRICTED, 44 | 45 | // 8: no partial fills, anyone can execute 46 | ERC20_TO_ERC721_FULL_OPEN, 47 | 48 | // 9: partial fills supported, anyone can execute 49 | ERC20_TO_ERC721_PARTIAL_OPEN, 50 | 51 | // 10: no partial fills, only offerer or zone can execute 52 | ERC20_TO_ERC721_FULL_RESTRICTED, 53 | 54 | // 11: partial fills supported, only offerer or zone can execute 55 | ERC20_TO_ERC721_PARTIAL_RESTRICTED, 56 | 57 | // 12: no partial fills, anyone can execute 58 | ERC20_TO_ERC1155_FULL_OPEN, 59 | 60 | // 13: partial fills supported, anyone can execute 61 | ERC20_TO_ERC1155_PARTIAL_OPEN, 62 | 63 | // 14: no partial fills, only offerer or zone can execute 64 | ERC20_TO_ERC1155_FULL_RESTRICTED, 65 | 66 | // 15: partial fills supported, only offerer or zone can execute 67 | ERC20_TO_ERC1155_PARTIAL_RESTRICTED, 68 | 69 | // 16: no partial fills, anyone can execute 70 | ERC721_TO_ERC20_FULL_OPEN, 71 | 72 | // 17: partial fills supported, anyone can execute 73 | ERC721_TO_ERC20_PARTIAL_OPEN, 74 | 75 | // 18: no partial fills, only offerer or zone can execute 76 | ERC721_TO_ERC20_FULL_RESTRICTED, 77 | 78 | // 19: partial fills supported, only offerer or zone can execute 79 | ERC721_TO_ERC20_PARTIAL_RESTRICTED, 80 | 81 | // 20: no partial fills, anyone can execute 82 | ERC1155_TO_ERC20_FULL_OPEN, 83 | 84 | // 21: partial fills supported, anyone can execute 85 | ERC1155_TO_ERC20_PARTIAL_OPEN, 86 | 87 | // 22: no partial fills, only offerer or zone can execute 88 | ERC1155_TO_ERC20_FULL_RESTRICTED, 89 | 90 | // 23: partial fills supported, only offerer or zone can execute 91 | ERC1155_TO_ERC20_PARTIAL_RESTRICTED 92 | } 93 | 94 | // prettier-ignore 95 | enum BasicOrderRouteType { 96 | // 0: provide Ether (or other native token) to receive offered ERC721 item. 97 | ETH_TO_ERC721, 98 | 99 | // 1: provide Ether (or other native token) to receive offered ERC1155 item. 100 | ETH_TO_ERC1155, 101 | 102 | // 2: provide ERC20 item to receive offered ERC721 item. 103 | ERC20_TO_ERC721, 104 | 105 | // 3: provide ERC20 item to receive offered ERC1155 item. 106 | ERC20_TO_ERC1155, 107 | 108 | // 4: provide ERC721 item to receive offered ERC20 item. 109 | ERC721_TO_ERC20, 110 | 111 | // 5: provide ERC1155 item to receive offered ERC20 item. 112 | ERC1155_TO_ERC20 113 | } 114 | 115 | // prettier-ignore 116 | enum ItemType { 117 | // 0: ETH on mainnet, MATIC on polygon, etc. 118 | NATIVE, 119 | 120 | // 1: ERC20 items (ERC777 and ERC20 analogues could also technically work) 121 | ERC20, 122 | 123 | // 2: ERC721 items 124 | ERC721, 125 | 126 | // 3: ERC1155 items 127 | ERC1155, 128 | 129 | // 4: ERC721 items where a number of tokenIds are supported 130 | ERC721_WITH_CRITERIA, 131 | 132 | // 5: ERC1155 items where a number of ids are supported 133 | ERC1155_WITH_CRITERIA 134 | } 135 | 136 | // prettier-ignore 137 | enum Side { 138 | // 0: Items that can be spent 139 | OFFER, 140 | 141 | // 1: Items that must be received 142 | CONSIDERATION 143 | } 144 | -------------------------------------------------------------------------------- /src/marketplaces/seaport-1.1/lib/ConsiderationStructs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.7; 3 | 4 | // prettier-ignore 5 | import { 6 | OrderType, 7 | BasicOrderType, 8 | ItemType, 9 | Side, 10 | BasicOrderRouteType 11 | } from "./ConsiderationEnums.sol"; 12 | 13 | /** 14 | * @dev An order contains eleven components: an offerer, a zone (or account that 15 | * can cancel the order or restrict who can fulfill the order depending on 16 | * the type), the order type (specifying partial fill support as well as 17 | * restricted order status), the start and end time, a hash that will be 18 | * provided to the zone when validating restricted orders, a salt, a key 19 | * corresponding to a given conduit, a counter, and an arbitrary number of 20 | * offer items that can be spent along with consideration items that must 21 | * be received by their respective recipient. 22 | */ 23 | struct OrderComponents { 24 | address offerer; 25 | address zone; 26 | OfferItem[] offer; 27 | ConsiderationItem[] consideration; 28 | OrderType orderType; 29 | uint256 startTime; 30 | uint256 endTime; 31 | bytes32 zoneHash; 32 | uint256 salt; 33 | bytes32 conduitKey; 34 | uint256 counter; 35 | } 36 | 37 | /** 38 | * @dev An offer item has five components: an item type (ETH or other native 39 | * tokens, ERC20, ERC721, and ERC1155, as well as criteria-based ERC721 and 40 | * ERC1155), a token address, a dual-purpose "identifierOrCriteria" 41 | * component that will either represent a tokenId or a merkle root 42 | * depending on the item type, and a start and end amount that support 43 | * increasing or decreasing amounts over the duration of the respective 44 | * order. 45 | */ 46 | struct OfferItem { 47 | ItemType itemType; 48 | address token; 49 | uint256 identifierOrCriteria; 50 | uint256 startAmount; 51 | uint256 endAmount; 52 | } 53 | 54 | /** 55 | * @dev A consideration item has the same five components as an offer item and 56 | * an additional sixth component designating the required recipient of the 57 | * item. 58 | */ 59 | struct ConsiderationItem { 60 | ItemType itemType; 61 | address token; 62 | uint256 identifierOrCriteria; 63 | uint256 startAmount; 64 | uint256 endAmount; 65 | address payable recipient; 66 | } 67 | 68 | /** 69 | * @dev A spent item is translated from a utilized offer item and has four 70 | * components: an item type (ETH or other native tokens, ERC20, ERC721, and 71 | * ERC1155), a token address, a tokenId, and an amount. 72 | */ 73 | struct SpentItem { 74 | ItemType itemType; 75 | address token; 76 | uint256 identifier; 77 | uint256 amount; 78 | } 79 | 80 | /** 81 | * @dev A received item is translated from a utilized consideration item and has 82 | * the same four components as a spent item, as well as an additional fifth 83 | * component designating the required recipient of the item. 84 | */ 85 | struct ReceivedItem { 86 | ItemType itemType; 87 | address token; 88 | uint256 identifier; 89 | uint256 amount; 90 | address payable recipient; 91 | } 92 | 93 | /** 94 | * @dev For basic orders involving ETH / native / ERC20 <=> ERC721 / ERC1155 95 | * matching, a group of six functions may be called that only requires a 96 | * subset of the usual order arguments. Note the use of a "basicOrderType" 97 | * enum; this represents both the usual order type as well as the "route" 98 | * of the basic order (a simple derivation function for the basic order 99 | * type is `basicOrderType = orderType + (4 * basicOrderRoute)`.) 100 | */ 101 | struct BasicOrderParameters { 102 | // calldata offset 103 | address considerationToken; // 0x24 104 | uint256 considerationIdentifier; // 0x44 105 | uint256 considerationAmount; // 0x64 106 | address payable offerer; // 0x84 107 | address zone; // 0xa4 108 | address offerToken; // 0xc4 109 | uint256 offerIdentifier; // 0xe4 110 | uint256 offerAmount; // 0x104 111 | BasicOrderType basicOrderType; // 0x124 112 | uint256 startTime; // 0x144 113 | uint256 endTime; // 0x164 114 | bytes32 zoneHash; // 0x184 115 | uint256 salt; // 0x1a4 116 | bytes32 offererConduitKey; // 0x1c4 117 | bytes32 fulfillerConduitKey; // 0x1e4 118 | uint256 totalOriginalAdditionalRecipients; // 0x204 119 | AdditionalRecipient[] additionalRecipients; // 0x224 120 | bytes signature; // 0x244 121 | // Total length, excluding dynamic array data: 0x264 (580) 122 | } 123 | 124 | /** 125 | * @dev Basic orders can supply any number of additional recipients, with the 126 | * implied assumption that they are supplied from the offered ETH (or other 127 | * native token) or ERC20 token for the order. 128 | */ 129 | struct AdditionalRecipient { 130 | uint256 amount; 131 | address payable recipient; 132 | } 133 | 134 | /** 135 | * @dev The full set of order components, with the exception of the counter, 136 | * must be supplied when fulfilling more sophisticated orders or groups of 137 | * orders. The total number of original consideration items must also be 138 | * supplied, as the caller may specify additional consideration items. 139 | */ 140 | struct OrderParameters { 141 | address offerer; // 0x00 142 | address zone; // 0x20 143 | OfferItem[] offer; // 0x40 144 | ConsiderationItem[] consideration; // 0x60 145 | OrderType orderType; // 0x80 146 | uint256 startTime; // 0xa0 147 | uint256 endTime; // 0xc0 148 | bytes32 zoneHash; // 0xe0 149 | uint256 salt; // 0x100 150 | bytes32 conduitKey; // 0x120 151 | uint256 totalOriginalConsiderationItems; // 0x140 152 | // offer.length // 0x160 153 | } 154 | 155 | /** 156 | * @dev Orders require a signature in addition to the other order parameters. 157 | */ 158 | struct Order { 159 | OrderParameters parameters; 160 | bytes signature; 161 | } 162 | 163 | /** 164 | * @dev Advanced orders include a numerator (i.e. a fraction to attempt to fill) 165 | * and a denominator (the total size of the order) in addition to the 166 | * signature and other order parameters. It also supports an optional field 167 | * for supplying extra data; this data will be included in a staticcall to 168 | * `isValidOrderIncludingExtraData` on the zone for the order if the order 169 | * type is restricted and the offerer or zone are not the caller. 170 | */ 171 | struct AdvancedOrder { 172 | OrderParameters parameters; 173 | uint120 numerator; 174 | uint120 denominator; 175 | bytes signature; 176 | bytes extraData; 177 | } 178 | 179 | /** 180 | * @dev Orders can be validated (either explicitly via `validate`, or as a 181 | * consequence of a full or partial fill), specifically cancelled (they can 182 | * also be cancelled in bulk via incrementing a per-zone counter), and 183 | * partially or fully filled (with the fraction filled represented by a 184 | * numerator and denominator). 185 | */ 186 | struct OrderStatus { 187 | bool isValidated; 188 | bool isCancelled; 189 | uint120 numerator; 190 | uint120 denominator; 191 | } 192 | 193 | /** 194 | * @dev A criteria resolver specifies an order, side (offer vs. consideration), 195 | * and item index. It then provides a chosen identifier (i.e. tokenId) 196 | * alongside a merkle proof demonstrating the identifier meets the required 197 | * criteria. 198 | */ 199 | struct CriteriaResolver { 200 | uint256 orderIndex; 201 | Side side; 202 | uint256 index; 203 | uint256 identifier; 204 | bytes32[] criteriaProof; 205 | } 206 | 207 | /** 208 | * @dev A fulfillment is applied to a group of orders. It decrements a series of 209 | * offer and consideration items, then generates a single execution 210 | * element. A given fulfillment can be applied to as many offer and 211 | * consideration items as desired, but must contain at least one offer and 212 | * at least one consideration that match. The fulfillment must also remain 213 | * consistent on all key parameters across all offer items (same offerer, 214 | * token, type, tokenId, and conduit preference) as well as across all 215 | * consideration items (token, type, tokenId, and recipient). 216 | */ 217 | struct Fulfillment { 218 | FulfillmentComponent[] offerComponents; 219 | FulfillmentComponent[] considerationComponents; 220 | } 221 | 222 | /** 223 | * @dev Each fulfillment component contains one index referencing a specific 224 | * order and another referencing a specific offer or consideration item. 225 | */ 226 | struct FulfillmentComponent { 227 | uint256 orderIndex; 228 | uint256 itemIndex; 229 | } 230 | 231 | /** 232 | * @dev An execution is triggered once all consideration items have been zeroed 233 | * out. It sends the item in question from the offerer to the item's 234 | * recipient, optionally sourcing approvals from either this contract 235 | * directly or from the offerer's chosen conduit if one is specified. An 236 | * execution is not provided as an argument, but rather is derived via 237 | * orders, criteria resolvers, and fulfillments (where the total number of 238 | * executions will be less than or equal to the total number of indicated 239 | * fulfillments) and returned as part of `matchOrders`. 240 | */ 241 | struct Execution { 242 | ReceivedItem item; 243 | address offerer; 244 | bytes32 conduitKey; 245 | } 246 | -------------------------------------------------------------------------------- /src/marketplaces/seaport-1.1/lib/ConsiderationTypeHashes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.7; 3 | 4 | import "./ConsiderationStructs.sol"; 5 | 6 | uint256 constant EIP712_Order_size = 0x180; 7 | uint256 constant EIP712_OfferItem_size = 0xc0; 8 | uint256 constant EIP712_ConsiderationItem_size = 0xe0; 9 | uint256 constant EIP712_DomainSeparator_offset = 0x02; 10 | uint256 constant EIP712_OrderHash_offset = 0x22; 11 | uint256 constant EIP712_DigestPayload_size = 0x42; 12 | uint256 constant EIP_712_PREFIX = ( 13 | 0x1901000000000000000000000000000000000000000000000000000000000000 14 | ); 15 | 16 | contract ConsiderationTypeHashes { 17 | bytes32 internal immutable _NAME_HASH; 18 | bytes32 internal immutable _VERSION_HASH; 19 | bytes32 internal immutable _EIP_712_DOMAIN_TYPEHASH; 20 | bytes32 internal immutable _OFFER_ITEM_TYPEHASH; 21 | bytes32 internal immutable _CONSIDERATION_ITEM_TYPEHASH; 22 | bytes32 internal immutable _ORDER_TYPEHASH; 23 | bytes32 internal immutable _DOMAIN_SEPARATOR; 24 | address internal constant seaportAddress = 25 | address(0x00000000006c3852cbEf3e08E8dF289169EdE581); 26 | 27 | constructor() { 28 | // Derive hash of the name of the contract. 29 | _NAME_HASH = keccak256(bytes("Seaport")); 30 | 31 | // Derive hash of the version string of the contract. 32 | _VERSION_HASH = keccak256(bytes("1.1")); 33 | 34 | bytes memory offerItemTypeString = abi.encodePacked( 35 | "OfferItem(", 36 | "uint8 itemType,", 37 | "address token,", 38 | "uint256 identifierOrCriteria,", 39 | "uint256 startAmount,", 40 | "uint256 endAmount", 41 | ")" 42 | ); 43 | 44 | // Construct the ConsiderationItem type string. 45 | // prettier-ignore 46 | bytes memory considerationItemTypeString = abi.encodePacked( 47 | "ConsiderationItem(", 48 | "uint8 itemType,", 49 | "address token,", 50 | "uint256 identifierOrCriteria,", 51 | "uint256 startAmount,", 52 | "uint256 endAmount,", 53 | "address recipient", 54 | ")" 55 | ); 56 | 57 | // Construct the OrderComponents type string, not including the above. 58 | // prettier-ignore 59 | bytes memory orderComponentsPartialTypeString = abi.encodePacked( 60 | "OrderComponents(", 61 | "address offerer,", 62 | "address zone,", 63 | "OfferItem[] offer,", 64 | "ConsiderationItem[] consideration,", 65 | "uint8 orderType,", 66 | "uint256 startTime,", 67 | "uint256 endTime,", 68 | "bytes32 zoneHash,", 69 | "uint256 salt,", 70 | "bytes32 conduitKey,", 71 | "uint256 counter", 72 | ")" 73 | ); 74 | // Derive the OfferItem type hash using the corresponding type string. 75 | bytes32 offerItemTypehash = keccak256(offerItemTypeString); 76 | 77 | // Derive ConsiderationItem type hash using corresponding type string. 78 | bytes32 considerationItemTypehash = keccak256( 79 | considerationItemTypeString 80 | ); 81 | 82 | // Construct the primary EIP-712 domain type string. 83 | // prettier-ignore 84 | _EIP_712_DOMAIN_TYPEHASH = keccak256( 85 | abi.encodePacked( 86 | "EIP712Domain(", 87 | "string name,", 88 | "string version,", 89 | "uint256 chainId,", 90 | "address verifyingContract", 91 | ")" 92 | ) 93 | ); 94 | 95 | _OFFER_ITEM_TYPEHASH = offerItemTypehash; 96 | _CONSIDERATION_ITEM_TYPEHASH = considerationItemTypehash; 97 | 98 | // Derive OrderItem type hash via combination of relevant type strings. 99 | _ORDER_TYPEHASH = keccak256( 100 | abi.encodePacked( 101 | orderComponentsPartialTypeString, 102 | considerationItemTypeString, 103 | offerItemTypeString 104 | ) 105 | ); 106 | 107 | _DOMAIN_SEPARATOR = _deriveDomainSeparator(); 108 | } 109 | 110 | /** 111 | * @dev Internal view function to derive the EIP-712 domain separator. 112 | * 113 | * @return The derived domain separator. 114 | */ 115 | function _deriveDomainSeparator() internal view returns (bytes32) { 116 | // prettier-ignore 117 | return keccak256( 118 | abi.encode( 119 | _EIP_712_DOMAIN_TYPEHASH, 120 | _NAME_HASH, 121 | _VERSION_HASH, 122 | 1, 123 | seaportAddress 124 | ) 125 | ); 126 | } 127 | 128 | /** 129 | * @dev Internal pure function to efficiently derive an digest to sign for 130 | * an order in accordance with EIP-712. 131 | * 132 | * @param orderHash The order hash. 133 | * 134 | * @return value The hash. 135 | */ 136 | function _deriveEIP712Digest(bytes32 orderHash) 137 | internal 138 | view 139 | returns (bytes32 value) 140 | { 141 | bytes32 domainSeparator = _DOMAIN_SEPARATOR; 142 | // Leverage scratch space to perform an efficient hash. 143 | assembly { 144 | // Place the EIP-712 prefix at the start of scratch space. 145 | mstore(0, EIP_712_PREFIX) 146 | 147 | // Place the domain separator in the next region of scratch space. 148 | mstore(EIP712_DomainSeparator_offset, domainSeparator) 149 | 150 | // Place the order hash in scratch space, spilling into the first 151 | // two bytes of the free memory pointer — this should never be set 152 | // as memory cannot be expanded to that size, and will be zeroed out 153 | // after the hash is performed. 154 | mstore(EIP712_OrderHash_offset, orderHash) 155 | 156 | // Hash the relevant region (65 bytes). 157 | value := keccak256(0, EIP712_DigestPayload_size) 158 | 159 | // Clear out the dirtied bits in the memory pointer. 160 | mstore(EIP712_OrderHash_offset, 0) 161 | } 162 | } 163 | 164 | /** 165 | * @dev Internal view function to derive the EIP-712 hash for an offer item. 166 | * 167 | * @param offerItem The offered item to hash. 168 | * 169 | * @return The hash. 170 | */ 171 | function _hashOfferItem(OfferItem memory offerItem) 172 | internal 173 | view 174 | returns (bytes32) 175 | { 176 | return 177 | keccak256( 178 | abi.encode( 179 | _OFFER_ITEM_TYPEHASH, 180 | offerItem.itemType, 181 | offerItem.token, 182 | offerItem.identifierOrCriteria, 183 | offerItem.startAmount, 184 | offerItem.endAmount 185 | ) 186 | ); 187 | } 188 | 189 | /** 190 | * @dev Internal view function to derive the EIP-712 hash for a consideration item. 191 | * 192 | * @param considerationItem The consideration item to hash. 193 | * 194 | * @return The hash. 195 | */ 196 | function _hashConsiderationItem(ConsiderationItem memory considerationItem) 197 | internal 198 | view 199 | returns (bytes32) 200 | { 201 | return 202 | keccak256( 203 | abi.encode( 204 | _CONSIDERATION_ITEM_TYPEHASH, 205 | considerationItem.itemType, 206 | considerationItem.token, 207 | considerationItem.identifierOrCriteria, 208 | considerationItem.startAmount, 209 | considerationItem.endAmount, 210 | considerationItem.recipient 211 | ) 212 | ); 213 | } 214 | 215 | /** 216 | * @dev Internal view function to derive the order hash for a given order. 217 | * Note that only the original consideration items are included in the 218 | * order hash, as additional consideration items may be supplied by the 219 | * caller. 220 | * 221 | * @param orderParameters The parameters of the order to hash. 222 | * @param counter The counter of the order to hash. 223 | * 224 | * @return orderHash The hash. 225 | */ 226 | function _deriveOrderHash( 227 | OrderParameters memory orderParameters, 228 | uint256 counter 229 | ) internal view returns (bytes32 orderHash) { 230 | // Designate new memory regions for offer and consideration item hashes. 231 | bytes32[] memory offerHashes = new bytes32[]( 232 | orderParameters.offer.length 233 | ); 234 | bytes32[] memory considerationHashes = new bytes32[]( 235 | orderParameters.totalOriginalConsiderationItems 236 | ); 237 | 238 | // Iterate over each offer on the order. 239 | for (uint256 i = 0; i < orderParameters.offer.length; ++i) { 240 | // Hash the offer and place the result into memory. 241 | offerHashes[i] = _hashOfferItem(orderParameters.offer[i]); 242 | } 243 | 244 | // Iterate over each consideration on the order. 245 | for ( 246 | uint256 i = 0; 247 | i < orderParameters.totalOriginalConsiderationItems; 248 | ++i 249 | ) { 250 | // Hash the consideration and place the result into memory. 251 | considerationHashes[i] = _hashConsiderationItem( 252 | orderParameters.consideration[i] 253 | ); 254 | } 255 | 256 | // Derive and return the order hash as specified by EIP-712. 257 | 258 | return 259 | keccak256( 260 | abi.encode( 261 | _ORDER_TYPEHASH, 262 | orderParameters.offerer, 263 | orderParameters.zone, 264 | keccak256(abi.encodePacked(offerHashes)), 265 | keccak256(abi.encodePacked(considerationHashes)), 266 | orderParameters.orderType, 267 | orderParameters.startTime, 268 | orderParameters.endTime, 269 | orderParameters.zoneHash, 270 | orderParameters.salt, 271 | orderParameters.conduitKey, 272 | counter 273 | ) 274 | ); 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /src/marketplaces/seaport-1.5/lib/ConsiderationEnums.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.7; 3 | 4 | // prettier-ignore 5 | enum OrderType { 6 | // 0: no partial fills, anyone can execute 7 | FULL_OPEN, 8 | 9 | // 1: partial fills supported, anyone can execute 10 | PARTIAL_OPEN, 11 | 12 | // 2: no partial fills, only offerer or zone can execute 13 | FULL_RESTRICTED, 14 | 15 | // 3: partial fills supported, only offerer or zone can execute 16 | PARTIAL_RESTRICTED 17 | } 18 | 19 | // prettier-ignore 20 | enum BasicOrderType { 21 | // 0: no partial fills, anyone can execute 22 | ETH_TO_ERC721_FULL_OPEN, 23 | 24 | // 1: partial fills supported, anyone can execute 25 | ETH_TO_ERC721_PARTIAL_OPEN, 26 | 27 | // 2: no partial fills, only offerer or zone can execute 28 | ETH_TO_ERC721_FULL_RESTRICTED, 29 | 30 | // 3: partial fills supported, only offerer or zone can execute 31 | ETH_TO_ERC721_PARTIAL_RESTRICTED, 32 | 33 | // 4: no partial fills, anyone can execute 34 | ETH_TO_ERC1155_FULL_OPEN, 35 | 36 | // 5: partial fills supported, anyone can execute 37 | ETH_TO_ERC1155_PARTIAL_OPEN, 38 | 39 | // 6: no partial fills, only offerer or zone can execute 40 | ETH_TO_ERC1155_FULL_RESTRICTED, 41 | 42 | // 7: partial fills supported, only offerer or zone can execute 43 | ETH_TO_ERC1155_PARTIAL_RESTRICTED, 44 | 45 | // 8: no partial fills, anyone can execute 46 | ERC20_TO_ERC721_FULL_OPEN, 47 | 48 | // 9: partial fills supported, anyone can execute 49 | ERC20_TO_ERC721_PARTIAL_OPEN, 50 | 51 | // 10: no partial fills, only offerer or zone can execute 52 | ERC20_TO_ERC721_FULL_RESTRICTED, 53 | 54 | // 11: partial fills supported, only offerer or zone can execute 55 | ERC20_TO_ERC721_PARTIAL_RESTRICTED, 56 | 57 | // 12: no partial fills, anyone can execute 58 | ERC20_TO_ERC1155_FULL_OPEN, 59 | 60 | // 13: partial fills supported, anyone can execute 61 | ERC20_TO_ERC1155_PARTIAL_OPEN, 62 | 63 | // 14: no partial fills, only offerer or zone can execute 64 | ERC20_TO_ERC1155_FULL_RESTRICTED, 65 | 66 | // 15: partial fills supported, only offerer or zone can execute 67 | ERC20_TO_ERC1155_PARTIAL_RESTRICTED, 68 | 69 | // 16: no partial fills, anyone can execute 70 | ERC721_TO_ERC20_FULL_OPEN, 71 | 72 | // 17: partial fills supported, anyone can execute 73 | ERC721_TO_ERC20_PARTIAL_OPEN, 74 | 75 | // 18: no partial fills, only offerer or zone can execute 76 | ERC721_TO_ERC20_FULL_RESTRICTED, 77 | 78 | // 19: partial fills supported, only offerer or zone can execute 79 | ERC721_TO_ERC20_PARTIAL_RESTRICTED, 80 | 81 | // 20: no partial fills, anyone can execute 82 | ERC1155_TO_ERC20_FULL_OPEN, 83 | 84 | // 21: partial fills supported, anyone can execute 85 | ERC1155_TO_ERC20_PARTIAL_OPEN, 86 | 87 | // 22: no partial fills, only offerer or zone can execute 88 | ERC1155_TO_ERC20_FULL_RESTRICTED, 89 | 90 | // 23: partial fills supported, only offerer or zone can execute 91 | ERC1155_TO_ERC20_PARTIAL_RESTRICTED 92 | } 93 | 94 | // prettier-ignore 95 | enum BasicOrderRouteType { 96 | // 0: provide Ether (or other native token) to receive offered ERC721 item. 97 | ETH_TO_ERC721, 98 | 99 | // 1: provide Ether (or other native token) to receive offered ERC1155 item. 100 | ETH_TO_ERC1155, 101 | 102 | // 2: provide ERC20 item to receive offered ERC721 item. 103 | ERC20_TO_ERC721, 104 | 105 | // 3: provide ERC20 item to receive offered ERC1155 item. 106 | ERC20_TO_ERC1155, 107 | 108 | // 4: provide ERC721 item to receive offered ERC20 item. 109 | ERC721_TO_ERC20, 110 | 111 | // 5: provide ERC1155 item to receive offered ERC20 item. 112 | ERC1155_TO_ERC20 113 | } 114 | 115 | // prettier-ignore 116 | enum ItemType { 117 | // 0: ETH on mainnet, MATIC on polygon, etc. 118 | NATIVE, 119 | 120 | // 1: ERC20 items (ERC777 and ERC20 analogues could also technically work) 121 | ERC20, 122 | 123 | // 2: ERC721 items 124 | ERC721, 125 | 126 | // 3: ERC1155 items 127 | ERC1155, 128 | 129 | // 4: ERC721 items where a number of tokenIds are supported 130 | ERC721_WITH_CRITERIA, 131 | 132 | // 5: ERC1155 items where a number of ids are supported 133 | ERC1155_WITH_CRITERIA 134 | } 135 | 136 | // prettier-ignore 137 | enum Side { 138 | // 0: Items that can be spent 139 | OFFER, 140 | 141 | // 1: Items that must be received 142 | CONSIDERATION 143 | } 144 | -------------------------------------------------------------------------------- /src/marketplaces/seaport-1.5/lib/ConsiderationStructs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.7; 3 | 4 | // prettier-ignore 5 | import { 6 | OrderType, 7 | BasicOrderType, 8 | ItemType, 9 | Side, 10 | BasicOrderRouteType 11 | } from "./ConsiderationEnums.sol"; 12 | 13 | /** 14 | * @dev An order contains eleven components: an offerer, a zone (or account that 15 | * can cancel the order or restrict who can fulfill the order depending on 16 | * the type), the order type (specifying partial fill support as well as 17 | * restricted order status), the start and end time, a hash that will be 18 | * provided to the zone when validating restricted orders, a salt, a key 19 | * corresponding to a given conduit, a counter, and an arbitrary number of 20 | * offer items that can be spent along with consideration items that must 21 | * be received by their respective recipient. 22 | */ 23 | struct OrderComponents { 24 | address offerer; 25 | address zone; 26 | OfferItem[] offer; 27 | ConsiderationItem[] consideration; 28 | OrderType orderType; 29 | uint256 startTime; 30 | uint256 endTime; 31 | bytes32 zoneHash; 32 | uint256 salt; 33 | bytes32 conduitKey; 34 | uint256 counter; 35 | } 36 | 37 | /** 38 | * @dev An offer item has five components: an item type (ETH or other native 39 | * tokens, ERC20, ERC721, and ERC1155, as well as criteria-based ERC721 and 40 | * ERC1155), a token address, a dual-purpose "identifierOrCriteria" 41 | * component that will either represent a tokenId or a merkle root 42 | * depending on the item type, and a start and end amount that support 43 | * increasing or decreasing amounts over the duration of the respective 44 | * order. 45 | */ 46 | struct OfferItem { 47 | ItemType itemType; 48 | address token; 49 | uint256 identifierOrCriteria; 50 | uint256 startAmount; 51 | uint256 endAmount; 52 | } 53 | 54 | /** 55 | * @dev A consideration item has the same five components as an offer item and 56 | * an additional sixth component designating the required recipient of the 57 | * item. 58 | */ 59 | struct ConsiderationItem { 60 | ItemType itemType; 61 | address token; 62 | uint256 identifierOrCriteria; 63 | uint256 startAmount; 64 | uint256 endAmount; 65 | address payable recipient; 66 | } 67 | 68 | /** 69 | * @dev A spent item is translated from a utilized offer item and has four 70 | * components: an item type (ETH or other native tokens, ERC20, ERC721, and 71 | * ERC1155), a token address, a tokenId, and an amount. 72 | */ 73 | struct SpentItem { 74 | ItemType itemType; 75 | address token; 76 | uint256 identifier; 77 | uint256 amount; 78 | } 79 | 80 | /** 81 | * @dev A received item is translated from a utilized consideration item and has 82 | * the same four components as a spent item, as well as an additional fifth 83 | * component designating the required recipient of the item. 84 | */ 85 | struct ReceivedItem { 86 | ItemType itemType; 87 | address token; 88 | uint256 identifier; 89 | uint256 amount; 90 | address payable recipient; 91 | } 92 | 93 | /** 94 | * @dev For basic orders involving ETH / native / ERC20 <=> ERC721 / ERC1155 95 | * matching, a group of six functions may be called that only requires a 96 | * subset of the usual order arguments. Note the use of a "basicOrderType" 97 | * enum; this represents both the usual order type as well as the "route" 98 | * of the basic order (a simple derivation function for the basic order 99 | * type is `basicOrderType = orderType + (4 * basicOrderRoute)`.) 100 | */ 101 | struct BasicOrderParameters { 102 | // calldata offset 103 | address considerationToken; // 0x24 104 | uint256 considerationIdentifier; // 0x44 105 | uint256 considerationAmount; // 0x64 106 | address payable offerer; // 0x84 107 | address zone; // 0xa4 108 | address offerToken; // 0xc4 109 | uint256 offerIdentifier; // 0xe4 110 | uint256 offerAmount; // 0x104 111 | BasicOrderType basicOrderType; // 0x124 112 | uint256 startTime; // 0x144 113 | uint256 endTime; // 0x164 114 | bytes32 zoneHash; // 0x184 115 | uint256 salt; // 0x1a4 116 | bytes32 offererConduitKey; // 0x1c4 117 | bytes32 fulfillerConduitKey; // 0x1e4 118 | uint256 totalOriginalAdditionalRecipients; // 0x204 119 | AdditionalRecipient[] additionalRecipients; // 0x224 120 | bytes signature; // 0x244 121 | // Total length, excluding dynamic array data: 0x264 (580) 122 | } 123 | 124 | /** 125 | * @dev Basic orders can supply any number of additional recipients, with the 126 | * implied assumption that they are supplied from the offered ETH (or other 127 | * native token) or ERC20 token for the order. 128 | */ 129 | struct AdditionalRecipient { 130 | uint256 amount; 131 | address payable recipient; 132 | } 133 | 134 | /** 135 | * @dev The full set of order components, with the exception of the counter, 136 | * must be supplied when fulfilling more sophisticated orders or groups of 137 | * orders. The total number of original consideration items must also be 138 | * supplied, as the caller may specify additional consideration items. 139 | */ 140 | struct OrderParameters { 141 | address offerer; // 0x00 142 | address zone; // 0x20 143 | OfferItem[] offer; // 0x40 144 | ConsiderationItem[] consideration; // 0x60 145 | OrderType orderType; // 0x80 146 | uint256 startTime; // 0xa0 147 | uint256 endTime; // 0xc0 148 | bytes32 zoneHash; // 0xe0 149 | uint256 salt; // 0x100 150 | bytes32 conduitKey; // 0x120 151 | uint256 totalOriginalConsiderationItems; // 0x140 152 | // offer.length // 0x160 153 | } 154 | 155 | /** 156 | * @dev Orders require a signature in addition to the other order parameters. 157 | */ 158 | struct Order { 159 | OrderParameters parameters; 160 | bytes signature; 161 | } 162 | 163 | /** 164 | * @dev Advanced orders include a numerator (i.e. a fraction to attempt to fill) 165 | * and a denominator (the total size of the order) in addition to the 166 | * signature and other order parameters. It also supports an optional field 167 | * for supplying extra data; this data will be included in a staticcall to 168 | * `isValidOrderIncludingExtraData` on the zone for the order if the order 169 | * type is restricted and the offerer or zone are not the caller. 170 | */ 171 | struct AdvancedOrder { 172 | OrderParameters parameters; 173 | uint120 numerator; 174 | uint120 denominator; 175 | bytes signature; 176 | bytes extraData; 177 | } 178 | 179 | /** 180 | * @dev Orders can be validated (either explicitly via `validate`, or as a 181 | * consequence of a full or partial fill), specifically cancelled (they can 182 | * also be cancelled in bulk via incrementing a per-zone counter), and 183 | * partially or fully filled (with the fraction filled represented by a 184 | * numerator and denominator). 185 | */ 186 | struct OrderStatus { 187 | bool isValidated; 188 | bool isCancelled; 189 | uint120 numerator; 190 | uint120 denominator; 191 | } 192 | 193 | /** 194 | * @dev A criteria resolver specifies an order, side (offer vs. consideration), 195 | * and item index. It then provides a chosen identifier (i.e. tokenId) 196 | * alongside a merkle proof demonstrating the identifier meets the required 197 | * criteria. 198 | */ 199 | struct CriteriaResolver { 200 | uint256 orderIndex; 201 | Side side; 202 | uint256 index; 203 | uint256 identifier; 204 | bytes32[] criteriaProof; 205 | } 206 | 207 | /** 208 | * @dev A fulfillment is applied to a group of orders. It decrements a series of 209 | * offer and consideration items, then generates a single execution 210 | * element. A given fulfillment can be applied to as many offer and 211 | * consideration items as desired, but must contain at least one offer and 212 | * at least one consideration that match. The fulfillment must also remain 213 | * consistent on all key parameters across all offer items (same offerer, 214 | * token, type, tokenId, and conduit preference) as well as across all 215 | * consideration items (token, type, tokenId, and recipient). 216 | */ 217 | struct Fulfillment { 218 | FulfillmentComponent[] offerComponents; 219 | FulfillmentComponent[] considerationComponents; 220 | } 221 | 222 | /** 223 | * @dev Each fulfillment component contains one index referencing a specific 224 | * order and another referencing a specific offer or consideration item. 225 | */ 226 | struct FulfillmentComponent { 227 | uint256 orderIndex; 228 | uint256 itemIndex; 229 | } 230 | 231 | /** 232 | * @dev An execution is triggered once all consideration items have been zeroed 233 | * out. It sends the item in question from the offerer to the item's 234 | * recipient, optionally sourcing approvals from either this contract 235 | * directly or from the offerer's chosen conduit if one is specified. An 236 | * execution is not provided as an argument, but rather is derived via 237 | * orders, criteria resolvers, and fulfillments (where the total number of 238 | * executions will be less than or equal to the total number of indicated 239 | * fulfillments) and returned as part of `matchOrders`. 240 | */ 241 | struct Execution { 242 | ReceivedItem item; 243 | address offerer; 244 | bytes32 conduitKey; 245 | } 246 | -------------------------------------------------------------------------------- /src/marketplaces/seaport-1.5/lib/ConsiderationTypeHashes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.7; 3 | 4 | import "./ConsiderationStructs.sol"; 5 | 6 | uint256 constant EIP712_Order_size = 0x180; 7 | uint256 constant EIP712_OfferItem_size = 0xc0; 8 | uint256 constant EIP712_ConsiderationItem_size = 0xe0; 9 | uint256 constant EIP712_DomainSeparator_offset = 0x02; 10 | uint256 constant EIP712_OrderHash_offset = 0x22; 11 | uint256 constant EIP712_DigestPayload_size = 0x42; 12 | uint256 constant EIP_712_PREFIX = ( 13 | 0x1901000000000000000000000000000000000000000000000000000000000000 14 | ); 15 | 16 | contract ConsiderationTypeHashes { 17 | bytes32 internal immutable _NAME_HASH; 18 | bytes32 internal immutable _VERSION_HASH; 19 | bytes32 internal immutable _EIP_712_DOMAIN_TYPEHASH; 20 | bytes32 internal immutable _OFFER_ITEM_TYPEHASH; 21 | bytes32 internal immutable _CONSIDERATION_ITEM_TYPEHASH; 22 | bytes32 internal immutable _ORDER_TYPEHASH; 23 | bytes32 internal immutable _DOMAIN_SEPARATOR; 24 | address internal constant seaportAddress = 25 | address(0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC); 26 | 27 | constructor() { 28 | // Derive hash of the name of the contract. 29 | _NAME_HASH = keccak256(bytes("Seaport")); 30 | 31 | // Derive hash of the version string of the contract. 32 | _VERSION_HASH = keccak256(bytes("1.5")); 33 | 34 | bytes memory offerItemTypeString = abi.encodePacked( 35 | "OfferItem(", 36 | "uint8 itemType,", 37 | "address token,", 38 | "uint256 identifierOrCriteria,", 39 | "uint256 startAmount,", 40 | "uint256 endAmount", 41 | ")" 42 | ); 43 | 44 | // Construct the ConsiderationItem type string. 45 | // prettier-ignore 46 | bytes memory considerationItemTypeString = abi.encodePacked( 47 | "ConsiderationItem(", 48 | "uint8 itemType,", 49 | "address token,", 50 | "uint256 identifierOrCriteria,", 51 | "uint256 startAmount,", 52 | "uint256 endAmount,", 53 | "address recipient", 54 | ")" 55 | ); 56 | 57 | // Construct the OrderComponents type string, not including the above. 58 | // prettier-ignore 59 | bytes memory orderComponentsPartialTypeString = abi.encodePacked( 60 | "OrderComponents(", 61 | "address offerer,", 62 | "address zone,", 63 | "OfferItem[] offer,", 64 | "ConsiderationItem[] consideration,", 65 | "uint8 orderType,", 66 | "uint256 startTime,", 67 | "uint256 endTime,", 68 | "bytes32 zoneHash,", 69 | "uint256 salt,", 70 | "bytes32 conduitKey,", 71 | "uint256 counter", 72 | ")" 73 | ); 74 | // Derive the OfferItem type hash using the corresponding type string. 75 | bytes32 offerItemTypehash = keccak256(offerItemTypeString); 76 | 77 | // Derive ConsiderationItem type hash using corresponding type string. 78 | bytes32 considerationItemTypehash = keccak256( 79 | considerationItemTypeString 80 | ); 81 | 82 | // Construct the primary EIP-712 domain type string. 83 | // prettier-ignore 84 | _EIP_712_DOMAIN_TYPEHASH = keccak256( 85 | abi.encodePacked( 86 | "EIP712Domain(", 87 | "string name,", 88 | "string version,", 89 | "uint256 chainId,", 90 | "address verifyingContract", 91 | ")" 92 | ) 93 | ); 94 | 95 | _OFFER_ITEM_TYPEHASH = offerItemTypehash; 96 | _CONSIDERATION_ITEM_TYPEHASH = considerationItemTypehash; 97 | 98 | // Derive OrderItem type hash via combination of relevant type strings. 99 | _ORDER_TYPEHASH = keccak256( 100 | abi.encodePacked( 101 | orderComponentsPartialTypeString, 102 | considerationItemTypeString, 103 | offerItemTypeString 104 | ) 105 | ); 106 | 107 | _DOMAIN_SEPARATOR = _deriveDomainSeparator(); 108 | } 109 | 110 | /** 111 | * @dev Internal view function to derive the EIP-712 domain separator. 112 | * 113 | * @return The derived domain separator. 114 | */ 115 | function _deriveDomainSeparator() internal view returns (bytes32) { 116 | // prettier-ignore 117 | return keccak256( 118 | abi.encode( 119 | _EIP_712_DOMAIN_TYPEHASH, 120 | _NAME_HASH, 121 | _VERSION_HASH, 122 | 1, 123 | seaportAddress 124 | ) 125 | ); 126 | } 127 | 128 | /** 129 | * @dev Internal pure function to efficiently derive an digest to sign for 130 | * an order in accordance with EIP-712. 131 | * 132 | * @param orderHash The order hash. 133 | * 134 | * @return value The hash. 135 | */ 136 | function _deriveEIP712Digest(bytes32 orderHash) 137 | internal 138 | view 139 | returns (bytes32 value) 140 | { 141 | bytes32 domainSeparator = _DOMAIN_SEPARATOR; 142 | // Leverage scratch space to perform an efficient hash. 143 | assembly { 144 | // Place the EIP-712 prefix at the start of scratch space. 145 | mstore(0, EIP_712_PREFIX) 146 | 147 | // Place the domain separator in the next region of scratch space. 148 | mstore(EIP712_DomainSeparator_offset, domainSeparator) 149 | 150 | // Place the order hash in scratch space, spilling into the first 151 | // two bytes of the free memory pointer — this should never be set 152 | // as memory cannot be expanded to that size, and will be zeroed out 153 | // after the hash is performed. 154 | mstore(EIP712_OrderHash_offset, orderHash) 155 | 156 | // Hash the relevant region (65 bytes). 157 | value := keccak256(0, EIP712_DigestPayload_size) 158 | 159 | // Clear out the dirtied bits in the memory pointer. 160 | mstore(EIP712_OrderHash_offset, 0) 161 | } 162 | } 163 | 164 | /** 165 | * @dev Internal view function to derive the EIP-712 hash for an offer item. 166 | * 167 | * @param offerItem The offered item to hash. 168 | * 169 | * @return The hash. 170 | */ 171 | function _hashOfferItem(OfferItem memory offerItem) 172 | internal 173 | view 174 | returns (bytes32) 175 | { 176 | return 177 | keccak256( 178 | abi.encode( 179 | _OFFER_ITEM_TYPEHASH, 180 | offerItem.itemType, 181 | offerItem.token, 182 | offerItem.identifierOrCriteria, 183 | offerItem.startAmount, 184 | offerItem.endAmount 185 | ) 186 | ); 187 | } 188 | 189 | /** 190 | * @dev Internal view function to derive the EIP-712 hash for a consideration item. 191 | * 192 | * @param considerationItem The consideration item to hash. 193 | * 194 | * @return The hash. 195 | */ 196 | function _hashConsiderationItem(ConsiderationItem memory considerationItem) 197 | internal 198 | view 199 | returns (bytes32) 200 | { 201 | return 202 | keccak256( 203 | abi.encode( 204 | _CONSIDERATION_ITEM_TYPEHASH, 205 | considerationItem.itemType, 206 | considerationItem.token, 207 | considerationItem.identifierOrCriteria, 208 | considerationItem.startAmount, 209 | considerationItem.endAmount, 210 | considerationItem.recipient 211 | ) 212 | ); 213 | } 214 | 215 | /** 216 | * @dev Internal view function to derive the order hash for a given order. 217 | * Note that only the original consideration items are included in the 218 | * order hash, as additional consideration items may be supplied by the 219 | * caller. 220 | * 221 | * @param orderParameters The parameters of the order to hash. 222 | * @param counter The counter of the order to hash. 223 | * 224 | * @return orderHash The hash. 225 | */ 226 | function _deriveOrderHash( 227 | OrderParameters memory orderParameters, 228 | uint256 counter 229 | ) internal view returns (bytes32 orderHash) { 230 | // Designate new memory regions for offer and consideration item hashes. 231 | bytes32[] memory offerHashes = new bytes32[]( 232 | orderParameters.offer.length 233 | ); 234 | bytes32[] memory considerationHashes = new bytes32[]( 235 | orderParameters.totalOriginalConsiderationItems 236 | ); 237 | 238 | // Iterate over each offer on the order. 239 | for (uint256 i = 0; i < orderParameters.offer.length; ++i) { 240 | // Hash the offer and place the result into memory. 241 | offerHashes[i] = _hashOfferItem(orderParameters.offer[i]); 242 | } 243 | 244 | // Iterate over each consideration on the order. 245 | for ( 246 | uint256 i = 0; 247 | i < orderParameters.totalOriginalConsiderationItems; 248 | ++i 249 | ) { 250 | // Hash the consideration and place the result into memory. 251 | considerationHashes[i] = _hashConsiderationItem( 252 | orderParameters.consideration[i] 253 | ); 254 | } 255 | 256 | // Derive and return the order hash as specified by EIP-712. 257 | 258 | return 259 | keccak256( 260 | abi.encode( 261 | _ORDER_TYPEHASH, 262 | orderParameters.offerer, 263 | orderParameters.zone, 264 | keccak256(abi.encodePacked(offerHashes)), 265 | keccak256(abi.encodePacked(considerationHashes)), 266 | orderParameters.orderType, 267 | orderParameters.startTime, 268 | orderParameters.endTime, 269 | orderParameters.zoneHash, 270 | orderParameters.salt, 271 | orderParameters.conduitKey, 272 | counter 273 | ) 274 | ); 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /src/marketplaces/seaport-1.6/lib/ConsiderationEnums.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.7; 3 | 4 | // prettier-ignore 5 | enum OrderType { 6 | // 0: no partial fills, anyone can execute 7 | FULL_OPEN, 8 | 9 | // 1: partial fills supported, anyone can execute 10 | PARTIAL_OPEN, 11 | 12 | // 2: no partial fills, only offerer or zone can execute 13 | FULL_RESTRICTED, 14 | 15 | // 3: partial fills supported, only offerer or zone can execute 16 | PARTIAL_RESTRICTED 17 | } 18 | 19 | // prettier-ignore 20 | enum BasicOrderType { 21 | // 0: no partial fills, anyone can execute 22 | ETH_TO_ERC721_FULL_OPEN, 23 | 24 | // 1: partial fills supported, anyone can execute 25 | ETH_TO_ERC721_PARTIAL_OPEN, 26 | 27 | // 2: no partial fills, only offerer or zone can execute 28 | ETH_TO_ERC721_FULL_RESTRICTED, 29 | 30 | // 3: partial fills supported, only offerer or zone can execute 31 | ETH_TO_ERC721_PARTIAL_RESTRICTED, 32 | 33 | // 4: no partial fills, anyone can execute 34 | ETH_TO_ERC1155_FULL_OPEN, 35 | 36 | // 5: partial fills supported, anyone can execute 37 | ETH_TO_ERC1155_PARTIAL_OPEN, 38 | 39 | // 6: no partial fills, only offerer or zone can execute 40 | ETH_TO_ERC1155_FULL_RESTRICTED, 41 | 42 | // 7: partial fills supported, only offerer or zone can execute 43 | ETH_TO_ERC1155_PARTIAL_RESTRICTED, 44 | 45 | // 8: no partial fills, anyone can execute 46 | ERC20_TO_ERC721_FULL_OPEN, 47 | 48 | // 9: partial fills supported, anyone can execute 49 | ERC20_TO_ERC721_PARTIAL_OPEN, 50 | 51 | // 10: no partial fills, only offerer or zone can execute 52 | ERC20_TO_ERC721_FULL_RESTRICTED, 53 | 54 | // 11: partial fills supported, only offerer or zone can execute 55 | ERC20_TO_ERC721_PARTIAL_RESTRICTED, 56 | 57 | // 12: no partial fills, anyone can execute 58 | ERC20_TO_ERC1155_FULL_OPEN, 59 | 60 | // 13: partial fills supported, anyone can execute 61 | ERC20_TO_ERC1155_PARTIAL_OPEN, 62 | 63 | // 14: no partial fills, only offerer or zone can execute 64 | ERC20_TO_ERC1155_FULL_RESTRICTED, 65 | 66 | // 15: partial fills supported, only offerer or zone can execute 67 | ERC20_TO_ERC1155_PARTIAL_RESTRICTED, 68 | 69 | // 16: no partial fills, anyone can execute 70 | ERC721_TO_ERC20_FULL_OPEN, 71 | 72 | // 17: partial fills supported, anyone can execute 73 | ERC721_TO_ERC20_PARTIAL_OPEN, 74 | 75 | // 18: no partial fills, only offerer or zone can execute 76 | ERC721_TO_ERC20_FULL_RESTRICTED, 77 | 78 | // 19: partial fills supported, only offerer or zone can execute 79 | ERC721_TO_ERC20_PARTIAL_RESTRICTED, 80 | 81 | // 20: no partial fills, anyone can execute 82 | ERC1155_TO_ERC20_FULL_OPEN, 83 | 84 | // 21: partial fills supported, anyone can execute 85 | ERC1155_TO_ERC20_PARTIAL_OPEN, 86 | 87 | // 22: no partial fills, only offerer or zone can execute 88 | ERC1155_TO_ERC20_FULL_RESTRICTED, 89 | 90 | // 23: partial fills supported, only offerer or zone can execute 91 | ERC1155_TO_ERC20_PARTIAL_RESTRICTED 92 | } 93 | 94 | // prettier-ignore 95 | enum BasicOrderRouteType { 96 | // 0: provide Ether (or other native token) to receive offered ERC721 item. 97 | ETH_TO_ERC721, 98 | 99 | // 1: provide Ether (or other native token) to receive offered ERC1155 item. 100 | ETH_TO_ERC1155, 101 | 102 | // 2: provide ERC20 item to receive offered ERC721 item. 103 | ERC20_TO_ERC721, 104 | 105 | // 3: provide ERC20 item to receive offered ERC1155 item. 106 | ERC20_TO_ERC1155, 107 | 108 | // 4: provide ERC721 item to receive offered ERC20 item. 109 | ERC721_TO_ERC20, 110 | 111 | // 5: provide ERC1155 item to receive offered ERC20 item. 112 | ERC1155_TO_ERC20 113 | } 114 | 115 | // prettier-ignore 116 | enum ItemType { 117 | // 0: ETH on mainnet, MATIC on polygon, etc. 118 | NATIVE, 119 | 120 | // 1: ERC20 items (ERC777 and ERC20 analogues could also technically work) 121 | ERC20, 122 | 123 | // 2: ERC721 items 124 | ERC721, 125 | 126 | // 3: ERC1155 items 127 | ERC1155, 128 | 129 | // 4: ERC721 items where a number of tokenIds are supported 130 | ERC721_WITH_CRITERIA, 131 | 132 | // 5: ERC1155 items where a number of ids are supported 133 | ERC1155_WITH_CRITERIA 134 | } 135 | 136 | // prettier-ignore 137 | enum Side { 138 | // 0: Items that can be spent 139 | OFFER, 140 | 141 | // 1: Items that must be received 142 | CONSIDERATION 143 | } 144 | -------------------------------------------------------------------------------- /src/marketplaces/seaport-1.6/lib/ConsiderationStructs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.7; 3 | 4 | // prettier-ignore 5 | import { 6 | OrderType, 7 | BasicOrderType, 8 | ItemType, 9 | Side, 10 | BasicOrderRouteType 11 | } from "./ConsiderationEnums.sol"; 12 | 13 | /** 14 | * @dev An order contains eleven components: an offerer, a zone (or account that 15 | * can cancel the order or restrict who can fulfill the order depending on 16 | * the type), the order type (specifying partial fill support as well as 17 | * restricted order status), the start and end time, a hash that will be 18 | * provided to the zone when validating restricted orders, a salt, a key 19 | * corresponding to a given conduit, a counter, and an arbitrary number of 20 | * offer items that can be spent along with consideration items that must 21 | * be received by their respective recipient. 22 | */ 23 | struct OrderComponents { 24 | address offerer; 25 | address zone; 26 | OfferItem[] offer; 27 | ConsiderationItem[] consideration; 28 | OrderType orderType; 29 | uint256 startTime; 30 | uint256 endTime; 31 | bytes32 zoneHash; 32 | uint256 salt; 33 | bytes32 conduitKey; 34 | uint256 counter; 35 | } 36 | 37 | /** 38 | * @dev An offer item has five components: an item type (ETH or other native 39 | * tokens, ERC20, ERC721, and ERC1155, as well as criteria-based ERC721 and 40 | * ERC1155), a token address, a dual-purpose "identifierOrCriteria" 41 | * component that will either represent a tokenId or a merkle root 42 | * depending on the item type, and a start and end amount that support 43 | * increasing or decreasing amounts over the duration of the respective 44 | * order. 45 | */ 46 | struct OfferItem { 47 | ItemType itemType; 48 | address token; 49 | uint256 identifierOrCriteria; 50 | uint256 startAmount; 51 | uint256 endAmount; 52 | } 53 | 54 | /** 55 | * @dev A consideration item has the same five components as an offer item and 56 | * an additional sixth component designating the required recipient of the 57 | * item. 58 | */ 59 | struct ConsiderationItem { 60 | ItemType itemType; 61 | address token; 62 | uint256 identifierOrCriteria; 63 | uint256 startAmount; 64 | uint256 endAmount; 65 | address payable recipient; 66 | } 67 | 68 | /** 69 | * @dev A spent item is translated from a utilized offer item and has four 70 | * components: an item type (ETH or other native tokens, ERC20, ERC721, and 71 | * ERC1155), a token address, a tokenId, and an amount. 72 | */ 73 | struct SpentItem { 74 | ItemType itemType; 75 | address token; 76 | uint256 identifier; 77 | uint256 amount; 78 | } 79 | 80 | /** 81 | * @dev A received item is translated from a utilized consideration item and has 82 | * the same four components as a spent item, as well as an additional fifth 83 | * component designating the required recipient of the item. 84 | */ 85 | struct ReceivedItem { 86 | ItemType itemType; 87 | address token; 88 | uint256 identifier; 89 | uint256 amount; 90 | address payable recipient; 91 | } 92 | 93 | /** 94 | * @dev For basic orders involving ETH / native / ERC20 <=> ERC721 / ERC1155 95 | * matching, a group of six functions may be called that only requires a 96 | * subset of the usual order arguments. Note the use of a "basicOrderType" 97 | * enum; this represents both the usual order type as well as the "route" 98 | * of the basic order (a simple derivation function for the basic order 99 | * type is `basicOrderType = orderType + (4 * basicOrderRoute)`.) 100 | */ 101 | struct BasicOrderParameters { 102 | // calldata offset 103 | address considerationToken; // 0x24 104 | uint256 considerationIdentifier; // 0x44 105 | uint256 considerationAmount; // 0x64 106 | address payable offerer; // 0x84 107 | address zone; // 0xa4 108 | address offerToken; // 0xc4 109 | uint256 offerIdentifier; // 0xe4 110 | uint256 offerAmount; // 0x104 111 | BasicOrderType basicOrderType; // 0x124 112 | uint256 startTime; // 0x144 113 | uint256 endTime; // 0x164 114 | bytes32 zoneHash; // 0x184 115 | uint256 salt; // 0x1a4 116 | bytes32 offererConduitKey; // 0x1c4 117 | bytes32 fulfillerConduitKey; // 0x1e4 118 | uint256 totalOriginalAdditionalRecipients; // 0x204 119 | AdditionalRecipient[] additionalRecipients; // 0x224 120 | bytes signature; // 0x244 121 | // Total length, excluding dynamic array data: 0x264 (580) 122 | } 123 | 124 | /** 125 | * @dev Basic orders can supply any number of additional recipients, with the 126 | * implied assumption that they are supplied from the offered ETH (or other 127 | * native token) or ERC20 token for the order. 128 | */ 129 | struct AdditionalRecipient { 130 | uint256 amount; 131 | address payable recipient; 132 | } 133 | 134 | /** 135 | * @dev The full set of order components, with the exception of the counter, 136 | * must be supplied when fulfilling more sophisticated orders or groups of 137 | * orders. The total number of original consideration items must also be 138 | * supplied, as the caller may specify additional consideration items. 139 | */ 140 | struct OrderParameters { 141 | address offerer; // 0x00 142 | address zone; // 0x20 143 | OfferItem[] offer; // 0x40 144 | ConsiderationItem[] consideration; // 0x60 145 | OrderType orderType; // 0x80 146 | uint256 startTime; // 0xa0 147 | uint256 endTime; // 0xc0 148 | bytes32 zoneHash; // 0xe0 149 | uint256 salt; // 0x100 150 | bytes32 conduitKey; // 0x120 151 | uint256 totalOriginalConsiderationItems; // 0x140 152 | // offer.length // 0x160 153 | } 154 | 155 | /** 156 | * @dev Orders require a signature in addition to the other order parameters. 157 | */ 158 | struct Order { 159 | OrderParameters parameters; 160 | bytes signature; 161 | } 162 | 163 | /** 164 | * @dev Advanced orders include a numerator (i.e. a fraction to attempt to fill) 165 | * and a denominator (the total size of the order) in addition to the 166 | * signature and other order parameters. It also supports an optional field 167 | * for supplying extra data; this data will be included in a staticcall to 168 | * `isValidOrderIncludingExtraData` on the zone for the order if the order 169 | * type is restricted and the offerer or zone are not the caller. 170 | */ 171 | struct AdvancedOrder { 172 | OrderParameters parameters; 173 | uint120 numerator; 174 | uint120 denominator; 175 | bytes signature; 176 | bytes extraData; 177 | } 178 | 179 | /** 180 | * @dev Orders can be validated (either explicitly via `validate`, or as a 181 | * consequence of a full or partial fill), specifically cancelled (they can 182 | * also be cancelled in bulk via incrementing a per-zone counter), and 183 | * partially or fully filled (with the fraction filled represented by a 184 | * numerator and denominator). 185 | */ 186 | struct OrderStatus { 187 | bool isValidated; 188 | bool isCancelled; 189 | uint120 numerator; 190 | uint120 denominator; 191 | } 192 | 193 | /** 194 | * @dev A criteria resolver specifies an order, side (offer vs. consideration), 195 | * and item index. It then provides a chosen identifier (i.e. tokenId) 196 | * alongside a merkle proof demonstrating the identifier meets the required 197 | * criteria. 198 | */ 199 | struct CriteriaResolver { 200 | uint256 orderIndex; 201 | Side side; 202 | uint256 index; 203 | uint256 identifier; 204 | bytes32[] criteriaProof; 205 | } 206 | 207 | /** 208 | * @dev A fulfillment is applied to a group of orders. It decrements a series of 209 | * offer and consideration items, then generates a single execution 210 | * element. A given fulfillment can be applied to as many offer and 211 | * consideration items as desired, but must contain at least one offer and 212 | * at least one consideration that match. The fulfillment must also remain 213 | * consistent on all key parameters across all offer items (same offerer, 214 | * token, type, tokenId, and conduit preference) as well as across all 215 | * consideration items (token, type, tokenId, and recipient). 216 | */ 217 | struct Fulfillment { 218 | FulfillmentComponent[] offerComponents; 219 | FulfillmentComponent[] considerationComponents; 220 | } 221 | 222 | /** 223 | * @dev Each fulfillment component contains one index referencing a specific 224 | * order and another referencing a specific offer or consideration item. 225 | */ 226 | struct FulfillmentComponent { 227 | uint256 orderIndex; 228 | uint256 itemIndex; 229 | } 230 | 231 | /** 232 | * @dev An execution is triggered once all consideration items have been zeroed 233 | * out. It sends the item in question from the offerer to the item's 234 | * recipient, optionally sourcing approvals from either this contract 235 | * directly or from the offerer's chosen conduit if one is specified. An 236 | * execution is not provided as an argument, but rather is derived via 237 | * orders, criteria resolvers, and fulfillments (where the total number of 238 | * executions will be less than or equal to the total number of indicated 239 | * fulfillments) and returned as part of `matchOrders`. 240 | */ 241 | struct Execution { 242 | ReceivedItem item; 243 | address offerer; 244 | bytes32 conduitKey; 245 | } 246 | -------------------------------------------------------------------------------- /src/marketplaces/seaport-1.6/lib/ConsiderationTypeHashes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.7; 3 | 4 | import "./ConsiderationStructs.sol"; 5 | 6 | uint256 constant EIP712_Order_size = 0x180; 7 | uint256 constant EIP712_OfferItem_size = 0xc0; 8 | uint256 constant EIP712_ConsiderationItem_size = 0xe0; 9 | uint256 constant EIP712_DomainSeparator_offset = 0x02; 10 | uint256 constant EIP712_OrderHash_offset = 0x22; 11 | uint256 constant EIP712_DigestPayload_size = 0x42; 12 | uint256 constant EIP_712_PREFIX = ( 13 | 0x1901000000000000000000000000000000000000000000000000000000000000 14 | ); 15 | 16 | contract ConsiderationTypeHashes { 17 | bytes32 internal immutable _NAME_HASH; 18 | bytes32 internal immutable _VERSION_HASH; 19 | bytes32 internal immutable _EIP_712_DOMAIN_TYPEHASH; 20 | bytes32 internal immutable _OFFER_ITEM_TYPEHASH; 21 | bytes32 internal immutable _CONSIDERATION_ITEM_TYPEHASH; 22 | bytes32 internal immutable _ORDER_TYPEHASH; 23 | bytes32 internal immutable _DOMAIN_SEPARATOR; 24 | address internal constant seaportAddress = 25 | address(0x0000000000000068F116a894984e2DB1123eB395); 26 | 27 | constructor() { 28 | // Derive hash of the name of the contract. 29 | _NAME_HASH = keccak256(bytes("Seaport")); 30 | 31 | // Derive hash of the version string of the contract. 32 | _VERSION_HASH = keccak256(bytes("1.6")); 33 | 34 | bytes memory offerItemTypeString = abi.encodePacked( 35 | "OfferItem(", 36 | "uint8 itemType,", 37 | "address token,", 38 | "uint256 identifierOrCriteria,", 39 | "uint256 startAmount,", 40 | "uint256 endAmount", 41 | ")" 42 | ); 43 | 44 | // Construct the ConsiderationItem type string. 45 | // prettier-ignore 46 | bytes memory considerationItemTypeString = abi.encodePacked( 47 | "ConsiderationItem(", 48 | "uint8 itemType,", 49 | "address token,", 50 | "uint256 identifierOrCriteria,", 51 | "uint256 startAmount,", 52 | "uint256 endAmount,", 53 | "address recipient", 54 | ")" 55 | ); 56 | 57 | // Construct the OrderComponents type string, not including the above. 58 | // prettier-ignore 59 | bytes memory orderComponentsPartialTypeString = abi.encodePacked( 60 | "OrderComponents(", 61 | "address offerer,", 62 | "address zone,", 63 | "OfferItem[] offer,", 64 | "ConsiderationItem[] consideration,", 65 | "uint8 orderType,", 66 | "uint256 startTime,", 67 | "uint256 endTime,", 68 | "bytes32 zoneHash,", 69 | "uint256 salt,", 70 | "bytes32 conduitKey,", 71 | "uint256 counter", 72 | ")" 73 | ); 74 | // Derive the OfferItem type hash using the corresponding type string. 75 | bytes32 offerItemTypehash = keccak256(offerItemTypeString); 76 | 77 | // Derive ConsiderationItem type hash using corresponding type string. 78 | bytes32 considerationItemTypehash = keccak256( 79 | considerationItemTypeString 80 | ); 81 | 82 | // Construct the primary EIP-712 domain type string. 83 | // prettier-ignore 84 | _EIP_712_DOMAIN_TYPEHASH = keccak256( 85 | abi.encodePacked( 86 | "EIP712Domain(", 87 | "string name,", 88 | "string version,", 89 | "uint256 chainId,", 90 | "address verifyingContract", 91 | ")" 92 | ) 93 | ); 94 | 95 | _OFFER_ITEM_TYPEHASH = offerItemTypehash; 96 | _CONSIDERATION_ITEM_TYPEHASH = considerationItemTypehash; 97 | 98 | // Derive OrderItem type hash via combination of relevant type strings. 99 | _ORDER_TYPEHASH = keccak256( 100 | abi.encodePacked( 101 | orderComponentsPartialTypeString, 102 | considerationItemTypeString, 103 | offerItemTypeString 104 | ) 105 | ); 106 | 107 | _DOMAIN_SEPARATOR = _deriveDomainSeparator(); 108 | } 109 | 110 | /** 111 | * @dev Internal view function to derive the EIP-712 domain separator. 112 | * 113 | * @return The derived domain separator. 114 | */ 115 | function _deriveDomainSeparator() internal view returns (bytes32) { 116 | // prettier-ignore 117 | return keccak256( 118 | abi.encode( 119 | _EIP_712_DOMAIN_TYPEHASH, 120 | _NAME_HASH, 121 | _VERSION_HASH, 122 | 1, 123 | seaportAddress 124 | ) 125 | ); 126 | } 127 | 128 | /** 129 | * @dev Internal pure function to efficiently derive an digest to sign for 130 | * an order in accordance with EIP-712. 131 | * 132 | * @param orderHash The order hash. 133 | * 134 | * @return value The hash. 135 | */ 136 | function _deriveEIP712Digest(bytes32 orderHash) 137 | internal 138 | view 139 | returns (bytes32 value) 140 | { 141 | bytes32 domainSeparator = _DOMAIN_SEPARATOR; 142 | // Leverage scratch space to perform an efficient hash. 143 | assembly { 144 | // Place the EIP-712 prefix at the start of scratch space. 145 | mstore(0, EIP_712_PREFIX) 146 | 147 | // Place the domain separator in the next region of scratch space. 148 | mstore(EIP712_DomainSeparator_offset, domainSeparator) 149 | 150 | // Place the order hash in scratch space, spilling into the first 151 | // two bytes of the free memory pointer — this should never be set 152 | // as memory cannot be expanded to that size, and will be zeroed out 153 | // after the hash is performed. 154 | mstore(EIP712_OrderHash_offset, orderHash) 155 | 156 | // Hash the relevant region (65 bytes). 157 | value := keccak256(0, EIP712_DigestPayload_size) 158 | 159 | // Clear out the dirtied bits in the memory pointer. 160 | mstore(EIP712_OrderHash_offset, 0) 161 | } 162 | } 163 | 164 | /** 165 | * @dev Internal view function to derive the EIP-712 hash for an offer item. 166 | * 167 | * @param offerItem The offered item to hash. 168 | * 169 | * @return The hash. 170 | */ 171 | function _hashOfferItem(OfferItem memory offerItem) 172 | internal 173 | view 174 | returns (bytes32) 175 | { 176 | return 177 | keccak256( 178 | abi.encode( 179 | _OFFER_ITEM_TYPEHASH, 180 | offerItem.itemType, 181 | offerItem.token, 182 | offerItem.identifierOrCriteria, 183 | offerItem.startAmount, 184 | offerItem.endAmount 185 | ) 186 | ); 187 | } 188 | 189 | /** 190 | * @dev Internal view function to derive the EIP-712 hash for a consideration item. 191 | * 192 | * @param considerationItem The consideration item to hash. 193 | * 194 | * @return The hash. 195 | */ 196 | function _hashConsiderationItem(ConsiderationItem memory considerationItem) 197 | internal 198 | view 199 | returns (bytes32) 200 | { 201 | return 202 | keccak256( 203 | abi.encode( 204 | _CONSIDERATION_ITEM_TYPEHASH, 205 | considerationItem.itemType, 206 | considerationItem.token, 207 | considerationItem.identifierOrCriteria, 208 | considerationItem.startAmount, 209 | considerationItem.endAmount, 210 | considerationItem.recipient 211 | ) 212 | ); 213 | } 214 | 215 | /** 216 | * @dev Internal view function to derive the order hash for a given order. 217 | * Note that only the original consideration items are included in the 218 | * order hash, as additional consideration items may be supplied by the 219 | * caller. 220 | * 221 | * @param orderParameters The parameters of the order to hash. 222 | * @param counter The counter of the order to hash. 223 | * 224 | * @return orderHash The hash. 225 | */ 226 | function _deriveOrderHash( 227 | OrderParameters memory orderParameters, 228 | uint256 counter 229 | ) internal view returns (bytes32 orderHash) { 230 | // Designate new memory regions for offer and consideration item hashes. 231 | bytes32[] memory offerHashes = new bytes32[]( 232 | orderParameters.offer.length 233 | ); 234 | bytes32[] memory considerationHashes = new bytes32[]( 235 | orderParameters.totalOriginalConsiderationItems 236 | ); 237 | 238 | // Iterate over each offer on the order. 239 | for (uint256 i = 0; i < orderParameters.offer.length; ++i) { 240 | // Hash the offer and place the result into memory. 241 | offerHashes[i] = _hashOfferItem(orderParameters.offer[i]); 242 | } 243 | 244 | // Iterate over each consideration on the order. 245 | for ( 246 | uint256 i = 0; 247 | i < orderParameters.totalOriginalConsiderationItems; 248 | ++i 249 | ) { 250 | // Hash the consideration and place the result into memory. 251 | considerationHashes[i] = _hashConsiderationItem( 252 | orderParameters.consideration[i] 253 | ); 254 | } 255 | 256 | // Derive and return the order hash as specified by EIP-712. 257 | 258 | return 259 | keccak256( 260 | abi.encode( 261 | _ORDER_TYPEHASH, 262 | orderParameters.offerer, 263 | orderParameters.zone, 264 | keccak256(abi.encodePacked(offerHashes)), 265 | keccak256(abi.encodePacked(considerationHashes)), 266 | orderParameters.orderType, 267 | orderParameters.startTime, 268 | orderParameters.endTime, 269 | orderParameters.zoneHash, 270 | orderParameters.salt, 271 | orderParameters.conduitKey, 272 | counter 273 | ) 274 | ); 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /src/marketplaces/sudoswap/interfaces/IPair.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | interface IPair { 5 | function swapNFTsForToken( 6 | uint256[] calldata nftIds, 7 | uint256 minExpectedTokenOutput, 8 | address payable tokenRecipient, 9 | bool isRouter, 10 | address routerCaller 11 | ) external returns (uint256 outputAmount); 12 | 13 | function swapTokenForSpecificNFTs( 14 | uint256[] calldata nftIds, 15 | uint256 maxExpectedTokenInput, 16 | address nftRecipient, 17 | bool isRouter, 18 | address routerCaller 19 | ) external payable returns (uint256 inputAmount); 20 | } 21 | -------------------------------------------------------------------------------- /src/marketplaces/sudoswap/interfaces/IPairFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import { IPair } from "./IPair.sol"; 5 | 6 | interface IPairFactory { 7 | enum PoolType { 8 | TOKEN, 9 | NFT, 10 | TRADE 11 | } 12 | 13 | function createPairETH( 14 | address _nft, 15 | address _bondingCurve, 16 | address payable _assetRecipient, 17 | PoolType _poolType, 18 | uint128 _delta, 19 | uint96 _fee, 20 | uint128 _spotPrice, 21 | uint256[] calldata _initialNFTIDs 22 | ) external payable returns (IPair pair); 23 | 24 | struct CreateERC20PairParams { 25 | address token; 26 | address nft; 27 | address bondingCurve; 28 | address payable assetRecipient; 29 | PoolType poolType; 30 | uint128 delta; 31 | uint96 fee; 32 | uint128 spotPrice; 33 | uint256[] initialNFTIDs; 34 | uint256 initialTokenBalance; 35 | } 36 | 37 | function createPairERC20(CreateERC20PairParams calldata params) 38 | external 39 | returns (IPair pair); 40 | 41 | function owner() external view returns (address); 42 | 43 | function changeProtocolFeeMultiplier(uint256 _protocolFeeMultiplier) 44 | external; 45 | 46 | function setRouterAllowed(address _router, bool isAllowed) external; 47 | } 48 | -------------------------------------------------------------------------------- /src/marketplaces/sudoswap/interfaces/IRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | interface IRouter { 5 | struct PairSwapSpecific { 6 | address pair; 7 | uint256[] nftIds; 8 | } 9 | 10 | function swapETHForSpecificNFTs( 11 | PairSwapSpecific[] calldata swapList, 12 | address payable ethRecipient, 13 | address nftRecipient, 14 | uint256 deadline 15 | ) external payable returns (uint256 remainingValue); 16 | 17 | function swapERC20ForSpecificNFTs( 18 | PairSwapSpecific[] calldata swapList, 19 | uint256 inputAmount, 20 | address nftRecipient, 21 | uint256 deadline 22 | ) external returns (uint256 remainingValue); 23 | 24 | function swapNFTsForToken( 25 | PairSwapSpecific[] calldata swapList, 26 | uint256 minOutput, 27 | address tokenRecipient, 28 | uint256 deadline 29 | ) external returns (uint256 outputAmount); 30 | 31 | function depositNFTs( 32 | address _nft, 33 | uint256[] calldata ids, 34 | address recipient 35 | ) external; 36 | 37 | function depositNFTs( 38 | address _nft, 39 | uint256[] calldata ids, 40 | address[] calldata recipients 41 | ) external; 42 | } 43 | -------------------------------------------------------------------------------- /src/marketplaces/wyvern/interfaces/IAtomicizer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.13; 3 | 4 | interface IAtomicizer { 5 | function atomicize( 6 | address[] calldata addrs, 7 | uint256[] calldata values, 8 | uint256[] calldata calldataLengths, 9 | bytes calldata calldatas 10 | ) external; 11 | } 12 | -------------------------------------------------------------------------------- /src/marketplaces/wyvern/interfaces/IERC1155.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.13; 3 | 4 | interface IERC1155 { 5 | function safeTransferFrom( 6 | address from, 7 | address to, 8 | uint256 id, 9 | uint256 amount, 10 | bytes memory data 11 | ) external; 12 | } 13 | -------------------------------------------------------------------------------- /src/marketplaces/wyvern/interfaces/IERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.13; 3 | 4 | interface IERC721 { 5 | function safeTransferFrom( 6 | address from, 7 | address to, 8 | uint256 tokenId 9 | ) external; 10 | 11 | function transferFrom( 12 | address from, 13 | address to, 14 | uint256 tokenId 15 | ) external; 16 | } 17 | -------------------------------------------------------------------------------- /src/marketplaces/wyvern/interfaces/IWyvernProxyRegistry.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.13; 3 | 4 | interface IWyvernProxyRegistry { 5 | function registerProxy() external returns (address); 6 | 7 | function proxies(address) external returns (address); 8 | } 9 | -------------------------------------------------------------------------------- /src/marketplaces/wyvern/interfaces/WyvernInterface.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.13; 3 | 4 | import { FeeMethod, Side, SaleKind, HowToCall } from "../lib/WyvernEnums.sol"; 5 | 6 | interface WyvernInterface { 7 | function atomicMatch_( 8 | address[14] calldata addrs, 9 | uint256[18] calldata uints, 10 | uint8[8] calldata feeMethodsSidesKindsHowToCalls, 11 | bytes calldata calldataBuy, 12 | bytes calldata calldataSell, 13 | bytes calldata replacementPatternBuy, 14 | bytes calldata replacementPatternSell, 15 | bytes calldata staticExtradataBuy, 16 | bytes calldata staticExtradataSell, 17 | uint8[2] calldata vs, 18 | bytes32[5] calldata rssMetadata 19 | ) external payable; 20 | 21 | function approveOrder_( 22 | address[7] calldata addrs, 23 | uint256[9] calldata uints, 24 | FeeMethod feeMethod, 25 | Side side, 26 | SaleKind saleKind, 27 | HowToCall howToCall, 28 | bytes calldata _calldata, 29 | bytes calldata replacementPattern, 30 | bytes calldata staticExtradata, 31 | bool orderbookInclusionDesired 32 | ) external; 33 | } 34 | -------------------------------------------------------------------------------- /src/marketplaces/wyvern/lib/ArrayUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.13; 3 | 4 | library ArrayUtils { 5 | function guardedArrayReplace( 6 | bytes memory array, 7 | bytes memory desired, 8 | bytes memory mask 9 | ) internal pure { 10 | require(array.length == desired.length); 11 | require(array.length == mask.length); 12 | 13 | uint256 words = array.length / 0x20; 14 | uint256 index = words * 0x20; 15 | assert(index / 0x20 == words); 16 | uint256 i; 17 | 18 | for (i = 0; i < words; i++) { 19 | /* Conceptually: array[i] = (!mask[i] && array[i]) || (mask[i] && desired[i]), bitwise in word chunks. */ 20 | assembly { 21 | let commonIndex := mul(0x20, add(1, i)) 22 | let maskValue := mload(add(mask, commonIndex)) 23 | mstore( 24 | add(array, commonIndex), 25 | or( 26 | and(not(maskValue), mload(add(array, commonIndex))), 27 | and(maskValue, mload(add(desired, commonIndex))) 28 | ) 29 | ) 30 | } 31 | } 32 | 33 | /* Deal with the last section of the byte array. */ 34 | if (words > 0) { 35 | /* This overlaps with bytes already set but is still more efficient than iterating through each of the remaining bytes individually. */ 36 | i = words; 37 | assembly { 38 | let commonIndex := mul(0x20, add(1, i)) 39 | let maskValue := mload(add(mask, commonIndex)) 40 | mstore( 41 | add(array, commonIndex), 42 | or( 43 | and(not(maskValue), mload(add(array, commonIndex))), 44 | and(maskValue, mload(add(desired, commonIndex))) 45 | ) 46 | ) 47 | } 48 | } else { 49 | /* If the byte array is shorter than a word, we must unfortunately do the whole thing bytewise. 50 | (bounds checks could still probably be optimized away in assembly, but this is a rare case) */ 51 | for (i = index; i < array.length; i++) { 52 | array[i] = 53 | ((mask[i] ^ 0xff) & array[i]) | 54 | (mask[i] & desired[i]); 55 | } 56 | } 57 | } 58 | 59 | /** 60 | * Test if two arrays are equal 61 | * @param a First array 62 | * @param b Second array 63 | * @return Whether or not all bytes in the arrays are equal 64 | */ 65 | function arrayEq(bytes memory a, bytes memory b) 66 | internal 67 | pure 68 | returns (bool) 69 | { 70 | return keccak256(a) == keccak256(b); 71 | } 72 | 73 | /** 74 | * Unsafe write address into a memory location using entire word 75 | * 76 | * @param index Memory location 77 | * @param source uint to write 78 | * @return End memory index 79 | */ 80 | function unsafeWriteAddressWord(uint256 index, address source) 81 | internal 82 | pure 83 | returns (uint256) 84 | { 85 | assembly { 86 | mstore(index, source) 87 | index := add(index, 0x20) 88 | } 89 | return index; 90 | } 91 | 92 | /** 93 | * Unsafe write uint into a memory location 94 | * 95 | * @param index Memory location 96 | * @param source uint to write 97 | * @return End memory index 98 | */ 99 | function unsafeWriteUint(uint256 index, uint256 source) 100 | internal 101 | pure 102 | returns (uint256) 103 | { 104 | assembly { 105 | mstore(index, source) 106 | index := add(index, 0x20) 107 | } 108 | return index; 109 | } 110 | 111 | /** 112 | * Unsafe write uint8 into a memory location 113 | * 114 | * @param index Memory location 115 | * @param source uint8 to write 116 | * @return End memory index 117 | */ 118 | function unsafeWriteUint8(uint256 index, uint8 source) 119 | internal 120 | pure 121 | returns (uint256) 122 | { 123 | assembly { 124 | mstore8(index, source) 125 | index := add(index, 0x1) 126 | } 127 | return index; 128 | } 129 | 130 | /** 131 | * Unsafe write uint8 into a memory location using entire word 132 | * 133 | * @param index Memory location 134 | * @param source uint to write 135 | * @return End memory index 136 | */ 137 | function unsafeWriteUint8Word(uint256 index, uint8 source) 138 | internal 139 | pure 140 | returns (uint256) 141 | { 142 | assembly { 143 | mstore(index, source) 144 | index := add(index, 0x20) 145 | } 146 | return index; 147 | } 148 | 149 | /** 150 | * Unsafe write bytes32 into a memory location using entire word 151 | * 152 | * @param index Memory location 153 | * @param source uint to write 154 | * @return End memory index 155 | */ 156 | function unsafeWriteBytes32(uint256 index, bytes32 source) 157 | internal 158 | pure 159 | returns (uint256) 160 | { 161 | assembly { 162 | mstore(index, source) 163 | index := add(index, 0x20) 164 | } 165 | return index; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/marketplaces/wyvern/lib/WyvernEnums.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.13; 3 | 4 | /* Fee method: protocol fee or split fee. */ 5 | enum FeeMethod { 6 | ProtocolFee, 7 | SplitFee 8 | } 9 | 10 | /** 11 | * Side: buy or sell. 12 | */ 13 | enum Side { 14 | Buy, 15 | Sell 16 | } 17 | 18 | /** 19 | * Currently supported kinds of sale: fixed price, Dutch auction. 20 | * English auctions cannot be supported without stronger escrow guarantees. 21 | * Future interesting options: Vickrey auction, nonlinear Dutch auctions. 22 | */ 23 | enum SaleKind { 24 | FixedPrice, 25 | DutchAuction 26 | } 27 | 28 | /* Delegate call could be used to atomically transfer multiple assets owned by the proxy contract with one order. */ 29 | enum HowToCall { 30 | Call, 31 | DelegateCall 32 | } 33 | -------------------------------------------------------------------------------- /src/marketplaces/wyvern/lib/WyvernStructs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.13; 3 | 4 | import "./WyvernEnums.sol"; 5 | 6 | /* An ECDSA signature. */ 7 | struct Sig { 8 | /* v parameter */ 9 | uint8 v; 10 | /* r parameter */ 11 | bytes32 r; 12 | /* s parameter */ 13 | bytes32 s; 14 | } 15 | 16 | /* An order on the exchange. */ 17 | struct Order { 18 | /* Exchange address, intended as a versioning mechanism. */ 19 | address exchange; 20 | /* Order maker address. */ 21 | address maker; 22 | /* Order taker address, if specified. */ 23 | address taker; 24 | /* Maker relayer fee of the order, unused for taker order. */ 25 | uint256 makerRelayerFee; 26 | /* Taker relayer fee of the order, or maximum taker fee for a taker order. */ 27 | uint256 takerRelayerFee; 28 | /* Maker protocol fee of the order, unused for taker order. */ 29 | uint256 makerProtocolFee; 30 | /* Taker protocol fee of the order, or maximum taker fee for a taker order. */ 31 | uint256 takerProtocolFee; 32 | /* Order fee recipient or zero address for taker order. */ 33 | address feeRecipient; 34 | /* Fee method (protocol token or split fee). */ 35 | FeeMethod feeMethod; 36 | /* Side (buy/sell). */ 37 | Side side; 38 | /* Kind of sale. */ 39 | SaleKind saleKind; 40 | /* Target. */ 41 | address target; 42 | /* HowToCall. */ 43 | HowToCall howToCall; 44 | /* Calldata. */ 45 | bytes _calldata; 46 | /* Calldata replacement pattern, or an empty byte array for no replacement. */ 47 | bytes replacementPattern; 48 | /* Static call target, zero-address for no static call. */ 49 | address staticTarget; 50 | /* Static call extra data. */ 51 | bytes staticExtradata; 52 | /* Token used to pay for the order, or the zero-address as a sentinel value for Ether. */ 53 | address paymentToken; 54 | /* Base price of the order (in paymentTokens). */ 55 | uint256 basePrice; 56 | /* Auction extra parameter - minimum bid increment for English auctions, starting/ending price difference. */ 57 | uint256 extra; 58 | /* Listing timestamp. */ 59 | uint256 listingTime; 60 | /* Expiration timestamp - 0 for no expiry. */ 61 | uint256 expirationTime; 62 | /* Order salt, used to prevent duplicate hashes. */ 63 | uint256 salt; 64 | } 65 | /* NOTE: uint counter is an additional component of the order but is read from storage */ 66 | -------------------------------------------------------------------------------- /src/marketplaces/wyvern/lib/WyvernTypeHashes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.13; 3 | 4 | import "./WyvernStructs.sol"; 5 | import "./ArrayUtils.sol"; 6 | 7 | uint256 constant EIP712_Order_size = 0x180; 8 | uint256 constant EIP712_DomainSeparator_offset = 0x02; 9 | uint256 constant EIP712_OrderHash_offset = 0x22; 10 | uint256 constant EIP712_DigestPayload_size = 0x42; 11 | uint256 constant EIP_712_PREFIX = ( 12 | 0x1901000000000000000000000000000000000000000000000000000000000000 13 | ); 14 | 15 | contract WyvernTypeHashes { 16 | bytes32 internal constant _NAME_HASH = 17 | 0x9a2ed463836165738cfa54208ff6e7847fd08cbaac309aac057086cb0a144d13; 18 | bytes32 internal constant _VERSION_HASH = 19 | 0xe2fd538c762ee69cab09ccd70e2438075b7004dd87577dc3937e9fcc8174bb64; 20 | bytes32 internal constant _EIP_712_DOMAIN_TYPEHASH = 21 | 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; 22 | bytes32 internal constant _ORDER_TYPEHASH = 23 | 0xdba08a88a748f356e8faf8578488343eab21b1741728779c9dcfdc782bc800f8; 24 | bytes32 internal immutable _DOMAIN_SEPARATOR; 25 | address internal constant wyvernAddress = 26 | 0x7f268357A8c2552623316e2562D90e642bB538E5; 27 | 28 | constructor() { 29 | _DOMAIN_SEPARATOR = _deriveDomainSeparator(); 30 | } 31 | 32 | /** 33 | * @dev Derive the domain separator for EIP-712 signatures. 34 | * @return The domain separator. 35 | */ 36 | function _deriveDomainSeparator() internal pure returns (bytes32) { 37 | return 38 | keccak256( 39 | abi.encode( 40 | _EIP_712_DOMAIN_TYPEHASH, 41 | _NAME_HASH, 42 | _VERSION_HASH, 43 | 1, 44 | wyvernAddress 45 | ) 46 | ); 47 | } 48 | 49 | function _deriveEIP712Digest(bytes32 orderHash) 50 | internal 51 | view 52 | returns (bytes32 value) 53 | { 54 | bytes32 domainSeparator = _DOMAIN_SEPARATOR; 55 | // Leverage scratch space to perform an efficient hash. 56 | assembly { 57 | // Place the EIP-712 prefix at the start of scratch space. 58 | mstore(0, EIP_712_PREFIX) 59 | 60 | // Place the domain separator in the next region of scratch space. 61 | mstore(EIP712_DomainSeparator_offset, domainSeparator) 62 | 63 | // Place the order hash in scratch space, spilling into the first 64 | // two bytes of the free memory pointer — this should never be set 65 | // as memory cannot be expanded to that size, and will be zeroed out 66 | // after the hash is performed. 67 | mstore(EIP712_OrderHash_offset, orderHash) 68 | 69 | // Hash the relevant region (65 bytes). 70 | value := keccak256(0, EIP712_DigestPayload_size) 71 | 72 | // Clear out the dirtied bits in the memory pointer. 73 | mstore(EIP712_OrderHash_offset, 0) 74 | } 75 | } 76 | 77 | function hashOrder(Order memory order, uint256 counter) 78 | internal 79 | pure 80 | returns (bytes32 hash) 81 | { 82 | /* Unfortunately abi.encodePacked doesn't work here, stack size constraints. */ 83 | uint256 size = 800; 84 | bytes memory array = new bytes(size); 85 | uint256 index; 86 | assembly { 87 | index := add(array, 0x20) 88 | } 89 | index = ArrayUtils.unsafeWriteBytes32(index, _ORDER_TYPEHASH); 90 | index = ArrayUtils.unsafeWriteAddressWord(index, order.exchange); 91 | index = ArrayUtils.unsafeWriteAddressWord(index, order.maker); 92 | index = ArrayUtils.unsafeWriteAddressWord(index, order.taker); 93 | index = ArrayUtils.unsafeWriteUint(index, order.makerRelayerFee); 94 | index = ArrayUtils.unsafeWriteUint(index, order.takerRelayerFee); 95 | index = ArrayUtils.unsafeWriteUint(index, order.makerProtocolFee); 96 | index = ArrayUtils.unsafeWriteUint(index, order.takerProtocolFee); 97 | index = ArrayUtils.unsafeWriteAddressWord(index, order.feeRecipient); 98 | index = ArrayUtils.unsafeWriteUint8Word(index, uint8(order.feeMethod)); 99 | index = ArrayUtils.unsafeWriteUint8Word(index, uint8(order.side)); 100 | index = ArrayUtils.unsafeWriteUint8Word(index, uint8(order.saleKind)); 101 | index = ArrayUtils.unsafeWriteAddressWord(index, order.target); 102 | index = ArrayUtils.unsafeWriteUint8Word(index, uint8(order.howToCall)); 103 | index = ArrayUtils.unsafeWriteBytes32( 104 | index, 105 | keccak256(order._calldata) 106 | ); 107 | index = ArrayUtils.unsafeWriteBytes32( 108 | index, 109 | keccak256(order.replacementPattern) 110 | ); 111 | index = ArrayUtils.unsafeWriteAddressWord(index, order.staticTarget); 112 | index = ArrayUtils.unsafeWriteBytes32( 113 | index, 114 | keccak256(order.staticExtradata) 115 | ); 116 | index = ArrayUtils.unsafeWriteAddressWord(index, order.paymentToken); 117 | index = ArrayUtils.unsafeWriteUint(index, order.basePrice); 118 | index = ArrayUtils.unsafeWriteUint(index, order.extra); 119 | index = ArrayUtils.unsafeWriteUint(index, order.listingTime); 120 | index = ArrayUtils.unsafeWriteUint(index, order.expirationTime); 121 | index = ArrayUtils.unsafeWriteUint(index, order.salt); 122 | index = ArrayUtils.unsafeWriteUint(index, counter); 123 | assembly { 124 | hash := keccak256(add(array, 0x20), size) 125 | } 126 | return hash; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/marketplaces/zeroEx/lib/LibNFTOrder.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | /// @dev A library for common NFT order operations. 5 | library LibNFTOrder { 6 | enum OrderStatus { 7 | INVALID, 8 | FILLABLE, 9 | UNFILLABLE, 10 | EXPIRED 11 | } 12 | 13 | enum TradeDirection { 14 | SELL_NFT, 15 | BUY_NFT 16 | } 17 | 18 | struct Property { 19 | address propertyValidator; 20 | bytes propertyData; 21 | } 22 | 23 | struct Fee { 24 | address recipient; 25 | uint256 amount; 26 | bytes feeData; 27 | } 28 | 29 | // "Base struct" for ERC721Order and ERC1155, used 30 | // by the abstract contract `NFTOrders`. 31 | struct NFTOrder { 32 | TradeDirection direction; 33 | address maker; 34 | address taker; 35 | uint256 expiry; 36 | uint256 nonce; 37 | address erc20Token; 38 | uint256 erc20TokenAmount; 39 | Fee[] fees; 40 | address nft; 41 | uint256 nftId; 42 | Property[] nftProperties; 43 | } 44 | 45 | // All fields align with those of NFTOrder 46 | struct ERC721Order { 47 | TradeDirection direction; 48 | address maker; 49 | address taker; 50 | uint256 expiry; 51 | uint256 nonce; 52 | address erc20Token; 53 | uint256 erc20TokenAmount; 54 | Fee[] fees; 55 | address erc721Token; 56 | uint256 erc721TokenId; 57 | Property[] erc721TokenProperties; 58 | } 59 | 60 | // All fields except `erc1155TokenAmount` align 61 | // with those of NFTOrder 62 | struct ERC1155Order { 63 | TradeDirection direction; 64 | address maker; 65 | address taker; 66 | uint256 expiry; 67 | uint256 nonce; 68 | address erc20Token; 69 | uint256 erc20TokenAmount; 70 | Fee[] fees; 71 | address erc1155Token; 72 | uint256 erc1155TokenId; 73 | Property[] erc1155TokenProperties; 74 | // End of fields shared with NFTOrder 75 | uint128 erc1155TokenAmount; 76 | } 77 | 78 | struct OrderInfo { 79 | bytes32 orderHash; 80 | OrderStatus status; 81 | // `orderAmount` is 1 for all ERC721Orders, and 82 | // `erc1155TokenAmount` for ERC1155Orders. 83 | uint128 orderAmount; 84 | // The remaining amount of the ERC721/ERC1155 asset 85 | // that can be filled for the order. 86 | uint128 remainingAmount; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/marketplaces/zeroEx/lib/LibSignature.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | library LibSignature { 5 | enum SignatureType { 6 | ILLEGAL, 7 | INVALID, 8 | EIP712, 9 | ETHSIGN, 10 | PRESIGNED 11 | } 12 | 13 | struct Signature { 14 | // How to validate the signature. 15 | SignatureType signatureType; 16 | // EC Signature data. 17 | uint8 v; 18 | // EC Signature data. 19 | bytes32 r; 20 | // EC Signature data. 21 | bytes32 s; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/tokens/TestERC1155.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.14; 3 | 4 | import "solmate/tokens/ERC1155.sol"; 5 | 6 | contract TestERC1155 is ERC1155 { 7 | function mint( 8 | address to, 9 | uint256 tokenId, 10 | uint256 amount 11 | ) public returns (bool) { 12 | _mint(to, tokenId, amount, ""); 13 | return true; 14 | } 15 | 16 | function uri(uint256) public pure override returns (string memory) { 17 | return "uri"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/tokens/TestERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.14; 3 | 4 | import "solmate/tokens/ERC20.sol"; 5 | 6 | contract TestERC20 is ERC20("Test20", "TST20", 18) { 7 | function mint(address to, uint256 amount) external returns (bool) { 8 | _mint(to, amount); 9 | return true; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/tokens/TestERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.14; 3 | 4 | import "solmate/tokens/ERC721.sol"; 5 | 6 | contract TestERC721 is ERC721("Test721", "TST721") { 7 | function mint(address to, uint256 tokenId) public returns (bool) { 8 | _mint(to, tokenId); 9 | return true; 10 | } 11 | 12 | function tokenURI(uint256) public pure override returns (string memory) { 13 | return "tokenURI"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/tokens/WETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.14; 3 | 4 | import { TestERC20 } from "./TestERC20.sol"; 5 | 6 | contract WETH is TestERC20 { 7 | event Deposit(address indexed dst, uint256 wad); 8 | event Withdrawal(address indexed src, uint256 wad); 9 | 10 | function deposit() public payable { 11 | balanceOf[msg.sender] += msg.value; 12 | emit Deposit(msg.sender, msg.value); 13 | } 14 | 15 | function withdraw(uint256 wad) public { 16 | require(balanceOf[msg.sender] >= wad); 17 | balanceOf[msg.sender] -= wad; 18 | address payable sender = payable(msg.sender); 19 | sender.transfer(wad); 20 | emit Withdrawal(msg.sender, wad); 21 | } 22 | 23 | function approve(address guy, uint256 wad) public override returns (bool) { 24 | allowance[msg.sender][guy] = wad; 25 | emit Approval(msg.sender, guy, wad); 26 | return true; 27 | } 28 | 29 | function transfer(address dst, uint256 wad) public override returns (bool) { 30 | return transferFrom(msg.sender, dst, wad); 31 | } 32 | 33 | function transferFrom( 34 | address src, 35 | address dst, 36 | uint256 wad 37 | ) public override returns (bool) { 38 | require(balanceOf[src] >= wad); 39 | 40 | if ( 41 | src != msg.sender && allowance[src][msg.sender] != type(uint256).max 42 | ) { 43 | require(allowance[src][msg.sender] >= wad); 44 | allowance[src][msg.sender] -= wad; 45 | } 46 | 47 | balanceOf[src] -= wad; 48 | balanceOf[dst] += wad; 49 | 50 | emit Transfer(src, dst, wad); 51 | 52 | return true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /test/utils/BaseOrderTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.14; 3 | 4 | import { DSTestPlus } from "solmate/test/utils/DSTestPlus.sol"; 5 | import { stdStorage, StdStorage } from "forge-std/Test.sol"; 6 | import { TestERC1155 } from "../tokens/TestERC1155.sol"; 7 | import { TestERC20 } from "../tokens/TestERC20.sol"; 8 | import { WETH } from "../tokens/WETH.sol"; 9 | import { TestERC721 } from "../tokens/TestERC721.sol"; 10 | 11 | contract BaseOrderTest is DSTestPlus { 12 | using stdStorage for StdStorage; 13 | 14 | StdStorage stdstore; 15 | 16 | uint256 constant MAX_INT = ~uint256(0); 17 | 18 | uint256 internal alicePk = 0xa11ce; 19 | uint256 internal bobPk = 0xb0b; 20 | uint256 internal calPk = 0xca1; 21 | uint256 internal feeReciever1Pk = 0xfee1; 22 | uint256 internal feeReciever2Pk = 0xfee2; 23 | address payable internal alice = payable(hevm.addr(alicePk)); 24 | address payable internal bob = payable(hevm.addr(bobPk)); 25 | address payable internal cal = payable(hevm.addr(calPk)); 26 | address payable internal feeReciever1 = payable(hevm.addr(feeReciever1Pk)); 27 | address payable internal feeReciever2 = payable(hevm.addr(feeReciever2Pk)); 28 | 29 | TestERC20 internal token1; 30 | TestERC20 internal token2; 31 | TestERC20 internal token3; 32 | // TestERC20 internal weth; 33 | WETH internal constant weth = 34 | WETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); 35 | 36 | // TestERC20 internal beth 37 | WETH internal constant beth = 38 | WETH(0x0000000000A39bb272e79075ade125fd351887Ac); 39 | 40 | TestERC721 internal test721_1; 41 | TestERC721 internal test721_2; 42 | TestERC721 internal test721_3; 43 | 44 | TestERC1155 internal test1155_1; 45 | TestERC1155 internal test1155_2; 46 | TestERC1155 internal test1155_3; 47 | 48 | address[] allTokens; 49 | TestERC20[] erc20s; 50 | address[] erc20Addresses; 51 | TestERC721[] erc721s; 52 | address[] erc721Addresses; 53 | TestERC1155[] erc1155s; 54 | address[] accounts; 55 | mapping(address => uint256) internal privateKeys; 56 | 57 | mapping(bytes32 => bool) originalMarketWriteSlots; 58 | 59 | event Transfer(address indexed from, address indexed to, uint256 value); 60 | 61 | event TransferSingle( 62 | address indexed operator, 63 | address indexed from, 64 | address indexed to, 65 | uint256 id, 66 | uint256 value 67 | ); 68 | 69 | struct RestoreERC20Balance { 70 | address token; 71 | address who; 72 | } 73 | 74 | function setUp() public virtual { 75 | hevm.label(alice, "alice"); 76 | hevm.label(bob, "bob"); 77 | hevm.label(cal, "cal"); 78 | hevm.label(address(this), "testContract"); 79 | 80 | privateKeys[alice] = alicePk; 81 | privateKeys[bob] = bobPk; 82 | privateKeys[cal] = calPk; 83 | 84 | _deployTestTokenContracts(); 85 | accounts = [alice, bob, cal, address(this)]; 86 | erc20s = [token1, token2, token3]; 87 | erc20Addresses = [ 88 | address(token1), 89 | address(token2), 90 | address(token3), 91 | address(weth), 92 | address(beth) 93 | ]; 94 | erc721s = [test721_1, test721_2, test721_3]; 95 | erc721Addresses = [ 96 | address(test721_1), 97 | address(test721_2), 98 | address(test721_3) 99 | ]; 100 | erc1155s = [test1155_1, test1155_2, test1155_3]; 101 | allTokens = [ 102 | address(token1), 103 | address(token2), 104 | address(token3), 105 | address(weth), 106 | address(beth), 107 | address(test721_1), 108 | address(test721_2), 109 | address(test721_3), 110 | address(test1155_1), 111 | address(test1155_2), 112 | address(test1155_3) 113 | ]; 114 | } 115 | 116 | /** 117 | * @dev deploy test token contracts 118 | */ 119 | function _deployTestTokenContracts() internal { 120 | token1 = new TestERC20(); 121 | token2 = new TestERC20(); 122 | token3 = new TestERC20(); 123 | test721_1 = new TestERC721(); 124 | test721_2 = new TestERC721(); 125 | test721_3 = new TestERC721(); 126 | test1155_1 = new TestERC1155(); 127 | test1155_2 = new TestERC1155(); 128 | test1155_3 = new TestERC1155(); 129 | hevm.label(address(token1), "token1"); 130 | hevm.label(address(weth), "weth"); 131 | hevm.label(address(beth), "beth"); 132 | hevm.label(address(test721_1), "test721_1"); 133 | hevm.label(address(test1155_1), "test1155_1"); 134 | hevm.label(address(feeReciever1), "feeReciever1"); 135 | hevm.label(address(feeReciever2), "feeReciever2"); 136 | } 137 | 138 | function _setApprovals( 139 | address _owner, 140 | address _erc20Target, 141 | address _erc721Target, 142 | address _erc1155Target 143 | ) internal { 144 | hevm.startPrank(_owner); 145 | for (uint256 i = 0; i < erc20s.length; i++) { 146 | erc20s[i].approve(_erc20Target, MAX_INT); 147 | } 148 | weth.approve(_erc20Target, MAX_INT); 149 | for (uint256 i = 0; i < erc721s.length; i++) { 150 | erc721s[i].setApprovalForAll(_erc721Target, true); 151 | } 152 | for (uint256 i = 0; i < erc1155s.length; i++) { 153 | erc1155s[i].setApprovalForAll( 154 | _erc1155Target != address(0) ? _erc1155Target : _erc721Target, 155 | true 156 | ); 157 | } 158 | 159 | hevm.stopPrank(); 160 | } 161 | 162 | /** 163 | * @dev reset written token storage slots to 0 and reinitialize 164 | * uint128(MAX_INT) erc20 balances for 3 test accounts and this. 165 | */ 166 | function _resetStorageAndEth(address market) internal { 167 | _resetTokensStorage(); 168 | _restoreEthBalances(); 169 | _resetMarketStorage(market); 170 | hevm.record(); 171 | } 172 | 173 | function _restoreEthBalances() internal { 174 | for (uint256 i = 0; i < accounts.length; i++) { 175 | hevm.deal(accounts[i], uint128(MAX_INT)); 176 | } 177 | hevm.deal(feeReciever1, 0); 178 | hevm.deal(feeReciever2, 0); 179 | } 180 | 181 | /** 182 | * @dev Reset market storage between runs to allow for duplicate orders 183 | */ 184 | function _resetMarketStorage(address market) internal { 185 | if (!originalMarketWriteSlots[0]) { 186 | (, bytes32[] memory writeSlots1) = hevm.accesses(market); 187 | for (uint256 i = 0; i < writeSlots1.length; i++) { 188 | originalMarketWriteSlots[writeSlots1[i]] = true; 189 | } 190 | originalMarketWriteSlots[0] = true; 191 | } 192 | (, bytes32[] memory writeSlots) = hevm.accesses(market); 193 | for (uint256 i = 0; i < writeSlots.length; i++) { 194 | if (originalMarketWriteSlots[writeSlots[i]]) continue; 195 | 196 | hevm.store(market, writeSlots[i], bytes32(0)); 197 | 198 | // Handle the Blur reentrancy guard. 199 | if ( 200 | market == 0xb2ecfE4E4D61f8790bbb9DE2D1259B9e2410CEA5 && 201 | writeSlots[i] == bytes32(uint256(0xfb)) 202 | ) { 203 | hevm.store(market, writeSlots[i], bytes32(uint256(1))); 204 | } 205 | } 206 | } 207 | 208 | function _resetTokensStorage() internal { 209 | for (uint256 i = 0; i < allTokens.length; i++) { 210 | _resetStorage(allTokens[i]); 211 | } 212 | } 213 | 214 | /** 215 | * @dev reset all storage written at an address thus far to 0; will 216 | * overwrite totalSupply()for ERC20s but that should be fine with the 217 | * goal of resetting the balances and owners of tokens - but note: 218 | * should be careful about approvals, etc 219 | * 220 | * note: must be called in conjunction with vm.record() 221 | */ 222 | function _resetStorage(address _addr) internal { 223 | (, bytes32[] memory writeSlots) = hevm.accesses(_addr); 224 | for (uint256 i = 0; i < writeSlots.length; i++) { 225 | hevm.store(_addr, writeSlots[i], bytes32(0)); 226 | } 227 | } 228 | 229 | receive() external payable virtual {} 230 | } 231 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@solidity-parser/parser@^0.14.0": 6 | version "0.14.2" 7 | resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.2.tgz#2d8f2bddb217621df882ceeae7d7b42ae8664db3" 8 | integrity sha512-10cr0s+MtRtqjEw0WFJrm2rwULN30xx7btd/v9cmqME2617/2M5MbHDkFIGIGTa7lwNw4bN9mVGfhlLzrYw8pA== 9 | dependencies: 10 | antlr4ts "^0.5.0-alpha.4" 11 | 12 | almost-equal@^1.1.0: 13 | version "1.1.0" 14 | resolved "https://registry.yarnpkg.com/almost-equal/-/almost-equal-1.1.0.tgz#f851c631138757994276aa2efbe8dfa3066cccdd" 15 | integrity sha512-0V/PkoculFl5+0Lp47JoxUcO0xSxhIBvm+BxHdD/OgXNmdRpRHCFnKVuUoWyS9EzQP+otSGv0m9Lb4yVkQBn2A== 16 | 17 | ansi-regex@^5.0.1: 18 | version "5.0.1" 19 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 20 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 21 | 22 | antlr4ts@^0.5.0-alpha.4: 23 | version "0.5.0-alpha.4" 24 | resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" 25 | integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== 26 | 27 | child_process@^1.0.2: 28 | version "1.0.2" 29 | resolved "https://registry.yarnpkg.com/child_process/-/child_process-1.0.2.tgz#b1f7e7fc73d25e7fd1d455adc94e143830182b5a" 30 | integrity sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g== 31 | 32 | clamp@^1.0.1: 33 | version "1.0.1" 34 | resolved "https://registry.yarnpkg.com/clamp/-/clamp-1.0.1.tgz#66a0e64011816e37196828fdc8c8c147312c8634" 35 | integrity sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA== 36 | 37 | color-interpolate@^1.0.5: 38 | version "1.0.5" 39 | resolved "https://registry.yarnpkg.com/color-interpolate/-/color-interpolate-1.0.5.tgz#d5710ce4244bd8b9feeda003f409edd4073b6217" 40 | integrity sha512-EcWwYtBJdbeHyYq/y5QwVWLBUm4s7+8K37ycgO9OdY6YuAEa0ywAY+ItlAxE1UO5bXW4ugxNhStTV3rsTZ35ZA== 41 | dependencies: 42 | clamp "^1.0.1" 43 | color-parse "^1.2.0" 44 | color-space "^1.14.3" 45 | lerp "^1.0.3" 46 | 47 | color-name@^1.0.0: 48 | version "1.1.4" 49 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 50 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 51 | 52 | color-parse@^1.2.0, color-parse@^1.4.2: 53 | version "1.4.2" 54 | resolved "https://registry.yarnpkg.com/color-parse/-/color-parse-1.4.2.tgz#78651f5d34df1a57f997643d86f7f87268ad4eb5" 55 | integrity sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA== 56 | dependencies: 57 | color-name "^1.0.0" 58 | 59 | color-space@^1.14.3: 60 | version "1.16.0" 61 | resolved "https://registry.yarnpkg.com/color-space/-/color-space-1.16.0.tgz#611781bca41cd8582a1466fd9e28a7d3d89772a2" 62 | integrity sha512-A6WMiFzunQ8KEPFmj02OnnoUnqhmSaHaZ/0LVFcPTdlvm8+3aMJ5x1HRHy3bDHPkovkf4sS0f4wsVvwk71fKkg== 63 | dependencies: 64 | hsluv "^0.0.3" 65 | mumath "^3.3.4" 66 | 67 | emoji-regex@^10.0.0: 68 | version "10.1.0" 69 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.1.0.tgz#d50e383743c0f7a5945c47087295afc112e3cf66" 70 | integrity sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg== 71 | 72 | emoji-regex@^8.0.0: 73 | version "8.0.0" 74 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 75 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 76 | 77 | escape-string-regexp@^4.0.0: 78 | version "4.0.0" 79 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 80 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 81 | 82 | hsluv@^0.0.3: 83 | version "0.0.3" 84 | resolved "https://registry.yarnpkg.com/hsluv/-/hsluv-0.0.3.tgz#829107dafb4a9f8b52a1809ed02e091eade6754c" 85 | integrity sha512-08iL2VyCRbkQKBySkSh6m8zMUa3sADAxGVWs3Z1aPcUkTJeK0ETG4Fc27tEmQBGUAXZjIsXOZqBvacuVNSC/fQ== 86 | 87 | is-fullwidth-code-point@^3.0.0: 88 | version "3.0.0" 89 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 90 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 91 | 92 | lerp@^1.0.3: 93 | version "1.0.3" 94 | resolved "https://registry.yarnpkg.com/lerp/-/lerp-1.0.3.tgz#a18c8968f917896de15ccfcc28d55a6b731e776e" 95 | integrity sha512-70Rh4rCkJDvwWiTsyZ1HmJGvnyfFah4m6iTux29XmasRiZPDBpT9Cfa4ai73+uLZxnlKruUS62jj2lb11wURiA== 96 | 97 | lru-cache@^6.0.0: 98 | version "6.0.0" 99 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 100 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 101 | dependencies: 102 | yallist "^4.0.0" 103 | 104 | mumath@^3.3.4: 105 | version "3.3.4" 106 | resolved "https://registry.yarnpkg.com/mumath/-/mumath-3.3.4.tgz#48d4a0f0fd8cad4e7b32096ee89b161a63d30bbf" 107 | integrity sha512-VAFIOG6rsxoc7q/IaY3jdjmrsuX9f15KlRLYTHmixASBZkZEKC1IFqE2BC5CdhXmK6WLM1Re33z//AGmeRI6FA== 108 | dependencies: 109 | almost-equal "^1.1.0" 110 | 111 | prettier-plugin-solidity@^1.0.0-beta.13: 112 | version "1.0.0-beta.19" 113 | resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.19.tgz#7c3607fc4028f5e6a425259ff03e45eedf733df3" 114 | integrity sha512-xxRQ5ZiiZyUoMFLE9h7HnUDXI/daf1tnmL1msEdcKmyh7ZGQ4YklkYLC71bfBpYU2WruTb5/SFLUaEb3RApg5g== 115 | dependencies: 116 | "@solidity-parser/parser" "^0.14.0" 117 | emoji-regex "^10.0.0" 118 | escape-string-regexp "^4.0.0" 119 | semver "^7.3.5" 120 | solidity-comments-extractor "^0.0.7" 121 | string-width "^4.2.3" 122 | 123 | prettier@^2.3.1: 124 | version "2.7.1" 125 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" 126 | integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== 127 | 128 | semver@^7.3.5: 129 | version "7.5.4" 130 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" 131 | integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== 132 | dependencies: 133 | lru-cache "^6.0.0" 134 | 135 | solidity-comments-extractor@^0.0.7: 136 | version "0.0.7" 137 | resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" 138 | integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== 139 | 140 | string-width@^4.2.3: 141 | version "4.2.3" 142 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 143 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 144 | dependencies: 145 | emoji-regex "^8.0.0" 146 | is-fullwidth-code-point "^3.0.0" 147 | strip-ansi "^6.0.1" 148 | 149 | strip-ansi@^6.0.1: 150 | version "6.0.1" 151 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 152 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 153 | dependencies: 154 | ansi-regex "^5.0.1" 155 | 156 | yallist@^4.0.0: 157 | version "4.0.0" 158 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 159 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 160 | --------------------------------------------------------------------------------