From 94d5dcc1a721f70ec5015fd0b1301f1ce237cf7a Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Tue, 29 Aug 2023 15:40:11 +0200 Subject: [PATCH 01/49] Feat/batch burn (#1051) * feat(batch_burn): add batch burn function * fix(docs): update SemiFungible1155 docs * chore(lint): cleanup lint ignores * chore(lint): defender lint errors * chore(deploy): reduce optimizer run for kb limit * chore(script): update upgrade script * feat(gha): split graph deploy develop-main * chore(lint): line length rule to warn from err * chore(gha): run CI on PR to develop * chore(gha): run e2e,ci on pr,push to develop * feat(graph): update graph for burn methods --- .github/workflows/ci-default.yml | 4 +- .github/workflows/deploy-graph.yml | 11 +- .github/workflows/e2e-tests.yml | 2 + .lintstagedignore | 10 + .lintstagedrc | 2 +- contracts/.openzeppelin/goerli.json | 365 +++ contracts/.solhint.json | 2 +- contracts/foundry.toml | 2 +- contracts/hardhat.config.ts | 2 +- contracts/src/HypercertMinter.sol | 18 + contracts/src/SemiFungible1155.sol | 236 +- contracts/src/interfaces/IHypercertToken.sol | 4 + contracts/tasks/upgrade.ts | 8 +- contracts/test/foundry/AllowlistMinter.t.sol | 6 +- .../foundry/HypercertMinter.transfers.t.sol | 6 +- .../foundry/SemiFungible1155.burning.t.sol | 65 + contracts/test/foundry/SemiFungibleHelper.sol | 17 +- defender/.eslintrc.yml | 2 +- defender/src/rollout.ts | 2 +- defender/src/setup.ts | 15 +- defender/src/update.ts | 10 +- docs/.eslintrc.yml | 27 + .../api/contracts/HypercertMinter.md | 39 +- .../api/contracts/SemiFungible1155.md | 28 +- .../contracts/interfaces/IHypercertToken.md | 17 + docs/package.json | 1 + frontend/.eslintrc.json | 5 - graph/.eslintrc.yml | 11 + graph/abis/HypercertMinter.json | 2189 +++++++++-------- .../HypercertMinter/HypercertMinter.ts | 255 +- graph/package.json | 6 +- graph/src/hypercert-minter.ts | 83 +- graph/tests/.latest.json | 2 +- graph/tests/hypercert-minter-burn.test.ts | 193 ++ graph/tests/hypercert-minter-utils.ts | 147 +- package.json | 3 +- yarn.lock | 10 +- 37 files changed, 2456 insertions(+), 1349 deletions(-) create mode 100644 .lintstagedignore create mode 100644 docs/.eslintrc.yml create mode 100644 graph/.eslintrc.yml create mode 100644 graph/tests/hypercert-minter-burn.test.ts diff --git a/.github/workflows/ci-default.yml b/.github/workflows/ci-default.yml index 77129584..5583e41f 100644 --- a/.github/workflows/ci-default.yml +++ b/.github/workflows/ci-default.yml @@ -21,11 +21,13 @@ on: push: branches: - main + - develop # Or when a pull request event occurs for a pull request against one of the # matched branches. pull_request: branches: - main + - develop # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -62,7 +64,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly-87bc53fc6c874bd4c92d97ed180b949e3a36d78c + version: nightly-bff4ed912bb023d7bf9b20eda581aa4867a1cf70 - name: Install run: | yarn install --immutable diff --git a/.github/workflows/deploy-graph.yml b/.github/workflows/deploy-graph.yml index 2511214a..a0781842 100644 --- a/.github/workflows/deploy-graph.yml +++ b/.github/workflows/deploy-graph.yml @@ -8,7 +8,8 @@ on: # A push occurs to one of the matched branches. push: branches: - - main + - main + - develop paths: - graph/** # Allows you to run this workflow manually from the Actions tab @@ -34,5 +35,9 @@ jobs: run: yarn install --immutable - name: Build the subgraph run: yarn build:graph - - name: Deploy the subgraph - run: yarn deploy:graph \ No newline at end of file + - name: Deploy the subgraph to goerli testnet + if: github.ref == 'refs/heads/develop' + run: yarn deploy:graph:goerli + - name: Deploy the subgraph to Optimism mainnet + if: github.ref == 'refs/heads/main' + run: yarn deploy:graph:optimism diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 33c3be37..1337bfe4 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -16,11 +16,13 @@ on: push: branches: - main + - develop # Or when a pull request event occurs for a pull request against one of the # matched branches. pull_request: branches: - main + - develop # Allows you to run this workflow manually from the Actions tab workflow_dispatch: diff --git a/.lintstagedignore b/.lintstagedignore new file mode 100644 index 00000000..339baae4 --- /dev/null +++ b/.lintstagedignore @@ -0,0 +1,10 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# root config +playwright.config.ts + +# patterns +graph/generated/ +e2e +docs +vendor \ No newline at end of file diff --git a/.lintstagedrc b/.lintstagedrc index 327ce68e..ad678de5 100644 --- a/.lintstagedrc +++ b/.lintstagedrc @@ -1,6 +1,6 @@ { "**/*.{js,jsx,ts,tsx,sol}": [ - "eslint --ignore-path .gitignore --ignore-pattern sdk/ --ignore-pattern graph/generated/", + "eslint --ignore-path .gitignore --ignore-path .lintstagedignore", "prettier --write" ], "**/*.{md,json}": ["prettier --write"] diff --git a/contracts/.openzeppelin/goerli.json b/contracts/.openzeppelin/goerli.json index e9968158..f6d23067 100644 --- a/contracts/.openzeppelin/goerli.json +++ b/contracts/.openzeppelin/goerli.json @@ -4403,6 +4403,371 @@ } } } + }, + "a74a0b26cd000c4d5c3717e7e2b2c4060405bf4c2f315356073581f711bf134d": { + "address": "0xDb77A1fDC905685B4052a512522D502638DdA5E3", + "txHash": "0xfe64805f07143e91ce6d02ce69e95c21f688a0cc083495baafba764274de05ff", + "layout": { + "solcVersion": "0.8.16", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_balances", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:25" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:28" + }, + { + "label": "_uri", + "offset": 0, + "slot": "103", + "type": "t_string_storage", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "104", + "type": "t_array(t_uint256)47_storage", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:528" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1155BurnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol:52" + }, + { + "label": "_baseURI", + "offset": 0, + "slot": "201", + "type": "t_string_storage", + "contract": "ERC1155URIStorageUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol:27" + }, + { + "label": "_tokenURIs", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_uint256,t_string_storage)", + "contract": "ERC1155URIStorageUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol:30" + }, + { + "label": "__gap", + "offset": 0, + "slot": "203", + "type": "t_array(t_uint256)48_storage", + "contract": "ERC1155URIStorageUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol:77" + }, + { + "label": "_owner", + "offset": 0, + "slot": "251", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "301", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "351", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol:107" + }, + { + "label": "typeCounter", + "offset": 0, + "slot": "401", + "type": "t_uint256", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:27" + }, + { + "label": "owners", + "offset": 0, + "slot": "402", + "type": "t_mapping(t_uint256,t_address)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:38" + }, + { + "label": "creators", + "offset": 0, + "slot": "403", + "type": "t_mapping(t_uint256,t_address)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:41" + }, + { + "label": "tokenValues", + "offset": 0, + "slot": "404", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:44" + }, + { + "label": "maxIndex", + "offset": 0, + "slot": "405", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:47" + }, + { + "label": "__gap", + "offset": 0, + "slot": "406", + "type": "t_array(t_uint256)25_storage", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:612" + }, + { + "label": "merkleRoots", + "offset": 0, + "slot": "431", + "type": "t_mapping(t_uint256,t_bytes32)", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:17" + }, + { + "label": "hasBeenClaimed", + "offset": 0, + "slot": "432", + "type": "t_mapping(t_uint256,t_mapping(t_bytes32,t_bool))", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:18" + }, + { + "label": "maxUnits", + "offset": 0, + "slot": "433", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:19" + }, + { + "label": "minted", + "offset": 0, + "slot": "434", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "435", + "type": "t_array(t_uint256)26_storage", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:69" + }, + { + "label": "_paused", + "offset": 0, + "slot": "461", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "462", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:116" + }, + { + "label": "typeRestrictions", + "offset": 0, + "slot": "511", + "type": "t_mapping(t_uint256,t_enum(TransferRestrictions)6957)", + "contract": "HypercertMinter", + "src": "src/HypercertMinter.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "512", + "type": "t_array(t_uint256)29_storage", + "contract": "HypercertMinter", + "src": "src/HypercertMinter.sol:246" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)25_storage": { + "label": "uint256[25]", + "numberOfBytes": "800" + }, + "t_array(t_uint256)26_storage": { + "label": "uint256[26]", + "numberOfBytes": "832" + }, + "t_array(t_uint256)29_storage": { + "label": "uint256[29]", + "numberOfBytes": "928" + }, + "t_array(t_uint256)47_storage": { + "label": "uint256[47]", + "numberOfBytes": "1504" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_enum(TransferRestrictions)6957": { + "label": "enum IHypercertToken.TransferRestrictions", + "members": [ + "AllowAll", + "DisallowAll", + "FromCreatorOnly" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_bytes32)": { + "label": "mapping(uint256 => bytes32)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_enum(TransferRestrictions)6957)": { + "label": "mapping(uint256 => enum IHypercertToken.TransferRestrictions)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_bytes32,t_bool))": { + "label": "mapping(uint256 => mapping(bytes32 => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_string_storage)": { + "label": "mapping(uint256 => string)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } } } } diff --git a/contracts/.solhint.json b/contracts/.solhint.json index 47f2ca08..4f59f59c 100644 --- a/contracts/.solhint.json +++ b/contracts/.solhint.json @@ -4,7 +4,7 @@ "code-complexity": ["error", 8], "compiler-version": ["error", "0.8.16"], "func-visibility": ["error", { "ignoreConstructors": true }], - "max-line-length": ["error", 120], + "max-line-length": ["warn", 120], "no-console": "off", "not-rely-on-time": "off", "reason-string": ["warn", { "maxLength": 64 }] diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 20f19235..bf1b6bfc 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -7,7 +7,7 @@ fuzz = { runs = 1025 } gas_reports = ["*"] libs = ["lib"] optimizer = true -optimizer_runs = 10_000 +optimizer_runs = 5_000 out = "out" solc = "0.8.16" src = "src" diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index e33ec241..5bd44b81 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -140,7 +140,7 @@ const config: HardhatUserConfig = { settings: { optimizer: { enabled: true, - runs: 10_000, + runs: 5_000, }, }, }, diff --git a/contracts/src/HypercertMinter.sol b/contracts/src/HypercertMinter.sol index 917c02c5..4a2e274d 100644 --- a/contracts/src/HypercertMinter.sol +++ b/contracts/src/HypercertMinter.sol @@ -139,6 +139,24 @@ contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, _burnToken(_account, _tokenID); } + /// @notice Burn a claimtoken + /// @dev see {IHypercertToken} + function batchBurnFraction(address _account, uint256[] memory _tokenIDs) external whenNotPaused { + _batchBurnToken(_account, _tokenIDs); + } + + /// @notice Burn a claimtoken; override is needed to update units/values + /// @dev see {ERC1155Burnable} + function burn(address account, uint256 id, uint256 value) public override whenNotPaused { + _burnToken(account, id); + } + + /// @notice Batch burn claimtokens; override is needed to update units/values + /// @dev see {ERC1155Burnable} + function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public override whenNotPaused { + _batchBurnToken(account, ids); + } + /// @dev see {IHypercertToken} function unitsOf(uint256 tokenID) external view override returns (uint256 units) { units = _unitsOf(tokenID); diff --git a/contracts/src/SemiFungible1155.sol b/contracts/src/SemiFungible1155.sol index cd88714a..7239109d 100644 --- a/contracts/src/SemiFungible1155.sol +++ b/contracts/src/SemiFungible1155.sol @@ -62,40 +62,72 @@ contract SemiFungible1155 is __UUPSUpgradeable_init(); } - /// @dev Get index of fractional token at `_id` by returning lower 128 bit values - /// @dev Returns 0 if `_id` is a baseType + /** + * @dev Returns the index of the fractional token at `_id` by returning lower 128 bit values. + * @param tokenID The ID of the token to query. + * @return The index of the fractional token. + * @dev This function returns 0 if `_id` is a baseType. + */ function getItemIndex(uint256 tokenID) internal pure returns (uint256) { return tokenID & NF_INDEX_MASK; } - /// @dev Get base type ID for token at `_id` by returning upper 128 bit values + /** + * @dev Get base type ID for token at `_id` by returning upper 128 bit values. + * @param tokenID The ID of the token to query. + * @return The base type ID of the token. + */ function getBaseType(uint256 tokenID) internal pure returns (uint256) { return tokenID & TYPE_MASK; } - /// @dev Identify that token at `_id` is base type. - /// @dev Upper 128 bits identify base type ID, lower bits should be 0 + /** + * @dev Identify that token at `_id` is base type. + * @param tokenID The ID of the token to query. + * @return A boolean indicating whether the token is a base type. + * @dev Upper 128 bits identify base type ID, lower bits should be 0. + */ function isBaseType(uint256 tokenID) internal pure returns (bool) { return (tokenID & TYPE_MASK == tokenID) && (tokenID & NF_INDEX_MASK == 0); } - /// @dev Identify that token at `_id` is fraction of a claim. - /// @dev Upper 128 bits identify base type ID, lower bits should be > 0 + /** + * @dev Returns a boolean indicating whether the token at `_id` belongs to a base type. + * @param tokenID The ID of the token to query. + * @return A boolean indicating whether the token is a typed item. + * @dev Upper 128 bits identify the type ID, lower bits identify the index of the typed item. + */ function isTypedItem(uint256 tokenID) internal pure returns (bool) { return (tokenID & TYPE_MASK != 0) && (tokenID & NF_INDEX_MASK != 0); } /// READ + /** + * @dev Returns the owner of a given token ID. + * @param tokenID The ID of the token to query. + * @return _owner The address of the owner of the token. + */ function ownerOf(uint256 tokenID) public view returns (address _owner) { _owner = owners[tokenID]; } - /// @dev see {IHypercertToken} + /** + * @dev Returns the number of units of a given token ID. + * @param tokenID The ID of the token to query. + * @return units The number of units of the token. + * @dev This function is used internally to get the number of units of a token. + */ function _unitsOf(uint256 tokenID) internal view returns (uint256 units) { units = tokenValues[tokenID]; } - /// @dev see {IHypercertToken} + /** + * @dev Returns the number of units of a given token ID owned by a given account. + * @param account The address of the account to query. + * @param tokenID The ID of the token to query. + * @return units The number of units of the token owned by the account. + * @dev This function is used internally to get the number of units of a token owned by an account. + */ function _unitsOf(address account, uint256 tokenID) internal view returns (uint256 units) { // Check if fraction token and accounts owns it if (ownerOf(tokenID) == account) { @@ -105,8 +137,13 @@ contract SemiFungible1155 is /// MUTATE - /// @dev create token type ID based of token counter - + /** + * @dev Creates a new token type ID based on the token counter. + * @param _account The address of the account that will own the new token type. + * @param units The number of units associated with the new token type. + * @param _uri The URI for the metadata associated with the new token type. + * @return typeID The new token type ID. + */ function _createTokenType(address _account, uint256 units, string memory _uri) internal returns (uint256 typeID) { _notMaxType(typeCounter); typeID = ++typeCounter << 128; @@ -120,7 +157,18 @@ contract SemiFungible1155 is emit TransferSingle(_account, address(0), address(0), typeID, 0); } - /// @dev Mint a new token type and the initial units + /** + * @dev Mints a new token with a new token type ID and assigns it to the specified account. + * @param _account The address of the account that will receive the new token. + * @param _units The number of units associated with the new token. + * @param _uri The URI for the metadata associated with the new token. + * @return typeID The new token type ID. + * @dev This function creates a new token type ID by calling the `_createTokenType` function and then mints a new token with the new type ID. + * @dev The `tokenID` is calculated by adding the `typeID` to the current maximum index for the `typeID`. + * @dev The `tokenValues` mapping is updated with the number of units associated with the new token. + * @dev A `ValueTransfer` event is emitted to indicate that a new token has been minted and assigned to the specified account. + * @dev If `_units` is zero, the function will revert with an error. + */ function _mintNewTypeWithToken( address _account, uint256 _units, @@ -139,7 +187,19 @@ contract SemiFungible1155 is emit ValueTransfer(typeID, 0, tokenID, _units); } - /// @dev Mint a new token type and the initial fractions + /** + * @dev Mints a new token with a new token type ID and assigns it to the specified account. + * @param _account The address of the account that will receive the new token. + * @param _fractions An array of values associated with the new token. + * @param _uri The URI for the metadata associated with the new token. + * @return typeID The new token type ID. + * @dev This function creates a new token type ID by calling the `_createTokenType` function and then mints a new token with the new type ID. + * @dev The `tokenID` is calculated by adding the `typeID` to the current maximum index for the `typeID`. + * @dev The `tokenValues` mapping is updated with the number of units associated with the new token. + * @dev A `ValueTransfer` event is emitted to indicate that a new token has been minted and assigned to the specified account. + * @dev If any of the fractional values in `_fractions` are zero, the function will revert with an error. + * @dev This function also calls the `_splitTokenUnits` function to split the new token into multiple sub-tokens with the specified fractional values. + */ function _mintNewTypeWithTokens( address _account, uint256[] calldata _fractions, @@ -149,7 +209,17 @@ contract SemiFungible1155 is _splitTokenUnits(_account, typeID + maxIndex[typeID], _fractions); } - /// @dev Mint a new token for an existing type + /** + * @dev Mints a new token with the specified token type ID and assigns it to the specified account. + * @param _account The address of the account that will receive the new token. + * @param _typeID The ID of the token type to mint. + * @param _units The number of units associated with the new token. + * @return tokenID The ID of the newly minted token. + * @dev This function checks that the specified token type ID is a base type and that the maximum number of tokens for the token type has not been reached. + * @dev The function then calculates the new token ID by adding the specified token type ID to the current maximum index for the token type. + * @dev The `tokenValues` mapping is updated with the number of units associated with the new token. + * @dev A `ValueTransfer` event is emitted to indicate that a new token has been minted and assigned to the specified account. + */ function _mintToken(address _account, uint256 _typeID, uint256 _units) internal returns (uint256 tokenID) { if (!isBaseType(_typeID)) revert Errors.NotAllowed(); @@ -165,8 +235,17 @@ contract SemiFungible1155 is emit ValueTransfer(_typeID, 0, tokenID, _units); } - /// @dev Mint new tokens for existing types - /// @notice Enables batch claiming from multiple allowlists + /** + * @dev Mints multiple tokens with the specified token type IDs and assigns them to the specified account. + * @param _account The address of the account that will receive the new tokens. + * @param _typeIDs An array of token type IDs to mint. + * @param _units An array of numbers of units associated with the new tokens. + * @return tokenIDs An array of the IDs of the newly minted tokens. + * @dev This function checks that each specified token type ID is a base type and that the maximum number of tokens for each token type has not been reached. + * @dev The function then calculates the new token IDs by adding the specified token type IDs to the current maximum index for each token type. + * @dev The `tokenValues` mapping is updated with the number of units associated with each new token. + * @dev A `BatchValueTransfer` event is emitted to indicate that new tokens have been minted and assigned to the specified account. + */ function _batchMintTokens( address _account, uint256[] calldata _typeIDs, @@ -196,8 +275,17 @@ contract SemiFungible1155 is emit BatchValueTransfer(_typeIDs, zeroes, tokenIDs, _units); } - /// @dev Split the units of `_tokenID` owned by `account` across `_values` - /// @dev `_values` must sum to total `units` held at `_tokenID` + /** + * @dev Splits a token into multiple tokens with different unit values. + * @param _account The address of the account that will receive the new tokens. + * @param _tokenID The ID of the token to split. + * @param _values An array of numbers of units associated with the new tokens. + * @dev This function splits a token into multiple tokens with different unit values. + * @dev The `_values` array specifies the number of units associated with each new token. + * @dev The function checks that the length of the `_values` array is between 2 and `FRACTION_LIMIT`, and that the sum of the values in the `_values` array is equal to the number of units associated with the original token. + * @dev The function then creates new tokens with the specified unit values and assigns them to the specified account. + * @dev A `BatchValueTransfer` event is emitted to indicate that the original token has been split into multiple tokens. + */ function _splitTokenUnits(address _account, uint256 _tokenID, uint256[] calldata _values) internal { if (_values.length > FRACTION_LIMIT || _values.length < 2) revert Errors.ArraySize(); if (tokenValues[_tokenID] != _getSum(_values)) revert Errors.NotAllowed(); @@ -255,8 +343,18 @@ contract SemiFungible1155 is emit BatchValueTransfer(typeIDs, fromIDs, toIDs, values); } - /// @dev Merge the units of `_fractionIDs`. - /// @dev Base type of `_fractionIDs` must be identical for all tokens. + /** + * @dev Merges the units of multiple tokens into a single token. + * @param _account The address of the account that will receive the merged token. + * @param _fractionIDs An array of token IDs to merge. + * @dev This function merges the units of multiple tokens into a single token. + * @dev The `_fractionIDs` array specifies the IDs of the tokens to merge. + * @dev The function checks that the length of the `_fractionIDs` array is between 2 and `FRACTION_LIMIT`. + * @dev The function then calculates the total value of the merged token by summing the values of the tokens to be merged. + * @dev The `tokenValues` mapping is updated with the total value of the merged token. + * @dev The tokens to be merged are burned except the last one that receives all the units. + * @dev A `BatchValueTransfer` event is emitted to indicate that the tokens have been merged into a single token. + */ function _mergeTokensUnits(address _account, uint256[] memory _fractionIDs) internal { if (_fractionIDs.length > FRACTION_LIMIT || _fractionIDs.length < 2) { revert Errors.ArraySize(); @@ -301,9 +399,14 @@ contract SemiFungible1155 is _burnBatch(_account, fromIDs, amounts); } - /// @dev Burn the token at `_tokenID` owned by `_account` - /// @dev Not allowed to burn base type. - /// @dev `_tokenID` must hold all value declared at base type + /** + * @dev Burns a single token and emits a `ValueTransfer` event with a value of 0. + * @param _account The address of the account that owns the token to burn. + * @param _tokenID The ID of the token to burn. + * @dev This function burns a single token with the specified ID and emits a `ValueTransfer` event `toTokenID` 0. + * @dev The function checks that the caller is the owner of the token or is approved to burn the token on behalf of the owner. + * @dev The function then deletes the token from the `tokenValues` mapping and calls the `_burn` function to burn the token. + */ function _burnToken(address _account, uint256 _tokenID) internal { if (_account != _msgSender() && !isApprovedForAll(_account, _msgSender())) revert Errors.NotApprovedOrOwner(); @@ -315,9 +418,54 @@ contract SemiFungible1155 is emit ValueTransfer(getBaseType(_tokenID), _tokenID, 0, value); } + /** + * @dev Burns multiple tokens and emits a `BatchValueTransfer` event with a value of 0 for each token burned. + * @param _account The address of the account that owns the tokens to burn. + * @param _tokenIDs An array of token IDs to burn. + * @dev This function burns multiple tokens with the specified IDs and emits a `BatchValueTransfer` event. + * @dev The function checks that the caller is the owner of the tokens or is approved to burn the tokens on behalf of the owner. + * @dev The function then deletes the tokens from the `tokenValues` mapping and calls the `_burnBatch` function to burn the tokens. + * @dev Finally, the function emits a `BatchValueTransfer` event with a value of 1 and `toTokenIDs` as 0 for each token burned to indicate that the tokens have been burned. + */ + function _batchBurnToken(address _account, uint256[] memory _tokenIDs) internal { + if (_account != _msgSender() && !isApprovedForAll(_account, _msgSender())) revert Errors.NotApprovedOrOwner(); + + uint256 len = _tokenIDs.length; + + // ERC115 requires values + uint256[] memory claimIDs = new uint256[](len); + uint256[] memory toTokens = new uint256[](len); + uint256[] memory claimUnits = new uint256[](len); + uint256[] memory values = new uint256[](len); + + for (uint256 i; i < len; i++) { + uint256 _tokenId = _tokenIDs[i]; + uint256 value = tokenValues[_tokenId]; + + delete tokenValues[_tokenId]; + + claimIDs[i] = getBaseType(_tokenId); + claimUnits[i] = value; + values[i] = 1; + } + + _burnBatch(_account, _tokenIDs, values); + emit BatchValueTransfer(claimIDs, _tokenIDs, toTokens, claimUnits); + } + /// TRANSFERS // The following functions are overrides required by Solidity. + /** + * @dev Called after a token transfer has been completed. + * @param operator The address of the operator performing the transfer. + * @param from The address of the sender of the tokens. + * @param to The address of the recipient of the tokens. + * @param ids An array of token IDs that were transferred. + * @param amounts An array of token amounts that were transferred. + * @param data Additional data that was passed along with the transfer. + * @dev This function updates the `owners` mapping to reflect the new owner of each token that was transferred. + */ function _afterTokenTransfer( address operator, address from, @@ -338,6 +486,16 @@ contract SemiFungible1155 is } } + /** + * @dev Called before a batch of tokens is transferred. + * @param operator The address of the operator performing the transfer. + * @param from The address of the sender of the tokens. + * @param fromIDs An array of token IDs that are being transferred. + * @param toIDs An array of token IDs that the tokens are being transferred to. + * @param values An array of token amounts that are being transferred. + * @param data Additional data that was passed along with the transfer. + * @dev This function checks that the transfer is allowed by verifying that the sender is approved to transfer the tokens and that the tokens being transferred are of the same base type. + */ function _beforeUnitTransfer( address operator, address from, @@ -363,8 +521,14 @@ contract SemiFungible1155 is /// METADATA - /// @dev see { openzeppelin-contracts-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol } - /// @dev Always returns the URI for the basetype so that it's managed in one place. + /** + * @dev Returns the metadata URI for a given token ID. + * @param tokenID The ID of the token to retrieve the metadata URI for. + * @return _uri The metadata URI for the specified token ID. + * @dev This function retrieves the metadata URI for the specified token ID by calling the `uri` function of the `ERC1155URIStorageUpgradeable` contract. + * @dev The metadata URI is a string that points to a JSON file containing information about the token, such as its name, symbol, and image. + * @dev This function always returns the URI for the basetype so that it's managed in one place. + */ function uri( uint256 tokenID ) public view virtual override(ERC1155Upgradeable, ERC1155URIStorageUpgradeable) returns (string memory _uri) { @@ -375,7 +539,10 @@ contract SemiFungible1155 is /// UTILS /** - * @dev Check if value is below max item index + * @dev Checks if the specified token ID is below the maximum item index. + * @param tokenID The ID of the token to check. + * @dev This function checks if the specified token ID is below the maximum item index by converting the token ID to a `uint128` value and incrementing it. + * @dev If the token ID is greater than or equal to the maximum item index, the function will revert with an error. */ function _notMaxItem(uint256 tokenID) private pure { uint128 _count = uint128(tokenID); @@ -383,7 +550,10 @@ contract SemiFungible1155 is } /** - * @dev Check if value is below max type index + * @dev Checks if the specified token ID is below the maximum type index. + * @param tokenID The ID of the token to check. + * @dev This function checks if the specified token ID is below the maximum type index by shifting the token ID right by 128 bits to get the type ID and converting it to a `uint128` value. + * @dev If the type ID is greater than or equal to the maximum type index, the function will revert with an error. */ function _notMaxType(uint256 tokenID) private pure { uint128 _count = uint128(tokenID >> 128); @@ -391,7 +561,11 @@ contract SemiFungible1155 is } /** - * @dev calculate the sum of the elements of an array + * @dev Calculates the sum of the elements of an array. + * @param array The array of uint256 values to sum. + * @return sum The sum of the elements of the array. + * @dev This function calculates the sum of the elements of the specified array by iterating over the array and adding each element to a running total. + * @dev If an element in the array is 0, the function will revert with an error. */ function _getSum(uint256[] memory array) internal pure returns (uint256 sum) { uint256 len = array.length; @@ -404,6 +578,12 @@ contract SemiFungible1155 is } } + /** + * @dev Returns an array containing a single element. + * @param element The element to include in the array. + * @return An array containing a single element. + * @dev This function returns an array containing a single element by creating a new array with a length of 1 and setting the first element to the specified value. + */ function _getSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; diff --git a/contracts/src/interfaces/IHypercertToken.sol b/contracts/src/interfaces/IHypercertToken.sol index 1ed1e34e..fd3d4b5b 100644 --- a/contracts/src/interfaces/IHypercertToken.sol +++ b/contracts/src/interfaces/IHypercertToken.sol @@ -46,6 +46,10 @@ interface IHypercertToken { /// @notice Operator must be allowed by `creator` and the token must represent the total amount of available units. function burnFraction(address account, uint256 tokenID) external; + /// @dev Function to burn the tokens at `tokenIDs` for `account` + /// @notice Operator must be allowed by `creator` and the tokens must represent the total amount of available units. + function batchBurnFraction(address account, uint256[] memory tokenIDs) external; + /// @dev Returns the `units` held by a (fractional) token at `claimID` /// @dev If `tokenID` is a base type, the total amount of `units` for the claim is returned. /// @dev If `tokenID` is a fractional token, the `units` held by the token is returned diff --git a/contracts/tasks/upgrade.ts b/contracts/tasks/upgrade.ts index b2d87899..a4cd7a5b 100644 --- a/contracts/tasks/upgrade.ts +++ b/contracts/tasks/upgrade.ts @@ -45,10 +45,12 @@ task("propose-upgrade", "Propose an upgrade to OpenZeppelin Defender") .addParam("multisig", "Owner multisig address") .setAction(async ({ proxy, multisig }, { ethers, upgrades }) => { const HypercertMinter = await ethers.getContractFactory("HypercertMinter"); - console.log("Proposing upgrade.."); + console.log(`Proposing upgrade to multisig ${multisig} as address ${proxy}`); const proposal = await defender.proposeUpgrade(proxy, HypercertMinter, { - multisig + description: "Add batch burning methods", + multisig, + multisigType: "Gnosis Safe", + title: "Add batch burn", }); console.log("Upgrade proposal created at: ", proposal.url); }); - diff --git a/contracts/test/foundry/AllowlistMinter.t.sol b/contracts/test/foundry/AllowlistMinter.t.sol index 93cac1d6..569ea593 100644 --- a/contracts/test/foundry/AllowlistMinter.t.sol +++ b/contracts/test/foundry/AllowlistMinter.t.sol @@ -22,7 +22,7 @@ contract MerkleHelper is AllowlistMinter, Merkle { } } - function generateData(uint256 size, uint256 value) public view returns (bytes32[] memory data) { + function generateData(uint256 size, uint256 value) public pure returns (bytes32[] memory data) { data = new bytes32[](size); for (uint256 i = 0; i < size; i++) { address user = address(uint160(i + 1)); @@ -147,7 +147,7 @@ contract AllowlistTest is PRBTest, StdCheats, StdUtils { merkle.createAllowlist(claimID, root, size * units); - changePrank(address(1)); + startHoax(address(1)); bytes32[] memory proof = merkle.getProof(data, 0); merkle.processClaim(proof, claimID, units); @@ -190,7 +190,7 @@ contract AllowlistTest is PRBTest, StdCheats, StdUtils { merkle.createAllowlist(claimID, root, size * value); - changePrank(address(3)); + startHoax(address(3)); merkle.isAllowedToClaim(proof, claimID, data[2]); diff --git a/contracts/test/foundry/HypercertMinter.transfers.t.sol b/contracts/test/foundry/HypercertMinter.transfers.t.sol index 29d1b406..0b27131a 100644 --- a/contracts/test/foundry/HypercertMinter.transfers.t.sol +++ b/contracts/test/foundry/HypercertMinter.transfers.t.sol @@ -92,7 +92,7 @@ contract HypercertMinterTransferTest is PRBTest, StdCheats, StdUtils { vm.prank(alice); hypercertMinter.mintClaim(alice, _units, _uri, IHypercertToken.TransferRestrictions.AllowAll); - changePrank(bob); + startHoax(bob); vm.expectRevert("ERC1155: caller is not token owner or approved"); hypercertMinter.safeTransferFrom(alice, bob, tokenID, 1, ""); @@ -108,7 +108,7 @@ contract HypercertMinterTransferTest is PRBTest, StdCheats, StdUtils { vm.prank(alice); hypercertMinter.mintClaim(alice, _units, _uri, IHypercertToken.TransferRestrictions.DisallowAll); - changePrank(bob); + startHoax(bob); vm.expectRevert("ERC1155: caller is not token owner or approved"); hypercertMinter.safeTransferFrom(alice, bob, tokenID, 1, ""); @@ -125,7 +125,7 @@ contract HypercertMinterTransferTest is PRBTest, StdCheats, StdUtils { vm.prank(alice); hypercertMinter.mintClaim(alice, _units, _uri, IHypercertToken.TransferRestrictions.FromCreatorOnly); - changePrank(bob); + startHoax(bob); vm.expectRevert("ERC1155: caller is not token owner or approved"); hypercertMinter.safeTransferFrom(alice, bob, tokenID, 1, ""); diff --git a/contracts/test/foundry/SemiFungible1155.burning.t.sol b/contracts/test/foundry/SemiFungible1155.burning.t.sol index 5f212dcd..847c2138 100644 --- a/contracts/test/foundry/SemiFungible1155.burning.t.sol +++ b/contracts/test/foundry/SemiFungible1155.burning.t.sol @@ -35,6 +35,11 @@ contract SemiFungible1155BurnTest is PRBTest, StdCheats, StdUtils, SemiFungible1 semiFungible.mintValue(alice, values, _uri); semiFungible.validateOwnerBalanceUnits(tokenIDs[1], alice, 1, values[1]); + changePrank(bob); + vm.expectRevert(NotApprovedOrOwner.selector); + semiFungible.burnValue(alice, tokenIDs[1]); + + changePrank(alice); vm.expectEmit(true, true, true, true); emit TransferSingle(alice, alice, address(0), tokenIDs[1], 1); semiFungible.burnValue(alice, tokenIDs[1]); @@ -42,6 +47,50 @@ contract SemiFungible1155BurnTest is PRBTest, StdCheats, StdUtils, SemiFungible1 semiFungible.validateNotOwnerNoBalanceNoUnits(tokenIDs[1], alice); } + function testBatchBurnFractions() public { + uint256 baseID = 1 << 128; + + uint256 size = 20; + uint256 value = 2000; + uint256[] memory values = semiFungible.buildValues(size, value); + uint256[] memory tokenIDs = semiFungible.buildIDs(baseID, size); + + uint256[] memory valueToBurn = new uint256[](2); + valueToBurn[0] = 1; + valueToBurn[1] = 1; + uint256[] memory idsToBurn = new uint256[](2); + idsToBurn[0] = tokenIDs[1]; + idsToBurn[1] = tokenIDs[7]; + uint256[] memory toTokens = new uint256[](2); + toTokens[0] = 0; + toTokens[1] = 0; + + startHoax(alice, 100 ether); + + semiFungible.mintValue(alice, values, _uri); + semiFungible.validateOwnerBalanceUnits(tokenIDs[1], alice, 1, values[1]); + + assertEq(semiFungible.unitsOf(tokenIDs[7]), 2000); + assertEq(semiFungible.unitsOf(baseID), size * value); + + changePrank(bob); + vm.expectRevert(NotApprovedOrOwner.selector); + semiFungible.batchBurnValues(alice, idsToBurn); + + changePrank(alice); + vm.expectEmit(true, true, true, true); + emit TransferBatch(alice, alice, address(0), idsToBurn, valueToBurn); + semiFungible.batchBurnValues(alice, idsToBurn); + + semiFungible.validateNotOwnerNoBalanceNoUnits(tokenIDs[1], alice); + assertEq(semiFungible.unitsOf(tokenIDs[1]), 0); + + semiFungible.validateNotOwnerNoBalanceNoUnits(tokenIDs[7], alice); + assertEq(semiFungible.unitsOf(tokenIDs[7]), 0); + + assertEq(semiFungible.unitsOf(baseID), size * value); + } + function testCannotBurnClaim() public { uint256 size = 20; uint256 value = 2000; @@ -54,4 +103,20 @@ contract SemiFungible1155BurnTest is PRBTest, StdCheats, StdUtils, SemiFungible1 vm.expectRevert("ERC1155: burn amount exceeds balance"); semiFungible.burnValue(alice, baseID); } + + function testCannotBatchBurnClaim() public { + uint256 size = 20; + uint256 value = 2000; + uint256[] memory values = semiFungible.buildValues(size, value); + + startHoax(alice, 100 ether); + + uint256 baseID = semiFungible.mintValue(alice, values, _uri); + + uint256[] memory idsToBurn = new uint256[](1); + idsToBurn[0] = baseID; + + vm.expectRevert("ERC1155: burn amount exceeds balance"); + semiFungible.batchBurnValues(alice, idsToBurn); + } } diff --git a/contracts/test/foundry/SemiFungibleHelper.sol b/contracts/test/foundry/SemiFungibleHelper.sol index 4d43a810..3a702e8b 100644 --- a/contracts/test/foundry/SemiFungibleHelper.sol +++ b/contracts/test/foundry/SemiFungibleHelper.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; + import { SemiFungible1155 } from "../../src/SemiFungible1155.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; @@ -51,6 +52,10 @@ contract SemiFungible1155Helper is SemiFungible1155, PRBTest, StdCheats, StdUtil _burnToken(account, tokenID); } + function batchBurnValues(address account, uint256[] memory tokenIDs) public { + _batchBurnToken(account, tokenIDs); + } + function unitsOf(uint256 tokenID) public view returns (uint256) { return _unitsOf(tokenID); } @@ -86,18 +91,24 @@ contract SemiFungible1155Helper is SemiFungible1155, PRBTest, StdCheats, StdUtil return 0; } sum = 0; - for (uint256 i = 0; i < array.length; i++) sum += array[i]; + for (uint256 i = 0; i < array.length; i++) { + sum += array[i]; + } } function buildValues(uint256 size, uint256 base) public pure returns (uint256[] memory) { uint256[] memory _values = new uint256[](size); - for (uint256 i = 0; i < size; i++) _values[i] = base; + for (uint256 i = 0; i < size; i++) { + _values[i] = base; + } return _values; } function buildIDs(uint256 baseID, uint256 size) public pure returns (uint256[] memory) { uint256[] memory _values = new uint256[](size); - for (uint256 i = 0; i < size; i++) _values[i] = baseID + i + 1; + for (uint256 i = 0; i < size; i++) { + _values[i] = baseID + i + 1; + } return _values; } diff --git a/defender/.eslintrc.yml b/defender/.eslintrc.yml index fb4528bd..07ab4df0 100644 --- a/defender/.eslintrc.yml +++ b/defender/.eslintrc.yml @@ -9,7 +9,7 @@ parserOptions: plugins: - "@typescript-eslint" root: true -ignorePatterns: ["rollup.config.js", "jest.config.ts", "build/"] +ignorePatterns: ["build/"] rules: "@typescript-eslint/semi": - warn diff --git a/defender/src/rollout.ts b/defender/src/rollout.ts index ebce74ae..6679b7d0 100644 --- a/defender/src/rollout.ts +++ b/defender/src/rollout.ts @@ -1,7 +1,7 @@ import { createTask } from "./create-autotask.js"; import { createSentinel } from "./create-sentinel.js"; import { encodeName } from "./networks.js"; -import { ApiError, ConfigError } from "./errors.js"; +import { ApiError } from "./errors.js"; import config from "./config.js"; export const rollOut = async () => { diff --git a/defender/src/setup.ts b/defender/src/setup.ts index ad0c212b..ed7d407f 100644 --- a/defender/src/setup.ts +++ b/defender/src/setup.ts @@ -1,11 +1,10 @@ import config from "./config.js"; - -import { ApiError, ConfigError } from "./errors.js"; +import { ConfigError } from "./errors.js"; import { reset } from "./reset.js"; +import { rollOut } from "./rollout.js"; +import { updateAutotask, updateSentinel } from "./update.js"; import { AutotaskClient } from "defender-autotask-client"; import { SentinelClient } from "defender-sentinel-client"; -import { updateAutotask, updateSentinel } from "./update.js"; -import { rollOut } from "./rollout.js"; const setup = async () => { const autotaskClient = new AutotaskClient(config.credentials); @@ -19,12 +18,12 @@ const setup = async () => { if (oldAutoTasks.items.length > 0) { updates = true; - updateAutotask(); + await updateAutotask(); } if (oldSentinels.items.length > 0) { updates = true; - updateSentinel(); + await updateSentinel(); } if (!updates) { @@ -36,8 +35,8 @@ const setup = async () => { throw new ConfigError("No networks specified"); } - rollOut(); + await rollOut(); } }; -setup(); +void setup(); diff --git a/defender/src/update.ts b/defender/src/update.ts index 5158ba84..4db80c24 100644 --- a/defender/src/update.ts +++ b/defender/src/update.ts @@ -14,7 +14,10 @@ export const updateAutotask = async () => { autotaskClient .updateCodeFromFolder(autoTask.autotaskId, `./build/relay/${name}`) .then((res) => { - console.log(`Updated ${autoTask.autotaskId}`); + console.log(`Updated ${autoTask.autotaskId}: ${res}`); + }) + .catch((err) => { + console.log(`Error updating ${autoTask.autotaskId}: ${err}`); }); }), ]); @@ -38,7 +41,10 @@ export const updateSentinel = async () => { abi, }) .then((res) => { - console.log("Updated: ", res); + console.log(`Updated ${sentinel.name}: ${res}`); + }) + .catch((err) => { + console.log(`Error updating ${sentinel.name}: ${err}`); }); }), ]); diff --git a/docs/.eslintrc.yml b/docs/.eslintrc.yml new file mode 100644 index 00000000..c1258f9f --- /dev/null +++ b/docs/.eslintrc.yml @@ -0,0 +1,27 @@ +extends: + - "eslint:recommended" + - "plugin:@typescript-eslint/eslint-recommended" + - "plugin:@typescript-eslint/recommended" + - "prettier" +parser: "@typescript-eslint/parser" +parserOptions: + project: "./docs/tsconfig.json" +plugins: + - "@docusaurus" + - "@typescript-eslint" +root: true +ignorePatterns: ["build/"] +rules: + "@typescript-eslint/semi": + - warn + "@typescript-eslint/switch-exhaustiveness-check": + - warn + "@typescript-eslint/no-floating-promises": + - error + - ignoreIIFE: true + ignoreVoid: true + "@typescript-eslint/no-inferrable-types": "off" + "@typescript-eslint/no-unused-vars": + - error + - argsIgnorePattern: "_" + varsIgnorePattern: "_" diff --git a/docs/docs/developer/api/contracts/HypercertMinter.md b/docs/docs/developer/api/contracts/HypercertMinter.md index 785dd5cf..012e3d60 100644 --- a/docs/docs/developer/api/contracts/HypercertMinter.md +++ b/docs/docs/developer/api/contracts/HypercertMinter.md @@ -60,6 +60,23 @@ _See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have t | ---- | --------- | ----------- | | \_0 | uint256[] | undefined | +### batchBurnFraction + +```solidity +function batchBurnFraction(address _account, uint256[] _tokenIDs) external nonpayable +``` + +Burn a claimtoken + +_see {IHypercertToken}_ + +#### Parameters + +| Name | Type | Description | +| ---------- | --------- | ----------- | +| \_account | address | undefined | +| \_tokenIDs | uint256[] | undefined | + ### batchMintClaimsFromAllowlists ```solidity @@ -85,6 +102,10 @@ _Calls AllowlistMinter to verify `proofs`.Mints the `amount` of units for the hy function burn(address account, uint256 id, uint256 value) external nonpayable ``` +Burn a claimtoken; override is needed to update units/values + +_see {ERC1155Burnable}_ + #### Parameters | Name | Type | Description | @@ -99,6 +120,10 @@ function burn(address account, uint256 id, uint256 value) external nonpayable function burnBatch(address account, uint256[] ids, uint256[] values) external nonpayable ``` +Batch burn claimtokens; override is needed to update units/values + +_see {ERC1155Burnable}_ + #### Parameters | Name | Type | Description | @@ -319,19 +344,19 @@ _Returns the address of the current owner._ function ownerOf(uint256 tokenID) external view returns (address _owner) ``` -READ +_Returns the owner of a given token ID._ #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | +| Name | Type | Description | +| ------- | ------- | ----------------------------- | +| tokenID | uint256 | The ID of the token to query. | #### Returns -| Name | Type | Description | -| ------- | ------- | ----------- | -| \_owner | address | undefined | +| Name | Type | Description | +| ------- | ------- | -------------------------------------- | +| \_owner | address | The address of the owner of the token. | ### pause diff --git a/docs/docs/developer/api/contracts/SemiFungible1155.md b/docs/docs/developer/api/contracts/SemiFungible1155.md index 444dfe22..a4086e37 100644 --- a/docs/docs/developer/api/contracts/SemiFungible1155.md +++ b/docs/docs/developer/api/contracts/SemiFungible1155.md @@ -129,19 +129,19 @@ _Returns the address of the current owner._ function ownerOf(uint256 tokenID) external view returns (address _owner) ``` -READ +_Returns the owner of a given token ID._ #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | +| Name | Type | Description | +| ------- | ------- | ----------------------------- | +| tokenID | uint256 | The ID of the token to query. | #### Returns -| Name | Type | Description | -| ------- | ------- | ----------- | -| \_owner | address | undefined | +| Name | Type | Description | +| ------- | ------- | -------------------------------------- | +| \_owner | address | The address of the owner of the token. | ### proxiableUUID @@ -285,19 +285,19 @@ _Upgrade the implementation of the proxy to `newImplementation`, and subsequentl function uri(uint256 tokenID) external view returns (string _uri) ``` -_see { openzeppelin-contracts-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol }Always returns the URI for the basetype so that it's managed in one place._ +_Returns the metadata URI for a given token ID.This function retrieves the metadata URI for the specified token ID by calling the `uri` function of the `ERC1155URIStorageUpgradeable` contract.The metadata URI is a string that points to a JSON file containing information about the token, such as its name, symbol, and image.This function always returns the URI for the basetype so that it's managed in one place._ #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | +| Name | Type | Description | +| ------- | ------- | ----------------------------------------------------- | +| tokenID | uint256 | The ID of the token to retrieve the metadata URI for. | #### Returns -| Name | Type | Description | -| ----- | ------ | ----------- | -| \_uri | string | undefined | +| Name | Type | Description | +| ----- | ------ | -------------------------------------------- | +| \_uri | string | The metadata URI for the specified token ID. | ## Events diff --git a/docs/docs/developer/api/contracts/interfaces/IHypercertToken.md b/docs/docs/developer/api/contracts/interfaces/IHypercertToken.md index 6bd5a931..30ed6f95 100644 --- a/docs/docs/developer/api/contracts/interfaces/IHypercertToken.md +++ b/docs/docs/developer/api/contracts/interfaces/IHypercertToken.md @@ -8,6 +8,23 @@ This interface declares the required functionality for a hypercert tokenThis int ## Methods +### batchBurnFraction + +```solidity +function batchBurnFraction(address account, uint256[] tokenIDs) external nonpayable +``` + +Operator must be allowed by `creator` and the tokens must represent the total amount of available units. + +_Function to burn the tokens at `tokenIDs` for `account`_ + +#### Parameters + +| Name | Type | Description | +| -------- | --------- | ----------- | +| account | address | undefined | +| tokenIDs | uint256[] | undefined | + ### burnFraction ```solidity diff --git a/docs/package.json b/docs/package.json index 7225bde0..674a836e 100644 --- a/docs/package.json +++ b/docs/package.json @@ -30,6 +30,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { + "@docusaurus/eslint-plugin": "^2.4.1", "@docusaurus/module-type-aliases": "^2.4.1", "@tsconfig/docusaurus": "^1.0.6", "typescript": "^4.9.4" diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index d99797cb..fdcf77c2 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -16,11 +16,6 @@ "prettier", "next" ], - "ignorePatterns": [ - "**/graph/generated/*", - "**/vendor/*.js", - "vendor/**/*.js" - ], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaFeatures": { diff --git a/graph/.eslintrc.yml b/graph/.eslintrc.yml new file mode 100644 index 00000000..2c49e547 --- /dev/null +++ b/graph/.eslintrc.yml @@ -0,0 +1,11 @@ +root: false +ignorePatterns: ["tests/", "generated/"] +parser: "@typescript-eslint/parser" +plugins: + - "@typescript-eslint" +extends: + - "eslint:recommended" + - "plugin:@typescript-eslint/recommended" +rules: + "@typescript-eslint/ban-types": + - "warn" diff --git a/graph/abis/HypercertMinter.json b/graph/abis/HypercertMinter.json index a0bb3aee..feb7ccb2 100644 --- a/graph/abis/HypercertMinter.json +++ b/graph/abis/HypercertMinter.json @@ -1,1065 +1,1130 @@ [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArraySize", - "type": "error" - }, - { - "inputs": [], - "name": "DoesNotExist", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "FractionalBurn", - "type": "error" - }, - { - "inputs": [], - "name": "Invalid", - "type": "error" - }, - { - "inputs": [], - "name": "NotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "TransfersNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "TypeMismatch", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "tokenID", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "root", - "type": "bytes32" - } - ], - "name": "AllowlistCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256[]", - "name": "claimIDs", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "fromTokenIDs", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "toTokenIDs", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "BatchValueTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "claimID", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "uri", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalUnits", - "type": "uint256" - } - ], - "name": "ClaimStored", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "tokenID", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "leaf", - "type": "bytes32" - } - ], - "name": "LeafClaimed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "TransferBatch", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TransferSingle", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "URI", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "claimID", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fromTokenID", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "toTokenID", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "ValueTransfer", - "type": "event" - }, - { - "inputs": [], - "name": "__SemiFungible1155_init", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "__Upgradeable1155_init", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "accounts", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "name": "balanceOfBatch", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[][]", - "name": "proofs", - "type": "bytes32[][]" - }, - { - "internalType": "uint256[]", - "name": "claimIDs", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "units", - "type": "uint256[]" - } - ], - "name": "batchMintClaimsFromAllowlists", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "burnBatch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenID", - "type": "uint256" - } - ], - "name": "burnValue", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "units", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "merkleRoot", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "_uri", - "type": "string" - }, - { - "internalType": "enum IHypercertToken.TransferRestrictions", - "name": "restrictions", - "type": "uint8" - } - ], - "name": "createAllowlist", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "hasBeenClaimed", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - }, - { - "internalType": "uint256", - "name": "claimID", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "leaf", - "type": "bytes32" - } - ], - "name": "isAllowedToClaim", - "outputs": [ - { - "internalType": "bool", - "name": "isAllowed", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "_fractionIDs", - "type": "uint256[]" - } - ], - "name": "mergeValue", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "units", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_uri", - "type": "string" - }, - { - "internalType": "enum IHypercertToken.TransferRestrictions", - "name": "restrictions", - "type": "uint8" - } - ], - "name": "mintClaim", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - }, - { - "internalType": "uint256", - "name": "claimID", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "units", - "type": "uint256" - } - ], - "name": "mintClaimFromAllowlist", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "units", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "fractions", - "type": "uint256[]" - }, - { - "internalType": "string", - "name": "_uri", - "type": "string" - }, - { - "internalType": "enum IHypercertToken.TransferRestrictions", - "name": "restrictions", - "type": "uint8" - } - ], - "name": "mintClaimWithFractions", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenID", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proxiableUUID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeBatchTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenID", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_values", - "type": "uint256[]" - } - ], - "name": "splitValue", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenID", - "type": "uint256" - } - ], - "name": "unitsOf", - "outputs": [ - { - "internalType": "uint256", - "name": "units", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenID", - "type": "uint256" - } - ], - "name": "unitsOf", - "outputs": [ - { - "internalType": "uint256", - "name": "units", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - } - ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenID", - "type": "uint256" - } - ], + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyClaimed", + "type": "error" + }, + { + "inputs": [], + "name": "ArraySize", + "type": "error" + }, + { + "inputs": [], + "name": "DoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "Invalid", + "type": "error" + }, + { + "inputs": [], + "name": "NotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "NotApprovedOrOwner", + "type": "error" + }, + { + "inputs": [], + "name": "TransfersNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "TypeMismatch", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + } + ], + "name": "AllowlistCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256[]", + "name": "claimIDs", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "fromTokenIDs", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "toTokenIDs", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "BatchValueTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "claimID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", "name": "uri", - "outputs": [ - { - "internalType": "string", - "name": "_uri", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalUnits", + "type": "uint256" + } + ], + "name": "ClaimStored", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "leaf", + "type": "bytes32" + } + ], + "name": "LeafClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "claimID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fromTokenID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "ValueTransfer", + "type": "event" + }, + { + "inputs": [], + "name": "__SemiFungible1155_init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "_tokenIDs", + "type": "uint256[]" + } + ], + "name": "batchBurnFraction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32[][]", + "name": "proofs", + "type": "bytes32[][]" + }, + { + "internalType": "uint256[]", + "name": "claimIDs", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "units", + "type": "uint256[]" + } + ], + "name": "batchMintClaimsFromAllowlists", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "burnBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenID", + "type": "uint256" + } + ], + "name": "burnFraction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "_uri", + "type": "string" + }, + { + "internalType": "enum IHypercertToken.TransferRestrictions", + "name": "restrictions", + "type": "uint8" + } + ], + "name": "createAllowlist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "hasBeenClaimed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + }, + { + "internalType": "uint256", + "name": "claimID", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "leaf", + "type": "bytes32" + } + ], + "name": "isAllowedToClaim", + "outputs": [ + { + "internalType": "bool", + "name": "isAllowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "_fractionIDs", + "type": "uint256[]" + } + ], + "name": "mergeFractions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_uri", + "type": "string" + }, + { + "internalType": "enum IHypercertToken.TransferRestrictions", + "name": "restrictions", + "type": "uint8" + } + ], + "name": "mintClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + }, + { + "internalType": "uint256", + "name": "claimID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + } + ], + "name": "mintClaimFromAllowlist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "fractions", + "type": "uint256[]" + }, + { + "internalType": "string", + "name": "_uri", + "type": "string" + }, + { + "internalType": "enum IHypercertToken.TransferRestrictions", + "name": "restrictions", + "type": "uint8" + } + ], + "name": "mintClaimWithFractions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + } + ], + "name": "readTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenID", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_newFractions", + "type": "uint256[]" + } + ], + "name": "splitFraction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + } + ], + "name": "unitsOf", + "outputs": [ + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + } + ], + "name": "unitsOf", + "outputs": [ + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "_uri", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } ] diff --git a/graph/generated/HypercertMinter/HypercertMinter.ts b/graph/generated/HypercertMinter/HypercertMinter.ts index 41fdeb8c..988629ae 100644 --- a/graph/generated/HypercertMinter/HypercertMinter.ts +++ b/graph/generated/HypercertMinter/HypercertMinter.ts @@ -7,7 +7,7 @@ import { Entity, Bytes, Address, - BigInt + BigInt, } from "@graphprotocol/graph-ts"; export class AdminChanged extends ethereum.Event { @@ -401,8 +401,8 @@ export class HypercertMinter extends ethereum.SmartContract { "balanceOf(address,uint256):(uint256)", [ ethereum.Value.fromAddress(account), - ethereum.Value.fromUnsignedBigInt(id) - ] + ethereum.Value.fromUnsignedBigInt(id), + ], ); return result[0].toBigInt(); @@ -414,8 +414,8 @@ export class HypercertMinter extends ethereum.SmartContract { "balanceOf(address,uint256):(uint256)", [ ethereum.Value.fromAddress(account), - ethereum.Value.fromUnsignedBigInt(id) - ] + ethereum.Value.fromUnsignedBigInt(id), + ], ); if (result.reverted) { return new ethereum.CallResult(); @@ -430,8 +430,8 @@ export class HypercertMinter extends ethereum.SmartContract { "balanceOfBatch(address[],uint256[]):(uint256[])", [ ethereum.Value.fromAddressArray(accounts), - ethereum.Value.fromUnsignedBigIntArray(ids) - ] + ethereum.Value.fromUnsignedBigIntArray(ids), + ], ); return result[0].toBigIntArray(); @@ -439,15 +439,15 @@ export class HypercertMinter extends ethereum.SmartContract { try_balanceOfBatch( accounts: Array
, - ids: Array + ids: Array, ): ethereum.CallResult> { let result = super.tryCall( "balanceOfBatch", "balanceOfBatch(address[],uint256[]):(uint256[])", [ ethereum.Value.fromAddressArray(accounts), - ethereum.Value.fromUnsignedBigIntArray(ids) - ] + ethereum.Value.fromUnsignedBigIntArray(ids), + ], ); if (result.reverted) { return new ethereum.CallResult(); @@ -462,8 +462,8 @@ export class HypercertMinter extends ethereum.SmartContract { "hasBeenClaimed(uint256,bytes32):(bool)", [ ethereum.Value.fromUnsignedBigInt(param0), - ethereum.Value.fromFixedBytes(param1) - ] + ethereum.Value.fromFixedBytes(param1), + ], ); return result[0].toBoolean(); @@ -471,15 +471,15 @@ export class HypercertMinter extends ethereum.SmartContract { try_hasBeenClaimed( param0: BigInt, - param1: Bytes + param1: Bytes, ): ethereum.CallResult { let result = super.tryCall( "hasBeenClaimed", "hasBeenClaimed(uint256,bytes32):(bool)", [ ethereum.Value.fromUnsignedBigInt(param0), - ethereum.Value.fromFixedBytes(param1) - ] + ethereum.Value.fromFixedBytes(param1), + ], ); if (result.reverted) { return new ethereum.CallResult(); @@ -495,8 +495,8 @@ export class HypercertMinter extends ethereum.SmartContract { [ ethereum.Value.fromFixedBytesArray(proof), ethereum.Value.fromUnsignedBigInt(claimID), - ethereum.Value.fromFixedBytes(leaf) - ] + ethereum.Value.fromFixedBytes(leaf), + ], ); return result[0].toBoolean(); @@ -505,7 +505,7 @@ export class HypercertMinter extends ethereum.SmartContract { try_isAllowedToClaim( proof: Array, claimID: BigInt, - leaf: Bytes + leaf: Bytes, ): ethereum.CallResult { let result = super.tryCall( "isAllowedToClaim", @@ -513,8 +513,8 @@ export class HypercertMinter extends ethereum.SmartContract { [ ethereum.Value.fromFixedBytesArray(proof), ethereum.Value.fromUnsignedBigInt(claimID), - ethereum.Value.fromFixedBytes(leaf) - ] + ethereum.Value.fromFixedBytes(leaf), + ], ); if (result.reverted) { return new ethereum.CallResult(); @@ -529,8 +529,8 @@ export class HypercertMinter extends ethereum.SmartContract { "isApprovedForAll(address,address):(bool)", [ ethereum.Value.fromAddress(account), - ethereum.Value.fromAddress(operator) - ] + ethereum.Value.fromAddress(operator), + ], ); return result[0].toBoolean(); @@ -538,15 +538,15 @@ export class HypercertMinter extends ethereum.SmartContract { try_isApprovedForAll( account: Address, - operator: Address + operator: Address, ): ethereum.CallResult { let result = super.tryCall( "isApprovedForAll", "isApprovedForAll(address,address):(bool)", [ ethereum.Value.fromAddress(account), - ethereum.Value.fromAddress(operator) - ] + ethereum.Value.fromAddress(operator), + ], ); if (result.reverted) { return new ethereum.CallResult(); @@ -587,7 +587,7 @@ export class HypercertMinter extends ethereum.SmartContract { ownerOf(tokenID: BigInt): Address { let result = super.call("ownerOf", "ownerOf(uint256):(address)", [ - ethereum.Value.fromUnsignedBigInt(tokenID) + ethereum.Value.fromUnsignedBigInt(tokenID), ]); return result[0].toAddress(); @@ -595,7 +595,7 @@ export class HypercertMinter extends ethereum.SmartContract { try_ownerOf(tokenID: BigInt): ethereum.CallResult
{ let result = super.tryCall("ownerOf", "ownerOf(uint256):(address)", [ - ethereum.Value.fromUnsignedBigInt(tokenID) + ethereum.Value.fromUnsignedBigInt(tokenID), ]); if (result.reverted) { return new ethereum.CallResult(); @@ -629,7 +629,7 @@ export class HypercertMinter extends ethereum.SmartContract { let result = super.tryCall( "proxiableUUID", "proxiableUUID():(bytes32)", - [] + [], ); if (result.reverted) { return new ethereum.CallResult(); @@ -638,11 +638,34 @@ export class HypercertMinter extends ethereum.SmartContract { return ethereum.CallResult.fromValue(value[0].toBytes()); } + readTransferRestriction(tokenID: BigInt): string { + let result = super.call( + "readTransferRestriction", + "readTransferRestriction(uint256):(string)", + [ethereum.Value.fromUnsignedBigInt(tokenID)], + ); + + return result[0].toString(); + } + + try_readTransferRestriction(tokenID: BigInt): ethereum.CallResult { + let result = super.tryCall( + "readTransferRestriction", + "readTransferRestriction(uint256):(string)", + [ethereum.Value.fromUnsignedBigInt(tokenID)], + ); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue(value[0].toString()); + } + supportsInterface(interfaceId: Bytes): boolean { let result = super.call( "supportsInterface", "supportsInterface(bytes4):(bool)", - [ethereum.Value.fromFixedBytes(interfaceId)] + [ethereum.Value.fromFixedBytes(interfaceId)], ); return result[0].toBoolean(); @@ -652,7 +675,7 @@ export class HypercertMinter extends ethereum.SmartContract { let result = super.tryCall( "supportsInterface", "supportsInterface(bytes4):(bool)", - [ethereum.Value.fromFixedBytes(interfaceId)] + [ethereum.Value.fromFixedBytes(interfaceId)], ); if (result.reverted) { return new ethereum.CallResult(); @@ -664,7 +687,7 @@ export class HypercertMinter extends ethereum.SmartContract { unitsOf(account: Address, tokenID: BigInt): BigInt { let result = super.call("unitsOf", "unitsOf(address,uint256):(uint256)", [ ethereum.Value.fromAddress(account), - ethereum.Value.fromUnsignedBigInt(tokenID) + ethereum.Value.fromUnsignedBigInt(tokenID), ]); return result[0].toBigInt(); @@ -676,8 +699,8 @@ export class HypercertMinter extends ethereum.SmartContract { "unitsOf(address,uint256):(uint256)", [ ethereum.Value.fromAddress(account), - ethereum.Value.fromUnsignedBigInt(tokenID) - ] + ethereum.Value.fromUnsignedBigInt(tokenID), + ], ); if (result.reverted) { return new ethereum.CallResult(); @@ -688,7 +711,7 @@ export class HypercertMinter extends ethereum.SmartContract { unitsOf1(tokenID: BigInt): BigInt { let result = super.call("unitsOf", "unitsOf(uint256):(uint256)", [ - ethereum.Value.fromUnsignedBigInt(tokenID) + ethereum.Value.fromUnsignedBigInt(tokenID), ]); return result[0].toBigInt(); @@ -696,7 +719,7 @@ export class HypercertMinter extends ethereum.SmartContract { try_unitsOf1(tokenID: BigInt): ethereum.CallResult { let result = super.tryCall("unitsOf", "unitsOf(uint256):(uint256)", [ - ethereum.Value.fromUnsignedBigInt(tokenID) + ethereum.Value.fromUnsignedBigInt(tokenID), ]); if (result.reverted) { return new ethereum.CallResult(); @@ -707,7 +730,7 @@ export class HypercertMinter extends ethereum.SmartContract { uri(tokenID: BigInt): string { let result = super.call("uri", "uri(uint256):(string)", [ - ethereum.Value.fromUnsignedBigInt(tokenID) + ethereum.Value.fromUnsignedBigInt(tokenID), ]); return result[0].toString(); @@ -715,7 +738,7 @@ export class HypercertMinter extends ethereum.SmartContract { try_uri(tokenID: BigInt): ethereum.CallResult { let result = super.tryCall("uri", "uri(uint256):(string)", [ - ethereum.Value.fromUnsignedBigInt(tokenID) + ethereum.Value.fromUnsignedBigInt(tokenID), ]); if (result.reverted) { return new ethereum.CallResult(); @@ -777,28 +800,36 @@ export class __SemiFungible1155_initCall__Outputs { } } -export class __Upgradeable1155_initCall extends ethereum.Call { - get inputs(): __Upgradeable1155_initCall__Inputs { - return new __Upgradeable1155_initCall__Inputs(this); +export class BatchBurnFractionCall extends ethereum.Call { + get inputs(): BatchBurnFractionCall__Inputs { + return new BatchBurnFractionCall__Inputs(this); } - get outputs(): __Upgradeable1155_initCall__Outputs { - return new __Upgradeable1155_initCall__Outputs(this); + get outputs(): BatchBurnFractionCall__Outputs { + return new BatchBurnFractionCall__Outputs(this); } } -export class __Upgradeable1155_initCall__Inputs { - _call: __Upgradeable1155_initCall; +export class BatchBurnFractionCall__Inputs { + _call: BatchBurnFractionCall; - constructor(call: __Upgradeable1155_initCall) { + constructor(call: BatchBurnFractionCall) { this._call = call; } + + get _account(): Address { + return this._call.inputValues[0].value.toAddress(); + } + + get _tokenIDs(): Array { + return this._call.inputValues[1].value.toBigIntArray(); + } } -export class __Upgradeable1155_initCall__Outputs { - _call: __Upgradeable1155_initCall; +export class BatchBurnFractionCall__Outputs { + _call: BatchBurnFractionCall; - constructor(call: __Upgradeable1155_initCall) { + constructor(call: BatchBurnFractionCall) { this._call = call; } } @@ -820,16 +851,20 @@ export class BatchMintClaimsFromAllowlistsCall__Inputs { this._call = call; } + get account(): Address { + return this._call.inputValues[0].value.toAddress(); + } + get proofs(): Array> { - return this._call.inputValues[0].value.toBytesMatrix(); + return this._call.inputValues[1].value.toBytesMatrix(); } get claimIDs(): Array { - return this._call.inputValues[1].value.toBigIntArray(); + return this._call.inputValues[2].value.toBigIntArray(); } get units(): Array { - return this._call.inputValues[2].value.toBigIntArray(); + return this._call.inputValues[3].value.toBigIntArray(); } } @@ -917,20 +952,20 @@ export class BurnBatchCall__Outputs { } } -export class BurnValueCall extends ethereum.Call { - get inputs(): BurnValueCall__Inputs { - return new BurnValueCall__Inputs(this); +export class BurnFractionCall extends ethereum.Call { + get inputs(): BurnFractionCall__Inputs { + return new BurnFractionCall__Inputs(this); } - get outputs(): BurnValueCall__Outputs { - return new BurnValueCall__Outputs(this); + get outputs(): BurnFractionCall__Outputs { + return new BurnFractionCall__Outputs(this); } } -export class BurnValueCall__Inputs { - _call: BurnValueCall; +export class BurnFractionCall__Inputs { + _call: BurnFractionCall; - constructor(call: BurnValueCall) { + constructor(call: BurnFractionCall) { this._call = call; } @@ -943,10 +978,10 @@ export class BurnValueCall__Inputs { } } -export class BurnValueCall__Outputs { - _call: BurnValueCall; +export class BurnFractionCall__Outputs { + _call: BurnFractionCall; - constructor(call: BurnValueCall) { + constructor(call: BurnFractionCall) { this._call = call; } } @@ -968,20 +1003,24 @@ export class CreateAllowlistCall__Inputs { this._call = call; } + get account(): Address { + return this._call.inputValues[0].value.toAddress(); + } + get units(): BigInt { - return this._call.inputValues[0].value.toBigInt(); + return this._call.inputValues[1].value.toBigInt(); } get merkleRoot(): Bytes { - return this._call.inputValues[1].value.toBytes(); + return this._call.inputValues[2].value.toBytes(); } get _uri(): string { - return this._call.inputValues[2].value.toString(); + return this._call.inputValues[3].value.toString(); } get restrictions(): i32 { - return this._call.inputValues[3].value.toI32(); + return this._call.inputValues[4].value.toI32(); } } @@ -1019,32 +1058,36 @@ export class InitializeCall__Outputs { } } -export class MergeValueCall extends ethereum.Call { - get inputs(): MergeValueCall__Inputs { - return new MergeValueCall__Inputs(this); +export class MergeFractionsCall extends ethereum.Call { + get inputs(): MergeFractionsCall__Inputs { + return new MergeFractionsCall__Inputs(this); } - get outputs(): MergeValueCall__Outputs { - return new MergeValueCall__Outputs(this); + get outputs(): MergeFractionsCall__Outputs { + return new MergeFractionsCall__Outputs(this); } } -export class MergeValueCall__Inputs { - _call: MergeValueCall; +export class MergeFractionsCall__Inputs { + _call: MergeFractionsCall; - constructor(call: MergeValueCall) { + constructor(call: MergeFractionsCall) { this._call = call; } + get _account(): Address { + return this._call.inputValues[0].value.toAddress(); + } + get _fractionIDs(): Array { - return this._call.inputValues[0].value.toBigIntArray(); + return this._call.inputValues[1].value.toBigIntArray(); } } -export class MergeValueCall__Outputs { - _call: MergeValueCall; +export class MergeFractionsCall__Outputs { + _call: MergeFractionsCall; - constructor(call: MergeValueCall) { + constructor(call: MergeFractionsCall) { this._call = call; } } @@ -1066,16 +1109,20 @@ export class MintClaimCall__Inputs { this._call = call; } + get account(): Address { + return this._call.inputValues[0].value.toAddress(); + } + get units(): BigInt { - return this._call.inputValues[0].value.toBigInt(); + return this._call.inputValues[1].value.toBigInt(); } get _uri(): string { - return this._call.inputValues[1].value.toString(); + return this._call.inputValues[2].value.toString(); } get restrictions(): i32 { - return this._call.inputValues[2].value.toI32(); + return this._call.inputValues[3].value.toI32(); } } @@ -1104,16 +1151,20 @@ export class MintClaimFromAllowlistCall__Inputs { this._call = call; } + get account(): Address { + return this._call.inputValues[0].value.toAddress(); + } + get proof(): Array { - return this._call.inputValues[0].value.toBytesArray(); + return this._call.inputValues[1].value.toBytesArray(); } get claimID(): BigInt { - return this._call.inputValues[1].value.toBigInt(); + return this._call.inputValues[2].value.toBigInt(); } get units(): BigInt { - return this._call.inputValues[2].value.toBigInt(); + return this._call.inputValues[3].value.toBigInt(); } } @@ -1142,20 +1193,24 @@ export class MintClaimWithFractionsCall__Inputs { this._call = call; } + get account(): Address { + return this._call.inputValues[0].value.toAddress(); + } + get units(): BigInt { - return this._call.inputValues[0].value.toBigInt(); + return this._call.inputValues[1].value.toBigInt(); } get fractions(): Array { - return this._call.inputValues[1].value.toBigIntArray(); + return this._call.inputValues[2].value.toBigIntArray(); } get _uri(): string { - return this._call.inputValues[2].value.toString(); + return this._call.inputValues[3].value.toString(); } get restrictions(): i32 { - return this._call.inputValues[3].value.toI32(); + return this._call.inputValues[4].value.toI32(); } } @@ -1345,20 +1400,20 @@ export class SetApprovalForAllCall__Outputs { } } -export class SplitValueCall extends ethereum.Call { - get inputs(): SplitValueCall__Inputs { - return new SplitValueCall__Inputs(this); +export class SplitFractionCall extends ethereum.Call { + get inputs(): SplitFractionCall__Inputs { + return new SplitFractionCall__Inputs(this); } - get outputs(): SplitValueCall__Outputs { - return new SplitValueCall__Outputs(this); + get outputs(): SplitFractionCall__Outputs { + return new SplitFractionCall__Outputs(this); } } -export class SplitValueCall__Inputs { - _call: SplitValueCall; +export class SplitFractionCall__Inputs { + _call: SplitFractionCall; - constructor(call: SplitValueCall) { + constructor(call: SplitFractionCall) { this._call = call; } @@ -1370,15 +1425,15 @@ export class SplitValueCall__Inputs { return this._call.inputValues[1].value.toBigInt(); } - get _values(): Array { + get _newFractions(): Array { return this._call.inputValues[2].value.toBigIntArray(); } } -export class SplitValueCall__Outputs { - _call: SplitValueCall; +export class SplitFractionCall__Outputs { + _call: SplitFractionCall; - constructor(call: SplitValueCall) { + constructor(call: SplitFractionCall) { this._call = call; } } diff --git a/graph/package.json b/graph/package.json index 12a023cd..e8f03fa3 100644 --- a/graph/package.json +++ b/graph/package.json @@ -14,9 +14,9 @@ "build": "yarn build:graph && yarn build:codegen", "build:graph": "graph build", "build:codegen": "graph codegen", - "deploy": "yarn auth && yarn deploy:goerli && yarn deploy:optimism", - "deploy:goerli": "graph deploy --node https://api.thegraph.com/deploy/ --network goerli hypercerts-admin/hypercerts-testnet", - "deploy:optimism": "graph deploy --node https://api.thegraph.com/deploy/ --network optimism hypercerts-admin/hypercerts-optimism-mainnet", + "deploy": "yarn deploy:goerli && yarn deploy:optimism", + "deploy:goerli": "yarn auth && graph deploy --node https://api.thegraph.com/deploy/ --network goerli hypercerts-admin/hypercerts-testnet", + "deploy:optimism": "yarn auth && graph deploy --node https://api.thegraph.com/deploy/ --network optimism hypercerts-admin/hypercerts-optimism-mainnet", "create-local": "graph create --node http://localhost:8020/ hypercerts-admin/hypercerts-testnet", "remove-local": "graph remove --node http://localhost:8020/ hypercerts-admin/hypercerts-testnet", "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 hypercerts-admin/hypercerts-testnet", diff --git a/graph/src/hypercert-minter.ts b/graph/src/hypercert-minter.ts index a9f65e3a..2c9b2de7 100644 --- a/graph/src/hypercert-minter.ts +++ b/graph/src/hypercert-minter.ts @@ -11,37 +11,37 @@ import { URI as URIEvent, ValueTransfer as ValueTransferEvent, } from "../generated/HypercertMinter/HypercertMinter"; +import { ClaimToken } from "../generated/schema"; import { getID, getOrCreateAllowlist, getOrCreateClaim, getOrCreateClaimToken, } from "./utils"; -import { Address, BigInt, log } from "@graphprotocol/graph-ts"; -import { ClaimToken } from "../generated/schema"; +import { Address, log } from "@graphprotocol/graph-ts"; const ZERO_ADDRESS = Address.fromString( - "0x0000000000000000000000000000000000000000" + "0x0000000000000000000000000000000000000000", ); -const ZERO_TOKEN = BigInt.fromI32(0); export function handleAllowlistCreated(event: AllowlistCreatedEvent): void { - let allowlist = getOrCreateAllowlist( + const allowlist = getOrCreateAllowlist( event.params.tokenID, event.params.root, - event.address + event.address, ); allowlist.save(); } -export function handleApprovalForAll(event: ApprovalForAllEvent): void {} +// eslint-disable-next-line @typescript-eslint/no-empty-function +export function handleApprovalForAll(_event: ApprovalForAllEvent): void {} export function handleClaimStored(event: ClaimStoredEvent): void { - let claim = getOrCreateClaim( + const claim = getOrCreateClaim( event.params.claimID, event.address, - event.block.timestamp + event.block.timestamp, ); claim.uri = event.params.uri; @@ -52,19 +52,36 @@ export function handleClaimStored(event: ClaimStoredEvent): void { claim.save(); } -export function handleInitialized(event: InitializedEvent): void {} +// eslint-disable-next-line @typescript-eslint/no-empty-function +export function handleInitialized(_event: InitializedEvent): void {} -export function handleLeafClaimed(event: LeafClaimedEvent): void {} +// eslint-disable-next-line @typescript-eslint/no-empty-function +export function handleLeafClaimed(_event: LeafClaimedEvent): void {} export function handleOwnershipTransferred( - event: OwnershipTransferredEvent + _event: OwnershipTransferredEvent, + // eslint-disable-next-line @typescript-eslint/no-empty-function ): void {} -export function handleTransferBatch(event: TransferBatchEvent): void {} +// operator, from, to, ids, values +export function handleTransferBatch(event: TransferBatchEvent): void { + for (let i = 0; i < event.params.ids.length; i++) { + const id = getID(event.params.ids[i], event.address); + const token = ClaimToken.load(id); + + if (!token) { + log.debug("Transfered ClaimToken does not exist: {}", [id]); + return; + } + + token.owner = event.params.to; + token.save(); + } +} export function handleTransferSingle(event: TransferSingleEvent): void { - let id = getID(event.params.id, event.address); - let token = ClaimToken.load(id); + const id = getID(event.params.id, event.address); + const token = ClaimToken.load(id); if (!token) { log.debug("Transfered ClaimToken does not exist: {}", [id]); @@ -75,7 +92,8 @@ export function handleTransferSingle(event: TransferSingleEvent): void { token.save(); } -export function handleURI(event: URIEvent): void {} +// eslint-disable-next-line @typescript-eslint/no-empty-function +export function handleURI(_event: URIEvent): void {} export function handleValueTransfer(event: ValueTransferEvent): void { log.debug("Received ValueTransferEvent claimID: {}", [ @@ -92,18 +110,18 @@ export function handleValueTransfer(event: ValueTransferEvent): void { event.params.value.toString(), ]); - let from = getOrCreateClaimToken( + const from = getOrCreateClaimToken( event.params.claimID, event.params.fromTokenID, - event.address + event.address, ); - let to = getOrCreateClaimToken( + const to = getOrCreateClaimToken( event.params.claimID, event.params.toTokenID, - event.address + event.address, ); - let value = event.params.value; + const value = event.params.value; log.debug("Got from: {}", [from.id]); log.debug("Got to: {}", [to.id]); @@ -123,6 +141,7 @@ export function handleValueTransfer(event: ValueTransferEvent): void { // Burn value if (!from.tokenID.isZero() && to.tokenID.isZero()) { from.units = from.units.minus(value); + from.owner = ZERO_ADDRESS; } log.debug("Saving from: {}", [from.id]); @@ -134,18 +153,23 @@ export function handleValueTransfer(event: ValueTransferEvent): void { //TODO cleanup to nicer state handling export function handleBatchValueTransfer(event: BatchValueTransfer): void { - let claimIDs = event.params.claimIDs; - let fromIDs = event.params.fromTokenIDs; - let toIDs = event.params.toTokenIDs; - let values = event.params.values; + const claimIDs = event.params.claimIDs; + const fromIDs = event.params.fromTokenIDs; + const toIDs = event.params.toTokenIDs; + const values = event.params.values; + const contractAddress = event.address; - let size = claimIDs.length; + const size = claimIDs.length; for (let i = 0; i < size; i++) { - let from = getOrCreateClaimToken(claimIDs[i], fromIDs[i], event.address); - let to = getOrCreateClaimToken(claimIDs[i], toIDs[i], event.address); + const from = getOrCreateClaimToken( + claimIDs[i], + fromIDs[i], + contractAddress, + ); + const to = getOrCreateClaimToken(claimIDs[i], toIDs[i], contractAddress); - let value = values[i]; + const value = values[i]; log.debug("Got from: {}", [from.id]); log.debug("Got to: {}", [to.id]); @@ -164,6 +188,7 @@ export function handleBatchValueTransfer(event: BatchValueTransfer): void { // Burn value if (!from.tokenID.isZero() && to.tokenID.isZero()) { from.units = from.units.minus(value); + from.owner = ZERO_ADDRESS; } log.debug("Saving from: {}", [from.id]); diff --git a/graph/tests/.latest.json b/graph/tests/.latest.json index a6d8f561..113c99a7 100644 --- a/graph/tests/.latest.json +++ b/graph/tests/.latest.json @@ -1,4 +1,4 @@ { "version": "0.5.4", - "timestamp": 1688082385888 + "timestamp": 1693308593418 } diff --git a/graph/tests/hypercert-minter-burn.test.ts b/graph/tests/hypercert-minter-burn.test.ts new file mode 100644 index 00000000..496b7c8b --- /dev/null +++ b/graph/tests/hypercert-minter-burn.test.ts @@ -0,0 +1,193 @@ +import { + handleTransferSingle, + handleValueTransfer, + handleBatchValueTransfer, + handleTransferBatch, +} from "../src/hypercert-minter"; +import { + buildIDs, + buildValues, + buildZeroes, + createBatchValueTransferEvent, + createTransferBatchEvent, + createTransferSingleEvent, + createValueTransferEvent, + getDefaultContractAddress, + ZERO_ADDRESS, + ZERO_TOKEN, +} from "./hypercert-minter-utils"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { + assert, + describe, + test, + clearStore, + beforeAll, + afterAll, + createMockedFunction, + afterEach, +} from "matchstick-as/assembly/index"; + +export { handleTransferSingle, handleValueTransfer, handleBatchValueTransfer }; + +describe("Describe entity assertions", () => { + beforeAll(() => {}); + + afterEach(() => { + clearStore(); + }); + + test("TransferSingle and TransferValue for an existing token to zero address burns the fraction", () => { + let from = Address.fromString("0x0000000000000000000000000000000000000001"); + + let claimID = BigInt.fromI64(1); + let fromID = BigInt.fromI64(0); + let toID = BigInt.fromI64(1); + let units = BigInt.fromI64(10000); + + // Create fraction token + let valueTransferEvent = createValueTransferEvent( + claimID, + fromID, + toID, + units, + ); + + createMockedFunction( + getDefaultContractAddress(), + "ownerOf", + "ownerOf(uint256):(address)", + ) + .withArgs([ethereum.Value.fromUnsignedBigInt(toID)]) + .returns([ethereum.Value.fromAddress(from)]); + + createMockedFunction( + getDefaultContractAddress(), + "ownerOf", + "ownerOf(uint256):(address)", + ) + .withArgs([ethereum.Value.fromUnsignedBigInt(fromID)]) + .returns([ethereum.Value.fromAddress(from)]); + + handleValueTransfer(valueTransferEvent); + + let fractionId = getDefaultContractAddress().toHexString().concat("-1"); + + assert.fieldEquals("ClaimToken", fractionId, "owner", from.toHexString()); + assert.fieldEquals("ClaimToken", fractionId, "units", "10000"); + + // Handle 1155 transfer to zero address + let transferSingleEvent = createTransferSingleEvent( + from, + from, + ZERO_ADDRESS, + BigInt.fromI64(1), + BigInt.fromI64(1), + ); + + handleTransferSingle(transferSingleEvent); + + assert.fieldEquals( + "ClaimToken", + fractionId, + "owner", + ZERO_ADDRESS.toHexString(), + ); + assert.fieldEquals("ClaimToken", fractionId, "units", "10000"); + + // Handle hypercert units transfer + let valueTransferEvent2 = createValueTransferEvent( + claimID, + toID, + ZERO_TOKEN, + units, + ); + + handleValueTransfer(valueTransferEvent2); + + assert.fieldEquals( + "ClaimToken", + fractionId, + "owner", + ZERO_ADDRESS.toHexString(), + ); + assert.fieldEquals("ClaimToken", fractionId, "units", "0"); + }); + + test("TransferBatch and BatchTransferValue for an existing token to zero address burns the fraction", () => { + let from = Address.fromString("0x0000000000000000000000000000000000000001"); + + let claimID = BigInt.fromI64(1); + let fromID = BigInt.fromI64(0); + let toID = BigInt.fromI64(1); + let units = BigInt.fromI64(10000); + + // Create fraction token + let valueTransferEvent = createBatchValueTransferEvent( + [claimID], + [fromID], + [toID], + [units], + ); + + createMockedFunction( + getDefaultContractAddress(), + "ownerOf", + "ownerOf(uint256):(address)", + ) + .withArgs([ethereum.Value.fromUnsignedBigInt(toID)]) + .returns([ethereum.Value.fromAddress(from)]); + + createMockedFunction( + getDefaultContractAddress(), + "ownerOf", + "ownerOf(uint256):(address)", + ) + .withArgs([ethereum.Value.fromUnsignedBigInt(fromID)]) + .returns([ethereum.Value.fromAddress(from)]); + + handleBatchValueTransfer(valueTransferEvent); + + let fractionId = getDefaultContractAddress().toHexString().concat("-1"); + + assert.fieldEquals("ClaimToken", fractionId, "owner", from.toHexString()); + assert.fieldEquals("ClaimToken", fractionId, "units", "10000"); + + // Handle 1155 transfer to zero address + let transferBatchEvent = createTransferBatchEvent( + from, + from, + ZERO_ADDRESS, + [BigInt.fromI64(1)], + [BigInt.fromI64(1)], + ); + + handleTransferBatch(transferBatchEvent); + + assert.fieldEquals( + "ClaimToken", + fractionId, + "owner", + ZERO_ADDRESS.toHexString(), + ); + assert.fieldEquals("ClaimToken", fractionId, "units", "10000"); + + // Handle hypercert units transfer + let valueTransferEvent2 = createBatchValueTransferEvent( + [claimID], + [toID], + [ZERO_TOKEN], + [units], + ); + + handleBatchValueTransfer(valueTransferEvent2); + + assert.fieldEquals( + "ClaimToken", + fractionId, + "owner", + ZERO_ADDRESS.toHexString(), + ); + assert.fieldEquals("ClaimToken", fractionId, "units", "0"); + }); +}); diff --git a/graph/tests/hypercert-minter-utils.ts b/graph/tests/hypercert-minter-utils.ts index 53a64853..e1694735 100644 --- a/graph/tests/hypercert-minter-utils.ts +++ b/graph/tests/hypercert-minter-utils.ts @@ -1,5 +1,3 @@ -import { newMockEvent } from "matchstick-as"; -import { ethereum, Address, BigInt, Bytes } from "@graphprotocol/graph-ts"; import { AllowlistCreated, BatchValueTransfer, @@ -10,6 +8,13 @@ import { URI, ValueTransfer, } from "../generated/HypercertMinter/HypercertMinter"; +import { ethereum, Address, BigInt, Bytes } from "@graphprotocol/graph-ts"; +import { newMockEvent } from "matchstick-as"; + +export const ZERO_ADDRESS = Address.fromString( + "0x0000000000000000000000000000000000000000", +); +export const ZERO_TOKEN = BigInt.fromI32(0); export function getDefaultContractAddress(): Address { return Address.fromString("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7"); @@ -28,7 +33,7 @@ export function buildZeroes(size: BigInt): BigInt[] { export function buildIDs( size: BigInt, - start: BigInt = BigInt.zero() + start: BigInt = BigInt.zero(), ): BigInt[] { let array: BigInt[] = []; for (let i = 0; i < size.toI32(); i++) { @@ -54,7 +59,7 @@ export function buildValues(size: BigInt): BigInt[] { export function createAllowlistCreatedEvent( tokenID: BigInt, - root: Bytes + root: Bytes, ): AllowlistCreated { let mockEvent = newMockEvent(); let parameters: ethereum.EventParam[] = new Array(); @@ -64,11 +69,11 @@ export function createAllowlistCreatedEvent( parameters.push( new ethereum.EventParam( "tokenID", - ethereum.Value.fromUnsignedBigInt(tokenID) - ) + ethereum.Value.fromUnsignedBigInt(tokenID), + ), ); parameters.push( - new ethereum.EventParam("root", ethereum.Value.fromFixedBytes(root)) + new ethereum.EventParam("root", ethereum.Value.fromFixedBytes(root)), ); let allowlistCreatedEvent = new AllowlistCreated( @@ -79,7 +84,7 @@ export function createAllowlistCreatedEvent( mockEvent.block, mockEvent.transaction, parameters, - mockEvent.receipt + mockEvent.receipt, ); return allowlistCreatedEvent; @@ -88,7 +93,7 @@ export function createAllowlistCreatedEvent( export function createClaimStoredEvent( claimID: BigInt, uri: string, - totalUnits: BigInt + totalUnits: BigInt, ): ClaimStored { let mockEvent = newMockEvent(); let parameters: ethereum.EventParam[] = new Array(); @@ -96,18 +101,18 @@ export function createClaimStoredEvent( parameters.push( new ethereum.EventParam( "claimID", - ethereum.Value.fromUnsignedBigInt(claimID) - ) + ethereum.Value.fromUnsignedBigInt(claimID), + ), ); parameters.push( - new ethereum.EventParam("uri", ethereum.Value.fromString(uri)) + new ethereum.EventParam("uri", ethereum.Value.fromString(uri)), ); parameters.push( new ethereum.EventParam( "totalUnits", - ethereum.Value.fromUnsignedBigInt(totalUnits) - ) + ethereum.Value.fromUnsignedBigInt(totalUnits), + ), ); let claimStoredEvent = new ClaimStored( @@ -118,7 +123,7 @@ export function createClaimStoredEvent( mockEvent.block, mockEvent.transaction, parameters, - mockEvent.receipt + mockEvent.receipt, ); return claimStoredEvent; @@ -126,7 +131,7 @@ export function createClaimStoredEvent( export function createLeafClaimedEvent( tokenID: BigInt, - leaf: Bytes + leaf: Bytes, ): LeafClaimed { let leafClaimedEvent = changetype(newMockEvent()); @@ -135,11 +140,11 @@ export function createLeafClaimedEvent( leafClaimedEvent.parameters.push( new ethereum.EventParam( "tokenID", - ethereum.Value.fromUnsignedBigInt(tokenID) - ) + ethereum.Value.fromUnsignedBigInt(tokenID), + ), ); leafClaimedEvent.parameters.push( - new ethereum.EventParam("leaf", ethereum.Value.fromFixedBytes(leaf)) + new ethereum.EventParam("leaf", ethereum.Value.fromFixedBytes(leaf)), ); return leafClaimedEvent; @@ -150,29 +155,39 @@ export function createTransferBatchEvent( from: Address, to: Address, ids: Array, - values: Array + values: Array, ): TransferBatch { - let transferBatchEvent = changetype(newMockEvent()); - - transferBatchEvent.parameters = new Array(); + let mockEvent = newMockEvent(); + let parameters: ethereum.EventParam[] = new Array(); - transferBatchEvent.parameters.push( - new ethereum.EventParam("operator", ethereum.Value.fromAddress(operator)) + parameters.push( + new ethereum.EventParam("operator", ethereum.Value.fromAddress(operator)), ); - transferBatchEvent.parameters.push( - new ethereum.EventParam("from", ethereum.Value.fromAddress(from)) + parameters.push( + new ethereum.EventParam("from", ethereum.Value.fromAddress(from)), ); - transferBatchEvent.parameters.push( - new ethereum.EventParam("to", ethereum.Value.fromAddress(to)) + parameters.push( + new ethereum.EventParam("to", ethereum.Value.fromAddress(to)), ); - transferBatchEvent.parameters.push( - new ethereum.EventParam("ids", ethereum.Value.fromUnsignedBigIntArray(ids)) + parameters.push( + new ethereum.EventParam("ids", ethereum.Value.fromUnsignedBigIntArray(ids)), ); - transferBatchEvent.parameters.push( + parameters.push( new ethereum.EventParam( "values", - ethereum.Value.fromUnsignedBigIntArray(values) - ) + ethereum.Value.fromUnsignedBigIntArray(values), + ), + ); + + let transferBatchEvent = new TransferBatch( + getDefaultContractAddress(), + mockEvent.logIndex, + mockEvent.transactionLogIndex, + mockEvent.logType, + mockEvent.block, + mockEvent.transaction, + parameters, + mockEvent.receipt, ); return transferBatchEvent; @@ -183,25 +198,25 @@ export function createTransferSingleEvent( from: Address, to: Address, id: BigInt, - value: BigInt + value: BigInt, ): TransferSingle { let mockEvent = newMockEvent(); let parameters: ethereum.EventParam[] = new Array(); parameters.push( - new ethereum.EventParam("operator", ethereum.Value.fromAddress(operator)) + new ethereum.EventParam("operator", ethereum.Value.fromAddress(operator)), ); parameters.push( - new ethereum.EventParam("from", ethereum.Value.fromAddress(from)) + new ethereum.EventParam("from", ethereum.Value.fromAddress(from)), ); parameters.push( - new ethereum.EventParam("to", ethereum.Value.fromAddress(to)) + new ethereum.EventParam("to", ethereum.Value.fromAddress(to)), ); parameters.push( - new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)) + new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)), ); parameters.push( - new ethereum.EventParam("value", ethereum.Value.fromUnsignedBigInt(value)) + new ethereum.EventParam("value", ethereum.Value.fromUnsignedBigInt(value)), ); let transferSingleEvent = new TransferSingle( @@ -212,7 +227,7 @@ export function createTransferSingleEvent( mockEvent.block, mockEvent.transaction, parameters, - mockEvent.receipt + mockEvent.receipt, ); return transferSingleEvent; @@ -224,20 +239,20 @@ export function createURIEvent(value: string, id: BigInt): URI { uriEvent.parameters = new Array(); uriEvent.parameters.push( - new ethereum.EventParam("value", ethereum.Value.fromString(value)) + new ethereum.EventParam("value", ethereum.Value.fromString(value)), ); uriEvent.parameters.push( - new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)) + new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)), ); return uriEvent; } export function createHypercertMinterUpgradedEvent( - implementation: Address + implementation: Address, ): HypercertMinterUpgraded { let hypercertMinterUpgradedEvent = changetype( - newMockEvent() + newMockEvent(), ); hypercertMinterUpgradedEvent.parameters = new Array(); @@ -245,8 +260,8 @@ export function createHypercertMinterUpgradedEvent( hypercertMinterUpgradedEvent.parameters.push( new ethereum.EventParam( "implementation", - ethereum.Value.fromAddress(implementation) - ) + ethereum.Value.fromAddress(implementation), + ), ); return hypercertMinterUpgradedEvent; @@ -256,7 +271,7 @@ export function createValueTransferEvent( claimID: BigInt, fromTokenID: BigInt, toTokenID: BigInt, - value: BigInt + value: BigInt, ): ValueTransfer { let mockEvent = newMockEvent(); let parameters: ethereum.EventParam[] = new Array(); @@ -264,24 +279,24 @@ export function createValueTransferEvent( parameters.push( new ethereum.EventParam( "claimID", - ethereum.Value.fromUnsignedBigInt(claimID) - ) + ethereum.Value.fromUnsignedBigInt(claimID), + ), ); parameters.push( new ethereum.EventParam( "fromTokenID", - ethereum.Value.fromUnsignedBigInt(fromTokenID) - ) + ethereum.Value.fromUnsignedBigInt(fromTokenID), + ), ); parameters.push( new ethereum.EventParam( "toTokenID", - ethereum.Value.fromUnsignedBigInt(toTokenID) - ) + ethereum.Value.fromUnsignedBigInt(toTokenID), + ), ); parameters.push( - new ethereum.EventParam("value", ethereum.Value.fromUnsignedBigInt(value)) + new ethereum.EventParam("value", ethereum.Value.fromUnsignedBigInt(value)), ); let valueTransferEvent = new ValueTransfer( @@ -292,7 +307,7 @@ export function createValueTransferEvent( mockEvent.block, mockEvent.transaction, parameters, - mockEvent.receipt + mockEvent.receipt, ); return valueTransferEvent; @@ -302,7 +317,7 @@ export function createBatchValueTransferEvent( claimIDs: BigInt[], fromTokenIDs: BigInt[], toTokenIDs: BigInt[], - values: BigInt[] + values: BigInt[], ): BatchValueTransfer { let mockEvent = newMockEvent(); let parameters: ethereum.EventParam[] = new Array(); @@ -310,26 +325,26 @@ export function createBatchValueTransferEvent( parameters.push( new ethereum.EventParam( "claimIDs", - ethereum.Value.fromUnsignedBigIntArray(claimIDs) - ) + ethereum.Value.fromUnsignedBigIntArray(claimIDs), + ), ); parameters.push( new ethereum.EventParam( "fromTokenIDs", - ethereum.Value.fromUnsignedBigIntArray(fromTokenIDs) - ) + ethereum.Value.fromUnsignedBigIntArray(fromTokenIDs), + ), ); parameters.push( new ethereum.EventParam( "toTokenIDs", - ethereum.Value.fromUnsignedBigIntArray(toTokenIDs) - ) + ethereum.Value.fromUnsignedBigIntArray(toTokenIDs), + ), ); parameters.push( new ethereum.EventParam( "values", - ethereum.Value.fromUnsignedBigIntArray(values) - ) + ethereum.Value.fromUnsignedBigIntArray(values), + ), ); let batchValueTransferEvent = new BatchValueTransfer( @@ -340,7 +355,7 @@ export function createBatchValueTransferEvent( mockEvent.block, mockEvent.transaction, parameters, - mockEvent.receipt + mockEvent.receipt, ); return batchValueTransferEvent; diff --git a/package.json b/package.json index 2fa76408..179cbb48 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "copy:html": "find build/ -name '*.html' -type f | grep -v index.html | sed s/\\.html$// | xargs -I _ bash -c 'mkdir -p _ && cp -v _.html _/index.html'", "deploy:cors-proxy": "turbo run deploy --filter=@hypercerts-org/cors-proxy --parallel", "deploy:defender": "turbo run deploy --filter=hypercerts-defender --parallel", - "deploy:graph": "turbo run deploy --filter=@hypercerts-org/graph --parallel", + "deploy:graph:goerli": "turbo run deploy:goerli --filter=@hypercerts-org/graph --parallel", + "deploy:graph:optimism": "turbo run deploy:optimism --filter=@hypercerts-org/graph --parallel", "deploy:os-observer": "turbo run deploy --filter=@hypercerts-org/os-observer --parallel", "deploy:site": "turbo run build --filter=@hypercerts-org/docs --filter=hypercerts-protocol && turbo run deploy --filter=@hypercerts-org/frontend && yarn copy", "dev:cors-proxy": "turbo run dev --filter=@hypercerts-org/cors-proxy --parallel", diff --git a/yarn.lock b/yarn.lock index 94734598..7a7f5f48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2027,6 +2027,14 @@ postcss-sort-media-queries "^4.2.1" tslib "^2.4.0" +"@docusaurus/eslint-plugin@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/eslint-plugin/-/eslint-plugin-2.4.1.tgz#37e143eee599a865ac363c4f33291d35d3bf238b" + integrity sha512-Sb+aLgf07v2xenPHlcBtvADFkE6xi1Nx9cKNb98Tq5MGoywHpxUfwT3RHar+eA8vCjR3fu0npSzuRt26AJa5lw== + dependencies: + "@typescript-eslint/utils" "^5.30.5" + tslib "^2.4.0" + "@docusaurus/logger@2.4.1": version "2.4.1" resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.4.1.tgz#4d2c0626b40752641f9fdd93ad9b5a7a0792f767" @@ -8836,7 +8844,7 @@ eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/utils@5.62.0": +"@typescript-eslint/utils@5.62.0", "@typescript-eslint/utils@^5.30.5": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== From 7eb8c8dd49eed9b25bfff7e04d8626be5f62be99 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Tue, 29 Aug 2023 16:21:56 +0200 Subject: [PATCH 02/49] chore(turbo): split graph deploys (#1055) --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 179cbb48..79ab3939 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,8 @@ "copy:html": "find build/ -name '*.html' -type f | grep -v index.html | sed s/\\.html$// | xargs -I _ bash -c 'mkdir -p _ && cp -v _.html _/index.html'", "deploy:cors-proxy": "turbo run deploy --filter=@hypercerts-org/cors-proxy --parallel", "deploy:defender": "turbo run deploy --filter=hypercerts-defender --parallel", - "deploy:graph:goerli": "turbo run deploy:goerli --filter=@hypercerts-org/graph --parallel", - "deploy:graph:optimism": "turbo run deploy:optimism --filter=@hypercerts-org/graph --parallel", + "deploy:graph:goerli": "yarn workspace graph deploy:goerli", + "deploy:graph:optimism": "yarn workspace graph deploy:optimism", "deploy:os-observer": "turbo run deploy --filter=@hypercerts-org/os-observer --parallel", "deploy:site": "turbo run build --filter=@hypercerts-org/docs --filter=hypercerts-protocol && turbo run deploy --filter=@hypercerts-org/frontend && yarn copy", "dev:cors-proxy": "turbo run dev --filter=@hypercerts-org/cors-proxy --parallel", From e4a0cdf96fa4ba366d0c421c39e30605974ac1b1 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Tue, 29 Aug 2023 16:59:47 +0200 Subject: [PATCH 03/49] Fix/workspace label (#1060) chore(yarn): update workspace label --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 79ab3939..b7defa66 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,8 @@ "copy:html": "find build/ -name '*.html' -type f | grep -v index.html | sed s/\\.html$// | xargs -I _ bash -c 'mkdir -p _ && cp -v _.html _/index.html'", "deploy:cors-proxy": "turbo run deploy --filter=@hypercerts-org/cors-proxy --parallel", "deploy:defender": "turbo run deploy --filter=hypercerts-defender --parallel", - "deploy:graph:goerli": "yarn workspace graph deploy:goerli", - "deploy:graph:optimism": "yarn workspace graph deploy:optimism", + "deploy:graph:goerli": "yarn workspace @hypercerts-org/graph deploy:goerli", + "deploy:graph:optimism": "yarn workspace @hypercerts-org/graph deploy:optimism", "deploy:os-observer": "turbo run deploy --filter=@hypercerts-org/os-observer --parallel", "deploy:site": "turbo run build --filter=@hypercerts-org/docs --filter=hypercerts-protocol && turbo run deploy --filter=@hypercerts-org/frontend && yarn copy", "dev:cors-proxy": "turbo run dev --filter=@hypercerts-org/cors-proxy --parallel", From 4cfd9805f12c7ec3dff7d356f0043b9cae2c97b3 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Tue, 29 Aug 2023 18:34:31 +0200 Subject: [PATCH 04/49] 1052 subgraph a claimed token should indicate whether it was claimed from an allowlist (#1058) * fix(graph): link claim with allowlist * chore(tweak): yada --- graph/generated/schema.ts | 17 +++++++++++++++++ graph/schema.graphql | 1 + 2 files changed, 18 insertions(+) diff --git a/graph/generated/schema.ts b/graph/generated/schema.ts index 7834b274..a1ae231d 100644 --- a/graph/generated/schema.ts +++ b/graph/generated/schema.ts @@ -222,6 +222,23 @@ export class Claim extends Entity { this.set("totalUnits", Value.fromBigInt(value)); } } + + get allowlist(): string | null { + let value = this.get("allowlist"); + if (!value || value.kind == ValueKind.NULL) { + return null; + } else { + return value.toString(); + } + } + + set allowlist(value: string | null) { + if (!value) { + this.unset("allowlist"); + } else { + this.set("allowlist", Value.fromString(value)); + } + } } export class ClaimToken extends Entity { diff --git a/graph/schema.graphql b/graph/schema.graphql index 85e54ed2..c2c8b8d5 100644 --- a/graph/schema.graphql +++ b/graph/schema.graphql @@ -13,6 +13,7 @@ type Claim @entity { creator: Bytes owner: Bytes totalUnits: BigInt + allowlist: Allowlist } type ClaimToken @entity { From 9487577448d7affbc817840b94b3149689f5ebb3 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Tue, 29 Aug 2023 20:59:49 +0200 Subject: [PATCH 05/49] fix(graph): update mapping to claim (#1061) --- graph/src/utils.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/graph/src/utils.ts b/graph/src/utils.ts index a401c245..f60642b5 100644 --- a/graph/src/utils.ts +++ b/graph/src/utils.ts @@ -9,9 +9,9 @@ export function getID(tokenID: BigInt, contract: Address): string { export function getOrCreateAllowlist( claimID: BigInt, root: Bytes, - contract: Address + contract: Address, ): Allowlist { - let id = getID(claimID, contract); + const id = getID(claimID, contract); let list = Allowlist.load(id); log.debug("Created allowlistID: {}", [id]); @@ -29,18 +29,24 @@ export function getOrCreateAllowlist( export function getOrCreateClaim( claimID: BigInt, contract: Address, - timestamp: BigInt + timestamp: BigInt, ): Claim { - let id = getID(claimID, contract); + const id = getID(claimID, contract); let claim = Claim.load(id); log.debug("Created claimID: {}", [id]); if (claim == null) { claim = new Claim(id); + const list = Allowlist.load(id); + if (timestamp) { claim.creation = timestamp; } + + if (list) { + claim.allowlist = list.id; + } claim.tokenID = claimID; claim.contract = contract.toHexString(); claim.save(); @@ -52,17 +58,17 @@ export function getOrCreateClaim( export function getOrCreateClaimToken( claimID: BigInt, tokenID: BigInt, - contract: Address + contract: Address, ): ClaimToken { - let minterContract = HypercertMinter.bind(contract); + const minterContract = HypercertMinter.bind(contract); - let id = getID(tokenID, contract); + const id = getID(tokenID, contract); let fraction = ClaimToken.load(id); if (fraction == null) { log.debug("Creating claimToken: {}", [id]); - let owner = minterContract.ownerOf(tokenID); + const owner = minterContract.ownerOf(tokenID); fraction = new ClaimToken(id); fraction.owner = owner; From c19514793952f08ee840ee5c80818ece27ad415a Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Wed, 6 Sep 2023 00:46:41 +0200 Subject: [PATCH 06/49] nitial trader implementation (#1063) * feat(iface): draft of trader interface * feat(trader): simple offer, buy, cancel flow * feat(db): update allowlist query (#1057) * feat(test): tweaks and initial tests for Trader * chore(gha): remove hardcoded foundry nightly * feat(test): add initial test for trader sales * feat(test): sales tests * feat(deploy): deployed to goerli * chore(ci): updated hh scripts for trader contract * feat(pause): pausable controls and tests * feat(trader): init trader graph --- .github/workflows/ci-default.yml | 2 - contracts/.openzeppelin/goerli.json | 880 ++++++++++++++++++ contracts/README.md | 4 +- contracts/src/HypercertTrader.sol | 401 ++++++++ contracts/src/SemiFungible1155.sol | 2 +- contracts/src/interfaces/IHypercertTrader.sol | 128 +++ contracts/tasks/deploy.ts | 47 +- contracts/tasks/transfer-owner.ts | 36 +- contracts/tasks/upgrade.ts | 69 +- .../test/foundry/HypercertTrader.admin.t.sol | 92 ++ .../test/foundry/HypercertTrader.offers.t.sol | 208 +++++ .../test/foundry/HypercertTrader.sales.t.sol | 245 +++++ .../foundry/SemiFungible1155.transfers.t.sol | 10 +- .../api/contracts/HypercertTrader.md | 416 +++++++++ .../api/contracts/IHypercertMinter.md | 39 + .../contracts/interfaces/IHypercertTrader.md | 133 +++ frontend/hooks/mintFractionAllowlistBatch.ts | 11 +- graph/abis/HypercertTrader.json | 456 +++++++++ .../HypercertTrader/HypercertTrader.ts | 875 +++++++++++++++++ graph/generated/schema.ts | 357 +++++++ graph/networks.json | 4 + graph/schema.graphql | 37 + graph/src/hypercert-trader.ts | 69 ++ graph/src/utils.ts | 96 +- graph/subgraph.yaml | 32 +- graph/tests/.latest.json | 2 +- graph/tests/hypercert-minter-burn.test.ts | 4 - graph/tests/hypercert-minter-claim.test.ts | 6 +- graph/tests/hypercert-trader-utils.ts | 261 ++++++ graph/tests/hypercert-trader.test.ts | 63 ++ 30 files changed, 4940 insertions(+), 45 deletions(-) create mode 100644 contracts/src/HypercertTrader.sol create mode 100644 contracts/src/interfaces/IHypercertTrader.sol create mode 100644 contracts/test/foundry/HypercertTrader.admin.t.sol create mode 100644 contracts/test/foundry/HypercertTrader.offers.t.sol create mode 100644 contracts/test/foundry/HypercertTrader.sales.t.sol create mode 100644 docs/docs/developer/api/contracts/HypercertTrader.md create mode 100644 docs/docs/developer/api/contracts/IHypercertMinter.md create mode 100644 docs/docs/developer/api/contracts/interfaces/IHypercertTrader.md create mode 100644 graph/abis/HypercertTrader.json create mode 100644 graph/generated/HypercertTrader/HypercertTrader.ts create mode 100644 graph/src/hypercert-trader.ts create mode 100644 graph/tests/hypercert-trader-utils.ts create mode 100644 graph/tests/hypercert-trader.test.ts diff --git a/.github/workflows/ci-default.yml b/.github/workflows/ci-default.yml index 5583e41f..1caeed21 100644 --- a/.github/workflows/ci-default.yml +++ b/.github/workflows/ci-default.yml @@ -63,8 +63,6 @@ jobs: cache: "yarn" - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly-bff4ed912bb023d7bf9b20eda581aa4867a1cf70 - name: Install run: | yarn install --immutable diff --git a/contracts/.openzeppelin/goerli.json b/contracts/.openzeppelin/goerli.json index f6d23067..abb0c675 100644 --- a/contracts/.openzeppelin/goerli.json +++ b/contracts/.openzeppelin/goerli.json @@ -30,6 +30,11 @@ "address": "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", "txHash": "0xeeb032f25fb656971f835204d0bd825f766593afadfe420110903420bb4f7071", "kind": "uups" + }, + { + "address": "0x689587461AA3103D3D7975c5e4B352Ab711C14C2", + "txHash": "0x236119a264468c853263e067fbde6781c2c4109a5a3027a9adcfdca56b9bdacb", + "kind": "uups" } ], "impls": { @@ -4768,6 +4773,881 @@ } } } + }, + "d1832c305d4610ff816070ba0b32f8fcbb0e86cead29b4261acf08bd5c0836e6": { + "address": "0x8561eAE9962FA3af19e2E972Ea717d4AD407BDbF", + "txHash": "0x0bcef85a53eb6fdec51cfa3c817e013b1ecf19f0a9387384202fae0ef66985a2", + "layout": { + "solcVersion": "0.8.16", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_paused", + "offset": 0, + "slot": "101", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "201", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol:107" + }, + { + "label": "totalUnitsForSale", + "offset": 0, + "slot": "251", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:30" + }, + { + "label": "offers", + "offset": 0, + "slot": "252", + "type": "t_mapping(t_uint256,t_struct(Offer)7905_storage)", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:31" + }, + { + "label": "_offerCounter", + "offset": 0, + "slot": "253", + "type": "t_uint256", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:32" + }, + { + "label": "__gap", + "offset": 0, + "slot": "254", + "type": "t_array(t_uint256)27_storage", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:359" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(AcceptedToken)7917_storage)dyn_storage": { + "label": "struct IHypercertTrader.AcceptedToken[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)27_storage": { + "label": "uint256[27]", + "numberOfBytes": "864" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_enum(OfferStatus)7912": { + "label": "enum IHypercertTrader.OfferStatus", + "members": [ + "Open", + "Fulfilled", + "Cancelled" + ], + "numberOfBytes": "1" + }, + "t_enum(OfferType)7908": { + "label": "enum IHypercertTrader.OfferType", + "members": [ + "Units", + "Fraction" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { + "label": "mapping(address => mapping(uint256 => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Offer)7905_storage)": { + "label": "mapping(uint256 => struct IHypercertTrader.Offer)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(AcceptedToken)7917_storage": { + "label": "struct IHypercertTrader.AcceptedToken", + "members": [ + { + "label": "token", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "minimumAmountPerUnit", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Offer)7905_storage": { + "label": "struct IHypercertTrader.Offer", + "members": [ + { + "label": "offerer", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "hypercertContract", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "fractionID", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "unitsAvailable", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "minUnitsPerTrade", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "maxUnitsPerTrade", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "offerType", + "type": "t_enum(OfferType)7908", + "offset": 0, + "slot": "6" + }, + { + "label": "status", + "type": "t_enum(OfferStatus)7912", + "offset": 1, + "slot": "6" + }, + { + "label": "acceptedTokens", + "type": "t_array(t_struct(AcceptedToken)7917_storage)dyn_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "dd332b99b39b573f44ffeb5c8685891923934c7ddf4763cc7767f224483eff8a": { + "address": "0x0A00a2f09cd37B24E7429c5238323bfebCfF3Ed9", + "txHash": "0xa2c8831ddf933b36362efd3e4cd6a0f2ba640d0a4908f3f97ae43c4661077ead", + "layout": { + "solcVersion": "0.8.16", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_balances", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:25" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:28" + }, + { + "label": "_uri", + "offset": 0, + "slot": "103", + "type": "t_string_storage", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "104", + "type": "t_array(t_uint256)47_storage", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:528" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1155BurnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol:52" + }, + { + "label": "_baseURI", + "offset": 0, + "slot": "201", + "type": "t_string_storage", + "contract": "ERC1155URIStorageUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol:27" + }, + { + "label": "_tokenURIs", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_uint256,t_string_storage)", + "contract": "ERC1155URIStorageUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol:30" + }, + { + "label": "__gap", + "offset": 0, + "slot": "203", + "type": "t_array(t_uint256)48_storage", + "contract": "ERC1155URIStorageUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol:77" + }, + { + "label": "_owner", + "offset": 0, + "slot": "251", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "301", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "351", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol:107" + }, + { + "label": "typeCounter", + "offset": 0, + "slot": "401", + "type": "t_uint256", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:27" + }, + { + "label": "owners", + "offset": 0, + "slot": "402", + "type": "t_mapping(t_uint256,t_address)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:38" + }, + { + "label": "creators", + "offset": 0, + "slot": "403", + "type": "t_mapping(t_uint256,t_address)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:41" + }, + { + "label": "tokenValues", + "offset": 0, + "slot": "404", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:44" + }, + { + "label": "maxIndex", + "offset": 0, + "slot": "405", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:47" + }, + { + "label": "__gap", + "offset": 0, + "slot": "406", + "type": "t_array(t_uint256)25_storage", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:612" + }, + { + "label": "merkleRoots", + "offset": 0, + "slot": "431", + "type": "t_mapping(t_uint256,t_bytes32)", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:17" + }, + { + "label": "hasBeenClaimed", + "offset": 0, + "slot": "432", + "type": "t_mapping(t_uint256,t_mapping(t_bytes32,t_bool))", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:18" + }, + { + "label": "maxUnits", + "offset": 0, + "slot": "433", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:19" + }, + { + "label": "minted", + "offset": 0, + "slot": "434", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "435", + "type": "t_array(t_uint256)26_storage", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:69" + }, + { + "label": "_paused", + "offset": 0, + "slot": "461", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "462", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:116" + }, + { + "label": "typeRestrictions", + "offset": 0, + "slot": "511", + "type": "t_mapping(t_uint256,t_enum(TransferRestrictions)7777)", + "contract": "HypercertMinter", + "src": "src/HypercertMinter.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "512", + "type": "t_array(t_uint256)29_storage", + "contract": "HypercertMinter", + "src": "src/HypercertMinter.sol:246" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)25_storage": { + "label": "uint256[25]", + "numberOfBytes": "800" + }, + "t_array(t_uint256)26_storage": { + "label": "uint256[26]", + "numberOfBytes": "832" + }, + "t_array(t_uint256)29_storage": { + "label": "uint256[29]", + "numberOfBytes": "928" + }, + "t_array(t_uint256)47_storage": { + "label": "uint256[47]", + "numberOfBytes": "1504" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_enum(TransferRestrictions)7777": { + "label": "enum IHypercertToken.TransferRestrictions", + "members": [ + "AllowAll", + "DisallowAll", + "FromCreatorOnly" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_bytes32)": { + "label": "mapping(uint256 => bytes32)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_enum(TransferRestrictions)7777)": { + "label": "mapping(uint256 => enum IHypercertToken.TransferRestrictions)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_bytes32,t_bool))": { + "label": "mapping(uint256 => mapping(bytes32 => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_string_storage)": { + "label": "mapping(uint256 => string)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "18f4479dd70171f19657f8c092580a0d6e9ec28cf1867e45d3e9e87aff3e1ee2": { + "address": "0xFf3F27c6132c30d1098b97FfeC05C3150dA90432", + "txHash": "0xaf2c9d0708fafea03a10da1e6b25f340c4a2847b09032d2890d40167496c7b49", + "layout": { + "solcVersion": "0.8.16", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_paused", + "offset": 0, + "slot": "101", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "201", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol:107" + }, + { + "label": "totalUnitsForSale", + "offset": 0, + "slot": "251", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:36" + }, + { + "label": "offers", + "offset": 0, + "slot": "252", + "type": "t_mapping(t_uint256,t_struct(Offer)7990_storage)", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:37" + }, + { + "label": "_offerCounter", + "offset": 0, + "slot": "253", + "type": "t_uint256", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "254", + "type": "t_array(t_uint256)27_storage", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:387" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(AcceptedToken)8002_storage)dyn_storage": { + "label": "struct IHypercertTrader.AcceptedToken[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)27_storage": { + "label": "uint256[27]", + "numberOfBytes": "864" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_enum(OfferStatus)7997": { + "label": "enum IHypercertTrader.OfferStatus", + "members": [ + "Open", + "Fulfilled", + "Cancelled" + ], + "numberOfBytes": "1" + }, + "t_enum(OfferType)7993": { + "label": "enum IHypercertTrader.OfferType", + "members": [ + "Units", + "Fraction" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { + "label": "mapping(address => mapping(uint256 => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Offer)7990_storage)": { + "label": "mapping(uint256 => struct IHypercertTrader.Offer)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(AcceptedToken)8002_storage": { + "label": "struct IHypercertTrader.AcceptedToken", + "members": [ + { + "label": "token", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "minimumAmountPerUnit", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Offer)7990_storage": { + "label": "struct IHypercertTrader.Offer", + "members": [ + { + "label": "offerer", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "hypercertContract", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "fractionID", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "unitsAvailable", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "minUnitsPerTrade", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "maxUnitsPerTrade", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "offerType", + "type": "t_enum(OfferType)7993", + "offset": 0, + "slot": "6" + }, + { + "label": "status", + "type": "t_enum(OfferStatus)7997", + "offset": 1, + "slot": "6" + }, + { + "label": "acceptedTokens", + "type": "t_array(t_struct(AcceptedToken)8002_storage)dyn_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } } } } diff --git a/contracts/README.md b/contracts/README.md index 6320a762..fc293242 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -88,7 +88,7 @@ yarn hardhat deploy --network goerli To transfer ownership of the proxy contract for upgrades, run the following: ```sh -yarn hardhat transfer-owner --network goerli --proxy PROXY_CONTRACT_ADDRESS --owner NEW_OWNER_ADDRESS +yarn hardhat transfer-owner-minter --network goerli --proxy PROXY_CONTRACT_ADDRESS --owner NEW_OWNER_ADDRESS ``` This is typically done to transfer control to a multi-sig (i.e. Gnosis Safe). @@ -110,7 +110,7 @@ Propose an upgrade via OpenZeppelin Defender. For more information, see this ```sh yarn build:hardhat -yarn hardhat propose-upgrade --network goerli --proxy PROXY_CONTRACT_ADDRESS --multisig OWNER_MULTISIG_ADDRESS +yarn hardhat propose-upgrade-minter --network goerli --proxy PROXY_CONTRACT_ADDRESS --multisig OWNER_MULTISIG_ADDRESS ``` This will output an OpenZeppelin URL that multi-sig members can use to approve/reject the upgrade. diff --git a/contracts/src/HypercertTrader.sol b/contracts/src/HypercertTrader.sol new file mode 100644 index 00000000..dfc08c1a --- /dev/null +++ b/contracts/src/HypercertTrader.sol @@ -0,0 +1,401 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +import { IHypercertTrader } from "./interfaces/IHypercertTrader.sol"; +import { IHypercertToken } from "./interfaces/IHypercertToken.sol"; +import { PausableUpgradeable } from "oz-upgradeable/security/PausableUpgradeable.sol"; +import { IERC1155Upgradeable } from "oz-upgradeable/token/ERC1155/IERC1155Upgradeable.sol"; +import { OwnableUpgradeable } from "oz-upgradeable/access/OwnableUpgradeable.sol"; +import { Initializable } from "oz-upgradeable/proxy/utils/Initializable.sol"; +import { UUPSUpgradeable } from "oz-upgradeable/proxy/utils/UUPSUpgradeable.sol"; + +import { Errors } from "./libs/Errors.sol"; + +error NotAllowed(); +error InvalidOffer(string); +error InvalidBuy(string); + +interface IHypercertMinter { + function ownerOf(uint256 id) external view returns (address); + + function unitsOf(uint256 id) external view returns (uint256); +} + +/** + * @title Contract for managing hypercert trades + * @notice Implementation of the HypercertTrader Interface + * @author bitbeckers + */ +contract HypercertTrader is IHypercertTrader, Initializable, OwnableUpgradeable, PausableUpgradeable, UUPSUpgradeable { + mapping(address => mapping(uint256 => uint256)) public totalUnitsForSale; + mapping(uint256 => Offer) public offers; + uint256 internal _offerCounter; + + /// INIT + + /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } + function initialize() public virtual initializer { + __Pausable_init(); + __Ownable_init(); + __UUPSUpgradeable_init(); + } + + /** + * @dev Creates a new offer to sell Hypercert tokens. + * @param hypercertContract The address of the Hypercert token contract. + * @param fractionID The ID of the fraction to sell. + * @param unitsForSale The number of units available for sale. + * @param minUnitsPerTrade The minimum number of units that can be bought in a single trade. + * @param maxUnitsPerTrade The maximum number of units that can be bought in a single trade. + * @param acceptedTokens The list of tokens that are accepted for payment. + * @notice This function creates a new offer to sell Hypercert tokens. The offer specifies the Hypercert token contract, + * the fraction to sell, the number of units available for sale, the minimum and maximum number of units that can be bought + * in a single trade, and the list of tokens that are accepted for payment. The offer is added to the list of existing offers + * and can be bought by other users using the `buyUnits` function. + */ + //TODO remove payable from offer + function createOffer( + address hypercertContract, + uint256 fractionID, + uint256 unitsForSale, + uint256 minUnitsPerTrade, + uint256 maxUnitsPerTrade, + AcceptedToken[] memory acceptedTokens + ) external payable whenNotPaused returns (uint256 offerID) { + // This checks is the contract is approved to trade on behalf of the owner at the time of offering. + // However, the owner can revoke this approval at any time. + if (!IERC1155Upgradeable(hypercertContract).isApprovedForAll(msg.sender, address(this))) revert NotAllowed(); + + _validateOffer( + msg.sender, + hypercertContract, + fractionID, + unitsForSale, + minUnitsPerTrade, + maxUnitsPerTrade, + acceptedTokens + ); + + offerID = _offerCounter; + offers[offerID] = _createOffer( + msg.sender, + hypercertContract, + fractionID, + unitsForSale, + minUnitsPerTrade, + maxUnitsPerTrade, + acceptedTokens + ); + + _offerCounter += 1; + totalUnitsForSale[hypercertContract][fractionID] += unitsForSale; + + emit OfferCreated(msg.sender, hypercertContract, fractionID, offerID); + } + + /** + * @dev Buys Hypercert tokens from an existing offer. + * @param recipient The address that will receive the Hypercert tokens. + * @param offerID The ID of the offer to buy from. + * @param unitAmount The number of units to buy. + * @param buyToken The address of the token used for payment. + * @param tokenAmountPerUnit The amount of tokens to pay per unit. + * @notice This function buys Hypercert tokens from an existing offer. The function verifies that the offer is valid and that + * the buyer has provided enough payment in the specified token. If the offer is for a fraction of a Hypercert token, the function + * splits the fraction and transfers the appropriate number of units to the buyer. If the offer is for a fixed number of units, + * the function transfers the units to the buyer. The function also transfers the payment to the offerer and emits a `Trade` event. + */ + function buyUnits( + address recipient, + uint256 offerID, + uint256 unitAmount, + address buyToken, + uint256 tokenAmountPerUnit + ) public payable whenNotPaused { + // Get the offer and validate that it is open and has enough units available + Offer storage offer = offers[offerID]; + _validateBuyOffer(offer, unitAmount, buyToken, tokenAmountPerUnit); + + offer.unitsAvailable -= unitAmount; + totalUnitsForSale[offer.hypercertContract][offer.fractionID] -= unitAmount; + + if (offer.unitsAvailable == 0) { + offer.status = OfferStatus.Fulfilled; + } + + uint256 unitsInFraction = IHypercertMinter(offer.hypercertContract).unitsOf(offer.fractionID); + + // Check if full fraction is being bought + if (unitsInFraction == unitAmount) { + IERC1155Upgradeable(offer.hypercertContract).safeTransferFrom( + offer.offerer, + recipient, + offer.fractionID, + 1, + "" + ); + } else { + // Create uint256[] for the split with the remaining units and units to transfer + uint256[] memory units = new uint256[](2); + units[0] = unitsInFraction - unitAmount; + units[1] = unitAmount; + + IHypercertToken(offer.hypercertContract).splitFraction(recipient, offer.fractionID, units); + } + (bool success, ) = payable(offer.offerer).call{ value: msg.value }(""); + if (!success) revert InvalidBuy("Payment failed"); + + emit Trade( + offer.offerer, + recipient, + offer.hypercertContract, + offer.fractionID, + unitAmount, + buyToken, + tokenAmountPerUnit, + offerID + ); + } + + /** + * @dev Buys Hypercert tokens from multiple existing offers in a single transaction. + * @param recipient The address that will receive the Hypercert tokens. + * @param offerIDs The list of IDs of the offers to buy from. + * @param unitAmounts The list of numbers of units to buy for each offer. + * @param buyTokens The list of addresses of the tokens used for payment for each offer. + * @param tokenAmountsPerUnit The list of amounts of tokens to pay per unit for each offer. + * @notice This function allows a user to buy Hypercert tokens from multiple existing offers in a single transaction. + * The function takes in several arrays of parameters, including the IDs of the offers to buy from, + * the number of units to buy for each offer, the tokens used for payment for each offer, + * and the amounts of tokens to pay per unit for each offer. + * The function then executes the trades and transfers the Hypercert tokens to the specified recipient. + */ + function batchBuyUnits( + address recipient, + uint256[] calldata offerIDs, + uint256[] calldata unitAmounts, + address[] calldata buyTokens, + uint256[] calldata tokenAmountsPerUnit + ) external payable whenNotPaused { + uint256 len = offerIDs.length; + for (uint256 i; i < len; ) { + buyUnits(recipient, offerIDs[i], unitAmounts[i], buyTokens[i], tokenAmountsPerUnit[i]); + unchecked { + ++i; + } + } + } + + /** + * @dev Cancels an existing offer. + * @param offerID The ID of the offer to cancel. + * @notice This function cancels an existing offer. The function verifies that the offer exists and that the caller is the offerer. + * The function sets the offer status to `Cancelled` and emits an `OfferCancelled` event. + */ + function cancelOffer(uint256 offerID) external whenNotPaused { + // Get the offer and validate that the caller is the offerer + Offer storage offer = offers[offerID]; + if (offer.hypercertContract == address(0)) revert InvalidOffer("No contract address found"); + if (offer.offerer != msg.sender) revert NotAllowed(); + if (offer.status != OfferStatus.Open) revert InvalidOffer("status"); + + // Update the offer and emit an OfferCancelled event + offer.status = OfferStatus.Cancelled; + totalUnitsForSale[offer.hypercertContract][offer.fractionID] -= offer.unitsAvailable; + emit OfferCancelled(msg.sender, offer.hypercertContract, offer.fractionID, offerID); + } + + /// PAUSABLE + + function pause() external onlyOwner { + _pause(); + } + + function unpause() external onlyOwner { + _unpause(); + } + + /// INTERNAL + + /** + * @dev Internal function to create a new offer to sell Hypercert tokens. + * @param offerer The address of the offerer. + * @param hypercertContract The address of the Hypercert token contract. + * @param fractionID The ID of the fraction to sell. + * @param unitsAvailable The number of units available for sale. + * @param minUnitsPerTrade The minimum number of units that can be bought in a single trade. + * @param maxUnitsPerTrade The maximum number of units that can be bought in a single trade. + * @param acceptedTokens The list of tokens that are accepted for payment. + * @return The storage reference to the newly created offer. + */ + function _createOffer( + address offerer, + address hypercertContract, + uint256 fractionID, + uint256 unitsAvailable, + uint256 minUnitsPerTrade, + uint256 maxUnitsPerTrade, + AcceptedToken[] memory acceptedTokens + ) internal returns (Offer storage) { + // TODO optimise init and adding accepted tokens + Offer storage offer = offers[_offerCounter]; + offer.offerer = offerer; + offer.hypercertContract = hypercertContract; + offer.fractionID = fractionID; + offer.unitsAvailable = unitsAvailable; + offer.minUnitsPerTrade = minUnitsPerTrade; + offer.maxUnitsPerTrade = maxUnitsPerTrade; + offer.status = OfferStatus.Open; + + if (minUnitsPerTrade == maxUnitsPerTrade) { + offer.offerType = OfferType.Fraction; + } else { + offer.offerType = OfferType.Units; + } + + uint256 len = acceptedTokens.length; + for (uint256 i; i < len; ) { + offer.acceptedTokens.push(AcceptedToken(acceptedTokens[i].token, acceptedTokens[i].minimumAmountPerUnit)); + + unchecked { + ++i; + } + } + + return offer; + } + + /** + * @dev Validates the parameters for a new offer. + * @param hypercertContract The address of the Hypercert token contract. + * @param fractionID The ID of the fraction to sell. + * @param unitsForSale The number of units available for sale. + * @param minUnitsPerTrade The minimum number of units that can be bought in a single trade. + * @param maxUnitsPerTrade The maximum number of units that can be bought in a single trade. + * @param acceptedTokens The list of tokens that are accepted for payment. + * @notice This internal function validates the parameters for a new offer. The function verifies that the Hypercert token contract + * exists and that the fraction ID is valid. The function also verifies that the units available, minimum units per trade, and maximum + * units per trade are valid and that the accepted tokens list is not empty. + */ + function _validateOffer( + address offerer, + address hypercertContract, + uint256 fractionID, + uint256 unitsForSale, + uint256 minUnitsPerTrade, + uint256 maxUnitsPerTrade, + AcceptedToken[] memory acceptedTokens + ) internal view returns (bool) { + if (IHypercertMinter(hypercertContract).ownerOf(fractionID) != offerer) revert InvalidOffer("Not owner"); + + // Validate units exist and are available + uint256 totalUnits = IHypercertMinter(hypercertContract).unitsOf(fractionID); + if ( + unitsForSale == 0 || + totalUnits < unitsForSale || + totalUnits < totalUnitsForSale[hypercertContract][fractionID] + unitsForSale + ) { + revert InvalidOffer("Insufficient units"); + } + + // Validate min/max units per trade + if (maxUnitsPerTrade > unitsForSale || minUnitsPerTrade > maxUnitsPerTrade) { + revert InvalidOffer("Min/Max units"); + } + + // If sale is for a fraction, the units must be a multiple of the minimum units per trade + if (minUnitsPerTrade == maxUnitsPerTrade && unitsForSale % minUnitsPerTrade != 0) { + revert InvalidOffer("Units indivisible by fractions"); + } + + // Minimum amount per unit must be greater than 0 + if (acceptedTokens.length == 0 || acceptedTokens[0].minimumAmountPerUnit == 0) { + revert InvalidOffer("No accepted tokens"); + } + + // for now only accept the native token, ZERO_ADDRESS + if (acceptedTokens.length != 1 || acceptedTokens[0].token != address(0)) { + revert InvalidOffer("Only zero token"); + } + } + + /** + * @dev Validates an existing offer for a buy operation. + * @param offer The offer to validate. + * @param unitAmountsToBuy The number of units to buy. + * @param buyToken The address of the token used for payment. + * @param tokenAmountPerUnit The amount of tokens to pay per unit. + * @notice This internal function validates an existing offer for a buy operation. The function verifies that the offer exists, + * is open, and has enough units available for sale. The function also verifies that the specified token is accepted for payment + * and that the buyer has provided enough payment in the specified token. + */ + function _validateBuyOffer( + Offer memory offer, + uint256 unitAmountsToBuy, + address buyToken, + uint256 tokenAmountPerUnit + ) internal { + if (offer.status != OfferStatus.Open || offer.offerType != OfferType.Units) { + revert InvalidOffer("Wrong status"); + } + + if ( + offer.unitsAvailable < unitAmountsToBuy || + offer.minUnitsPerTrade > unitAmountsToBuy || + offer.maxUnitsPerTrade < unitAmountsToBuy + ) revert InvalidOffer("Min/Max units"); + + // Check for sufficient funds; currently only native token + if (buyToken != address(0) || (unitAmountsToBuy * tokenAmountPerUnit) > msg.value) { + revert InvalidOffer("Wrong token/value"); + } + + // TODO check on overpayment??? + + //TODO optimize array search or use mapping + // Check for accepted tokens + uint256 len = offer.acceptedTokens.length; + bool tokenAccepted = false; + for (uint256 i; i < len; ) { + if (!tokenAccepted) { + tokenAccepted = offer.acceptedTokens[i].token == buyToken; + } + + if ( + offer.acceptedTokens[i].token == buyToken && + offer.acceptedTokens[i].minimumAmountPerUnit > tokenAmountPerUnit + ) { + revert InvalidOffer("Wrong token/value"); + } + + unchecked { + ++i; + } + } + if (!tokenAccepted) revert InvalidOffer("Wrong token/value"); + } + + /// INTERNAL + + /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol } + function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { + // solhint-disable-previous-line no-empty-blocks + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + * Assuming 30 available slots (slots cost space, cost gas) + * 1. totalUnitsForSale + * 2. offers + * 3. _offerCounter + */ + uint256[27] private __gap; +} diff --git a/contracts/src/SemiFungible1155.sol b/contracts/src/SemiFungible1155.sol index 7239109d..fba07983 100644 --- a/contracts/src/SemiFungible1155.sol +++ b/contracts/src/SemiFungible1155.sol @@ -324,7 +324,7 @@ contract SemiFungible1155 is } } - _beforeUnitTransfer(_msgSender(), _account, fromIDs, toIDs, values, ""); + _beforeUnitTransfer(_msgSender(), owners[_tokenID], fromIDs, toIDs, values, ""); for (uint256 i; i < len; ) { valueLeft -= values[i]; diff --git a/contracts/src/interfaces/IHypercertTrader.sol b/contracts/src/interfaces/IHypercertTrader.sol new file mode 100644 index 00000000..a8ee04f6 --- /dev/null +++ b/contracts/src/interfaces/IHypercertTrader.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +/// @title Interface for hypercert token trading +/// @author bitbeckers +/// @notice This interface declares the required functionality to interact with the hypercert marketplace +interface IHypercertTrader { + /** + * @dev Struct for an offer to sell Hypercert tokens. + */ + struct Offer { + address offerer; + address hypercertContract; + uint256 fractionID; + uint256 unitsAvailable; + uint256 minUnitsPerTrade; + uint256 maxUnitsPerTrade; + OfferType offerType; + OfferStatus status; + AcceptedToken[] acceptedTokens; + } + + /** + * @dev Enum for the type of offer (Units or Fraction). + */ + enum OfferType { + Units, + Fraction + } + + /** + * @dev Enum for the status of an offer (Open, Fulfilled, or Cancelled). + */ + enum OfferStatus { + Open, + Fulfilled, + Cancelled + } + + /** + * @dev Struct for a token that is accepted for payment. + */ + struct AcceptedToken { + address token; + uint256 minimumAmountPerUnit; + } + + event OfferCreated( + address indexed offerer, + address indexed hypercertContract, + uint256 indexed fractionID, + uint256 offerID + ); + + event Trade( + address indexed seller, + address indexed buyer, + address indexed hypercertContract, + uint256 fractionID, + uint256 unitsBought, + address buyToken, + uint256 tokenAmountPerUnit, + uint256 offerID + ); + + event OfferCancelled( + address indexed creator, + address indexed hypercertContract, + uint256 indexed fractionID, + uint256 offerID + ); + + /** + * @dev Creates a new offer to sell Hypercert tokens. + * @param hypercertContract The address of the Hypercert token contract. + * @param fractionID The ID of the fraction to sell. + * @param units The number of units available for sale. + * @param minUnitsPerTrade The minimum number of units that can be bought in a single trade. + * @param maxUnitsPerTrade The maximum number of units that can be bought in a single trade. + * @param acceptedTokens The list of tokens that are accepted for payment. + */ + function createOffer( + address hypercertContract, + uint256 fractionID, + uint256 units, + uint256 minUnitsPerTrade, + uint256 maxUnitsPerTrade, + AcceptedToken[] memory acceptedTokens + ) external payable returns (uint256 offerID); + + /** + * @dev Buys Hypercert tokens from an existing offer. + * @param recipient The address that will receive the Hypercert tokens. + * @param offerID The ID of the offer to buy from. + * @param unitAmount The number of units to buy. + * @param buyToken The address of the token used for payment. + * @param tokenAmountPerUnit The amount of tokens to pay per unit. + */ + function buyUnits( + address recipient, + uint256 offerID, + uint256 unitAmount, + address buyToken, + uint256 tokenAmountPerUnit + ) external payable; + + /** + * @dev Buys Hypercert tokens from multiple existing offers in a single transaction. + * @param recipient The address that will receive the Hypercert tokens. + * @param offerIDs The list of IDs of the offers to buy from. + * @param unitAmounts The list of numbers of units to buy for each offer. + * @param buyTokens The list of addresses of the tokens used for payment for each offer. + * @param tokenAmountsPerUnit The list of amounts of tokens to pay per unit for each offer. + */ + function batchBuyUnits( + address recipient, + uint256[] calldata offerIDs, + uint256[] calldata unitAmounts, + address[] calldata buyTokens, + uint256[] calldata tokenAmountsPerUnit + ) external payable; + + /** + * @dev Cancels an existing offer. + * @param offerID The ID of the offer to cancel. + */ + function cancelOffer(uint256 offerID) external; +} diff --git a/contracts/tasks/deploy.ts b/contracts/tasks/deploy.ts index 9015db74..75a87639 100644 --- a/contracts/tasks/deploy.ts +++ b/contracts/tasks/deploy.ts @@ -1,7 +1,7 @@ import { task } from "hardhat/config"; import { writeFile } from "node:fs/promises"; -task("deploy", "Deploy contracts and verify") +task("deploy-minter", "Deploy contracts and verify") .addOptionalParam("output", "write the details of the deployment to this file if this is set") .setAction(async ({ output }, { ethers, upgrades }) => { const HypercertMinter = await ethers.getContractFactory("HypercertMinter"); @@ -45,3 +45,48 @@ task("deploy", "Deploy contracts and verify") } } }); + +task("deploy-trader", "Deploy HypercertTrader and verify") + .addOptionalParam("output", "write the details of the deployment to this file if this is set") + .setAction(async ({ output }, { ethers, upgrades }) => { + const HypercertTrader = await ethers.getContractFactory("HypercertTrader"); + const hypercertTrader = await upgrades.deployProxy(HypercertTrader, { + kind: "uups", + unsafeAllow: ["constructor"], + }); + const contract = await hypercertTrader.deployed(); + console.log(`hypercertTrader is deployed to proxy address: ${hypercertTrader.address}`); + + // If the `deploymentFile` option is set then write the deployed address to + // a json object on disk. This is intended to be deliberate with how we + // output the contract address and other contract information. + if (output) { + const txReceipt = await contract.provider.getTransactionReceipt(hypercertTrader.deployTransaction.hash); + await writeFile( + output, + JSON.stringify({ + address: hypercertTrader.address, + blockNumber: txReceipt.blockNumber, + }), + "utf-8", + ); + } + + if (hre.network.name !== "hardhat" && hre.network.name !== "localhost") { + try { + const code = await hypercertTrader.instance?.provider.getCode(hypercertTrader.address); + if (code === "0x") { + console.log(`${hypercertTrader.name} contract deployment has not completed. waiting to verify...`); + await hypercertTrader.instance?.deployed(); + } + await hre.run("verify:verify", { + address: hypercertTrader.address, + }); + } catch ({ message }) { + if ((message as string).includes("Reason: Already Verified")) { + console.log("Reason: Already Verified"); + } + console.error(message); + } + } + }); diff --git a/contracts/tasks/transfer-owner.ts b/contracts/tasks/transfer-owner.ts index 03421503..20c80c66 100644 --- a/contracts/tasks/transfer-owner.ts +++ b/contracts/tasks/transfer-owner.ts @@ -1,13 +1,13 @@ import { task } from "hardhat/config"; -task("transfer-owner", "Transfer ownership of ProxyAdmin contract") +task("transfer-owner-minter", "Transfer ownership of ProxyAdmin contract HypercertMinter") .addParam("proxy", "Proxy contract address") .addParam("owner", "Address of new owner") .setAction(async ({ proxy, owner }, { ethers, upgrades }) => { const HypercertMinter = await ethers.getContractFactory("HypercertMinter"); const hypercertMinter = await HypercertMinter.attach(proxy); - console.log('Transferring ownership of proxy contract...'); + console.log("Transferring ownership of proxy contract..."); const transferTransaction = await hypercertMinter.transferOwnership(owner); console.log("Sent transfer transaction, waiting for transaction receipt..."); @@ -27,5 +27,33 @@ task("transfer-owner", "Transfer ownership of ProxyAdmin contract") } console.log(`Successfully verified that the HypercertMinter contract was transferred. Contract address: ${proxy}`); - } -); + }); + +task("transfer-owner-trader", "Transfer ownership of ProxyAdmin contract HypercertTrader") + .addParam("proxy", "Proxy contract address") + .addParam("owner", "Address of new owner") + .setAction(async ({ proxy, owner }, { ethers, upgrades }) => { + const HypercertTrader = await ethers.getContractFactory("HypercertTrader"); + const hypercertTrader = await HypercertTrader.attach(proxy); + + console.log("Transferring ownership of proxy contract..."); + const transferTransaction = await hypercertTrader.transferOwnership(owner); + console.log("Sent transfer transaction, waiting for transaction receipt..."); + + const transferReceipt = await transferTransaction.wait(); + if (transferReceipt == null || transferReceipt.status == 0) { + console.error(transferReceipt); + console.error("Transaction failed, failed to transfer contract"); + return; + } + + console.log(`Transaction succeeded. Transaction Hash: ${transferReceipt.transactionHash}`); + + const newOwner = await hypercertTrader.owner(); + if (newOwner !== owner) { + console.error(`Verification failed: the contract is owned by ${newOwner}.`); + return; + } + + console.log(`Successfully verified that the HypercertTrader contract was transferred. Contract address: ${proxy}`); + }); diff --git a/contracts/tasks/upgrade.ts b/contracts/tasks/upgrade.ts index a4cd7a5b..6fc6a6c4 100644 --- a/contracts/tasks/upgrade.ts +++ b/contracts/tasks/upgrade.ts @@ -3,7 +3,7 @@ import { task } from "hardhat/config"; /** * Used to upgrade a contract directly via local keys */ -task("upgrade", "Upgrade implementation contract and verify") +task("upgrade-minter", "Upgrade implementation contract of Minter and verify") .addParam("proxy", "Provider proxy address") .setAction(async ({ proxy }, { ethers, upgrades }) => { const HypercertMinter = await ethers.getContractFactory("HypercertMinter"); @@ -38,19 +38,76 @@ task("upgrade", "Upgrade implementation contract and verify") }); /** - * Used to propose a multi-sig upgrade via OpenZeppelin Defender + * Used to upgrade a contract directly via local keys + */ +task("upgrade-trader", "Upgrade implementation contract of Trader and verify") + .addParam("proxy", "Provider proxy address") + .setAction(async ({ proxy }, { ethers, upgrades }) => { + const HypercertTrader = await ethers.getContractFactory("HypercertTrader"); + + // Validate (redundant?) + console.log("Validating upgrade.."); + await upgrades.validateUpgrade(proxy, HypercertTrader).then(() => console.log("Valid upgrade. Deploying..")); + + // Upgrade + const hypercertTraderUpgrade = await upgrades.upgradeProxy(proxy, HypercertTrader, { + kind: "uups", + unsafeAllow: ["constructor"], + }); + await hypercertTraderUpgrade.deployed(); + console.log(`HypercertTrader at proxy address ${hypercertTraderUpgrade.address} was upgraded`); + + try { + const code = await hypercertTraderUpgrade.instance?.provider.getCode(hypercertTraderUpgrade.address); + if (code === "0x") { + console.log(`${hypercertTraderUpgrade.name} contract upgrade has not completed. waiting to verify...`); + await hypercertTraderUpgrade.instance?.deployed(); + } + await hre.run("verify:verify", { + address: hypercertTraderUpgrade.address, + }); + } catch ({ message }) { + if ((message as string).includes("Reason: Already Verified")) { + console.log("Reason: Already Verified"); + } + console.error(message); + } + }); + +/** + * Used to propose a multi-sig upgrade via OpenZeppelin Defender for HypercertMinter */ -task("propose-upgrade", "Propose an upgrade to OpenZeppelin Defender") +task("propose-upgrade-minter", "Propose an upgrade to OpenZeppelin Defender") .addParam("proxy", "Proxy contract address") .addParam("multisig", "Owner multisig address") - .setAction(async ({ proxy, multisig }, { ethers, upgrades }) => { + .addOptionalParam("description", "Description of upgrade") + .setAction(async ({ proxy, multisig, description = "Upgrade Minter contract" }, { ethers, upgrades }) => { const HypercertMinter = await ethers.getContractFactory("HypercertMinter"); console.log(`Proposing upgrade to multisig ${multisig} as address ${proxy}`); const proposal = await defender.proposeUpgrade(proxy, HypercertMinter, { - description: "Add batch burning methods", + description, + multisig, + multisigType: "Gnosis Safe", + title: "Upgrade Minter contract", + }); + console.log("Upgrade proposal created at: ", proposal.url); + }); + +/** + * Used to propose a multi-sig upgrade via OpenZeppelin Defender for HypercertTrader + */ +task("propose-upgrade-trader", "Propose an upgrade to OpenZeppelin Defender") + .addParam("proxy", "Proxy contract address") + .addParam("multisig", "Owner multisig address") + .addOptionalParam("description", "Description of upgrade") + .setAction(async ({ proxy, multisig, description = "Upgrade Trader contract" }, { ethers, upgrades }) => { + const HypercertTrader = await ethers.getContractFactory("HypercertTrader"); + console.log(`Proposing upgrade to multisig ${multisig} as address ${proxy}`); + const proposal = await defender.proposeUpgrade(proxy, HypercertTrader, { + description, multisig, multisigType: "Gnosis Safe", - title: "Add batch burn", + title: "Upgrade Trader contract", }); console.log("Upgrade proposal created at: ", proposal.url); }); diff --git a/contracts/test/foundry/HypercertTrader.admin.t.sol b/contracts/test/foundry/HypercertTrader.admin.t.sol new file mode 100644 index 00000000..4cf645c6 --- /dev/null +++ b/contracts/test/foundry/HypercertTrader.admin.t.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.16; + +import { HypercertTrader } from "../../src/HypercertTrader.sol"; +import { HypercertMinter } from "../../src/HypercertMinter.sol"; +import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { PRBTest } from "prb-test/PRBTest.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { StdUtils } from "forge-std/StdUtils.sol"; + +interface IHypercertMinter { + function ownerOf(uint256 id) external view returns (address); + + function unitsOf(uint256 id) external view returns (uint256); +} + +contract HypercertTraderHelper is HypercertTrader { + error NotAllowed(); + error InvalidOffer(string); + + // TODO - Use UUPS pattern for contracts and getting owner + address internal alice = address(1); + address internal bob = address(2); + + HypercertMinter public hypercertMinter = new HypercertMinter(); + + function getOffer(uint256 key) external view returns (Offer memory) { + return offers[key]; + } + + function getOfferCount() external view returns (uint256) { + return _offerCounter; + } +} + +contract HypercertTraderAdminTest is HypercertTraderHelper, PRBTest, StdCheats, StdUtils { + HypercertTraderHelper internal hypercertTrader; + + function setUp() public { + hypercertTrader = new HypercertTraderHelper(); + } + + function testPausability() public { + AcceptedToken[] memory acceptedTokens = new AcceptedToken[](1); + acceptedTokens[0] = AcceptedToken(address(0), 1); + + // Contract is not paused + assertEq(hypercertTrader.paused(), false); + + // Bob can't pause the contracts + vm.startPrank(bob); + vm.expectRevert("Ownable: caller is not the owner"); + hypercertTrader.pause(); + + // Owner can pause the contract + vm.startPrank(owner()); + vm.expectEmit(true, false, false, false); + emit Paused(owner()); + hypercertTrader.pause(); + + // All functions are paused + vm.expectRevert("Pausable: paused"); + hypercertTrader.createOffer(address(hypercertMinter), 1, 1, 1, 1, acceptedTokens); + + vm.expectRevert("Pausable: paused"); + hypercertTrader.cancelOffer(1); + + vm.expectRevert("Pausable: paused"); + hypercertTrader.buyUnits(alice, 1, 1, address(0), 1); + + // Bob can't unpause the contract + vm.startPrank(bob); + vm.expectRevert("Ownable: caller is not the owner"); + hypercertTrader.unpause(); + + // Owner can unpause the contract + vm.startPrank(owner()); + vm.expectEmit(true, false, false, false); + emit Unpaused(owner()); + hypercertTrader.unpause(); + + // All functions are unpaused + vm.expectRevert(NotAllowed.selector); + hypercertTrader.createOffer(address(hypercertMinter), 1, 1, 1, 1, acceptedTokens); + + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "No contract address found")); + hypercertTrader.cancelOffer(1); + + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Min/Max units")); + hypercertTrader.buyUnits(alice, 1, 1, address(0), 1); + } +} diff --git a/contracts/test/foundry/HypercertTrader.offers.t.sol b/contracts/test/foundry/HypercertTrader.offers.t.sol new file mode 100644 index 00000000..71c09133 --- /dev/null +++ b/contracts/test/foundry/HypercertTrader.offers.t.sol @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.16; + +import { HypercertTrader } from "../../src/HypercertTrader.sol"; +import { HypercertMinter } from "../../src/HypercertMinter.sol"; +import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { PRBTest } from "prb-test/PRBTest.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { StdUtils } from "forge-std/StdUtils.sol"; + +interface IHypercertMinter { + function ownerOf(uint256 id) external view returns (address); + + function unitsOf(uint256 id) external view returns (uint256); +} + +contract HypercertTraderHelper is HypercertTrader { + error NotAllowed(); + error InvalidOffer(string); + + address alice = address(1); + address bob = address(2); + + HypercertMinter public hypercertMinter = new HypercertMinter(); + + function getOffer(uint256 key) external view returns (Offer memory) { + return offers[key]; + } + + function getOfferCount() external view returns (uint256) { + return _offerCounter; + } + + function exposedValidateBuyOffer( + address offerer, + address hypercertContract, + uint256 fractionID, + uint256 units, + uint256 minUnitsPerTrade, + uint256 maxUnitsPerTrade, + AcceptedToken[] memory acceptedTokens + ) external { + _validateOffer( + offerer, + hypercertContract, + fractionID, + units, + minUnitsPerTrade, + maxUnitsPerTrade, + acceptedTokens + ); + } +} + +contract HypercertTraderCreateOfferTest is HypercertTraderHelper, PRBTest, StdCheats, StdUtils { + HypercertTraderHelper internal hypercertTrader; + + function setUp() public { + hypercertTrader = new HypercertTraderHelper(); + } + + function testCreateOfferWithAllowance() public { + // Setup + vm.startPrank(alice); + hypercertMinter.mintClaim(alice, 10000, "ipfs://test", IHypercertToken.TransferRestrictions.FromCreatorOnly); + + uint256 baseID = 1 << 128; + uint256 tokenIndex = 1; + uint256 tokenID = baseID + tokenIndex; + + AcceptedToken[] memory acceptedTokens = new AcceptedToken[](1); + acceptedTokens[0] = AcceptedToken(address(0), 1); + + // Reverts when Trader contract is not approved + vm.expectRevert(NotAllowed.selector); + hypercertTrader.createOffer(address(hypercertMinter), tokenID, 1, 1, 1, acceptedTokens); + + // Set approval + hypercertMinter.setApprovalForAll(address(hypercertTrader), true); + + // Alice creates an offer + vm.expectEmit(true, true, true, true); + emit OfferCreated(alice, address(hypercertMinter), tokenID, 0); + uint256 offerID = hypercertTrader.createOffer(address(hypercertMinter), tokenID, 1, 1, 1, acceptedTokens); + + assertEq(hypercertTrader.getOfferCount(), 1); + assertEq(hypercertTrader.totalUnitsForSale(address(hypercertMinter), tokenID), 1); + + // Offer is created + Offer memory offer = hypercertTrader.getOffer(offerID); + assertEq(offer.fractionID, tokenID); + assertEq(offer.unitsAvailable, 1); + assertEq(offer.minUnitsPerTrade, 1); + assertEq(offer.maxUnitsPerTrade, 1); + assertEq(offer.acceptedTokens.length, 1); + assertEq(uint256(offer.status), uint256(OfferStatus.Open)); + } + + function testCannotCreateOfferForNonExistentToken() public { + hypercertMinter.setApprovalForAll(address(hypercertTrader), true); + + AcceptedToken[] memory acceptedTokens = new AcceptedToken[](1); + acceptedTokens[0] = AcceptedToken(address(0), 1); + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Not owner")); + hypercertTrader.createOffer(address(hypercertMinter), 1, 1, 1, 1, acceptedTokens); + } + + function testCanCancelOffer() public { + // Setup + vm.startPrank(alice); + hypercertMinter.mintClaim(alice, 10000, "ipfs://test", IHypercertToken.TransferRestrictions.FromCreatorOnly); + + uint256 baseID = 1 << 128; + uint256 tokenIndex = 1; + uint256 tokenID = baseID + tokenIndex; + + AcceptedToken[] memory acceptedTokens = new AcceptedToken[](1); + acceptedTokens[0] = AcceptedToken(address(0), 1); + + hypercertMinter.setApprovalForAll(address(hypercertTrader), true); + + // Alice creates an offer + vm.expectEmit(true, true, true, true); + emit OfferCreated(alice, address(hypercertMinter), tokenID, 0); + uint256 offerID = hypercertTrader.createOffer(address(hypercertMinter), tokenID, 1, 1, 1, acceptedTokens); + + Offer memory offer = hypercertTrader.getOffer(offerID); + assertEq(offer.fractionID, tokenID); + assertEq(uint256(offer.status), uint256(OfferStatus.Open)); + assertEq(hypercertTrader.totalUnitsForSale(address(hypercertMinter), tokenID), 1); + + // Bob tries to cancel the offer and is rejected + changePrank(bob); + vm.expectRevert(NotAllowed.selector); + hypercertTrader.cancelOffer(offerID); + + // Alice cancels the offer + changePrank(alice); + vm.expectEmit(true, true, true, true); + emit OfferCancelled(alice, address(hypercertMinter), tokenID, 0); + hypercertTrader.cancelOffer(offerID); + + // The offer is cancelled + Offer memory updatedOffer = hypercertTrader.getOffer(offerID); + assertEq(uint256(updatedOffer.status), uint256(OfferStatus.Cancelled)); + assertEq(hypercertTrader.totalUnitsForSale(address(hypercertMinter), tokenID), 0); + } + + function testOfferValidations() public { + vm.mockCall( + address(hypercertMinter), + abi.encodeWithSelector(IHypercertMinter.ownerOf.selector, 42), + abi.encode(alice) + ); + vm.mockCall( + address(hypercertMinter), + abi.encodeWithSelector(IHypercertMinter.unitsOf.selector, 42), + abi.encode(10) + ); + AcceptedToken[] memory acceptedToken = new AcceptedToken[](1); + acceptedToken[0] = AcceptedToken(address(0), 1); + + // Fail on 0 units + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Insufficient units")); + hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 0, 1, 1, acceptedToken); + + // Fail on more units than in the fraction + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Insufficient units")); + hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 11, 1, 1, acceptedToken); + + // Fail on higher than max units + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Min/Max units")); + hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 1, 999, acceptedToken); + + // Fail on lower than min units + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Min/Max units")); + hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 999, 1, acceptedToken); + + // Fail when min-max are equal but the units are not divisible by the min-max value + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Units indivisible by fractions")); + hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 7, 2, 2, acceptedToken); + + // Fail when there's no accepted token + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "No accepted tokens")); + hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 1, 1, new AcceptedToken[](0)); + + // Fail when the accepted token has a minimum amount per unit of 0 + AcceptedToken[] memory invalidAcceptedToken = new AcceptedToken[](1); + invalidAcceptedToken[0] = AcceptedToken(address(0), 0); + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "No accepted tokens")); + hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 1, 1, invalidAcceptedToken); + + // Fail when accepted token that's not the native token + AcceptedToken[] memory nonNativeAcceptedToken = new AcceptedToken[](1); + nonNativeAcceptedToken[0] = AcceptedToken(address(1), 1); + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Only zero token")); + hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 1, 1, nonNativeAcceptedToken); + + // Fail on insufficient units in fraction + vm.mockCall( + address(hypercertMinter), + abi.encodeWithSelector(IHypercertMinter.unitsOf.selector, 42), + abi.encode(1) + ); + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Insufficient units")); + hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 1, 1, new AcceptedToken[](0)); + } +} diff --git a/contracts/test/foundry/HypercertTrader.sales.t.sol b/contracts/test/foundry/HypercertTrader.sales.t.sol new file mode 100644 index 00000000..c086fdd4 --- /dev/null +++ b/contracts/test/foundry/HypercertTrader.sales.t.sol @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.16; + +import { HypercertTrader } from "../../src/HypercertTrader.sol"; +import { HypercertMinter } from "../../src/HypercertMinter.sol"; +import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { PRBTest } from "prb-test/PRBTest.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { StdUtils } from "forge-std/StdUtils.sol"; + +interface IHypercertMinter { + function ownerOf(uint256 id) external view returns (address); + + function unitsOf(uint256 id) external view returns (uint256); +} + +contract HypercertTraderHelper is HypercertTrader, PRBTest, StdCheats, StdUtils { + error NotAllowed(); + error InvalidOffer(string); + error InvalidBuy(string); + + address alice = makeAddr("alice"); + address bob = makeAddr("bob"); + + HypercertMinter public hypercertMinter = new HypercertMinter(); + + function getOffer(uint256 key) external view returns (Offer memory) { + return offers[key]; + } + + function getOfferCount() external view returns (uint256) { + return _offerCounter; + } + + function exposedValidateBuyOffer( + Offer memory offer, + uint256 unitAmount, + address buyToken, + uint256 tokenAmountPerUnit + ) external payable { + _validateBuyOffer(offer, unitAmount, buyToken, tokenAmountPerUnit); + } + + function createDefaultOffer(bool full) external returns (uint256 offerID, uint256 fractionID) { + vm.startPrank(alice); + hypercertMinter.mintClaim(alice, 10000, "ipfs://test", IHypercertToken.TransferRestrictions.FromCreatorOnly); + + uint256 baseID = 1 << 128; + uint256 tokenIndex = 1; + fractionID = baseID + tokenIndex; + + AcceptedToken[] memory acceptedTokens = new AcceptedToken[](1); + acceptedTokens[0] = AcceptedToken(address(0), 3); + + hypercertMinter.setApprovalForAll(address(this), true); + + vm.expectEmit(true, true, true, true); + emit OfferCreated(alice, address(hypercertMinter), fractionID, 0); + if (full) { + offerID = this.createOffer(address(hypercertMinter), fractionID, 10000, 10, 10000, acceptedTokens); + } else { + offerID = this.createOffer(address(hypercertMinter), fractionID, 1000, 10, 1000, acceptedTokens); + } + } +} + +//TODO cleanup inheritance +contract HypercertTraderBuyOfferTest is HypercertTraderHelper { + HypercertTraderHelper internal hypercertTrader; + + function setUp() public { + hypercertTrader = new HypercertTraderHelper(); + } + + function testBuyOfferFullBid() public { + // Alice has no balance + assertEq(alice.balance, 0); + + // Alice creates a offer + (uint256 offerID, uint256 fractionID) = hypercertTrader.createDefaultOffer(false); + assertEq(hypercertTrader.getOfferCount(), 1); + assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 1000); + + // Bob buys the full offer + startHoax(bob, 10 ether); + vm.expectEmit(true, true, true, true); + emit Trade(alice, bob, address(hypercertTrader.hypercertMinter()), fractionID, 1000, address(0), 10, offerID); + hypercertTrader.buyUnits{ value: 10000 }(bob, offerID, 1000, address(0), 10); + + // Bob owns the new fraction + assertEq(hypercertTrader.hypercertMinter().ownerOf(fractionID + 1), bob); + + // Alice still owns the old fraction and the units that weren't sold + assertEq(hypercertTrader.hypercertMinter().ownerOf(fractionID), alice); + assertEq(hypercertTrader.hypercertMinter().unitsOf(fractionID), 9000); + + // The offer is closed + Offer memory offer = hypercertTrader.getOffer(offerID); + assertEq(uint256(offer.status), uint256(OfferStatus.Fulfilled)); + assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 0); + + // And bob can't buy any more of the offer + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong status")); + hypercertTrader.buyUnits{ value: 10000 }(bob, offerID, 10, address(0), 10); + + // Alice received the funds + assertEq(alice.balance, 10000); + } + + function testBuyOfferFullFraction() public { + // Alice has no balance + assertEq(alice.balance, 0); + + // Alice creates a offer + (uint256 offerID, uint256 fractionID) = hypercertTrader.createDefaultOffer(true); + assertEq(hypercertTrader.getOfferCount(), 1); + assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 10000); + + // Bob buys the full offer for the full token + startHoax(bob, 10 ether); + vm.expectEmit(true, true, true, true); + emit Trade(alice, bob, address(hypercertTrader.hypercertMinter()), fractionID, 10000, address(0), 10, offerID); + hypercertTrader.buyUnits{ value: 100000 }(bob, offerID, 10000, address(0), 10); + + // Bob bought the full fraction and owns it + assertEq(hypercertTrader.hypercertMinter().ownerOf(fractionID), bob); + + // No new fraction was minted + assertEq(hypercertTrader.hypercertMinter().unitsOf(fractionID + 1), 0); + + // The offer is closed + Offer memory offer = hypercertTrader.getOffer(offerID); + assertEq(uint256(offer.status), uint256(OfferStatus.Fulfilled)); + assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 0); + + // And bob can't buy any more of the offer + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong status")); + hypercertTrader.buyUnits{ value: 10000 }(bob, offerID, 1, address(0), 10); + + // Alice received the funds + assertEq(alice.balance, 100000); + } + + function testBuyOfferPartial() public { + // Alice creates a offer + (uint256 offerID, uint256 fractionID) = hypercertTrader.createDefaultOffer(false); + assertEq(hypercertTrader.getOfferCount(), 1); + assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 1000); + + // Bob buys part of the offer + startHoax(bob, 10 ether); + vm.expectEmit(true, true, true, true); + emit Trade(alice, bob, address(hypercertTrader.hypercertMinter()), fractionID, 500, address(0), 10, offerID); + hypercertTrader.buyUnits{ value: 5000 }(bob, offerID, 500, address(0), 10); + + // Bob owns the new fraction worth 500 units + assertEq(hypercertTrader.hypercertMinter().ownerOf(fractionID + 1), bob); + assertEq(hypercertTrader.hypercertMinter().unitsOf(fractionID + 1), 500); + + // The offer is still open + Offer memory offer = hypercertTrader.getOffer(offerID); + assertEq(uint256(offer.status), uint256(OfferStatus.Open)); + assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 500); + + // And bob can buy the rest of the offer + vm.expectEmit(true, true, true, true); + emit Trade(alice, bob, address(hypercertTrader.hypercertMinter()), fractionID, 500, address(0), 10, offerID); + hypercertTrader.buyUnits{ value: 5000 }(bob, offerID, 500, address(0), 10); + + // Bob owns the new fraction worth 500 units + assertEq(hypercertTrader.hypercertMinter().ownerOf(fractionID + 2), bob); + assertEq(hypercertTrader.hypercertMinter().unitsOf(fractionID + 2), 500); + + // The offer is closed + offer = hypercertTrader.getOffer(offerID); + assertEq(uint256(offer.status), uint256(OfferStatus.Fulfilled)); + assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 0); + } + + function testBuyOfferFailsLowBid() public { + // Alice creates a offer + (uint256 offerID, ) = hypercertTrader.createDefaultOffer(false); + assertEq(hypercertTrader.getOfferCount(), 1); + + // Bob tries to buy the offer with a low bid (tokenAmountPerUnit lower than min asking price) + startHoax(bob, 10 ether); + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong token/value")); + hypercertTrader.buyUnits{ value: 5000 }(bob, offerID, 500, address(0), 2); + + // Bob tries to buy the offer with a low bid (msg.value too low) + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong token/value")); + hypercertTrader.buyUnits{ value: 4999 }(bob, offerID, 500, address(0), 10); + + // The offer is still open + Offer memory offer = hypercertTrader.getOffer(offerID); + assertEq(uint256(offer.status), uint256(OfferStatus.Open)); + } + + function testBuyOfferValidations() public { + Offer memory offer = Offer({ + offerer: alice, + hypercertContract: address(hypercertMinter), + fractionID: 42, + unitsAvailable: 10, + minUnitsPerTrade: 2, + maxUnitsPerTrade: 5, + status: OfferStatus.Open, + offerType: OfferType.Units, + acceptedTokens: new AcceptedToken[](1) + }); + + vm.mockCall( + address(hypercertMinter), + abi.encodeWithSelector(IHypercertMinter.ownerOf.selector, 42), + abi.encode(alice) + ); + + offer.acceptedTokens[0] = AcceptedToken(address(0), 2); + + // Expect revert on mix/maxUnitsPerTrade + // Bid too low + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong token/value")); + this.exposedValidateBuyOffer(offer, 3, address(0), 1); + + // Units bought too low + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Min/Max units")); + this.exposedValidateBuyOffer(offer, 1, address(0), 3); + + // Too high + // Units bought too high + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Min/Max units")); + this.exposedValidateBuyOffer(offer, 11, address(0), 3); + + // Within range but no value + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong token/value")); + this.exposedValidateBuyOffer(offer, 3, address(0), 3); + + this.exposedValidateBuyOffer{ value: 10 }(offer, 3, address(0), 3); + + // Expect revert on wrong token + offer.acceptedTokens[0] = AcceptedToken(address(1337), 2); + vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong token/value")); + this.exposedValidateBuyOffer(offer, 3, address(1), 1); + } +} diff --git a/contracts/test/foundry/SemiFungible1155.transfers.t.sol b/contracts/test/foundry/SemiFungible1155.transfers.t.sol index 482e717b..821ea745 100644 --- a/contracts/test/foundry/SemiFungible1155.transfers.t.sol +++ b/contracts/test/foundry/SemiFungible1155.transfers.t.sol @@ -20,12 +20,11 @@ contract SemiFungible1155TransferTest is PRBTest, StdCheats, StdUtils { _uri = "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi"; alice = address(1); bob = address(2); - hoax(alice, 100 ether); + startHoax(alice, 100 ether); } // UNHAPPY PATHS function testFailTransferTypeIDToken() public { - vm.startPrank(alice); semiFungible.mintValue(alice, 10000, _uri); //NotApprovedOrOWner, since no owner @@ -33,7 +32,6 @@ contract SemiFungible1155TransferTest is PRBTest, StdCheats, StdUtils { } function testFailTransferNonExistingFractionToken() public { - vm.startPrank(alice); semiFungible.mintValue(alice, 10000, _uri); //NotApprovedOrOWner, since no owner @@ -41,8 +39,6 @@ contract SemiFungible1155TransferTest is PRBTest, StdCheats, StdUtils { } function testTransferNonExistingTokenWithValue() public { - vm.startPrank(alice); - uint256 baseID = 1 << 128; uint128 tokenID = 1; @@ -51,8 +47,6 @@ contract SemiFungible1155TransferTest is PRBTest, StdCheats, StdUtils { } function testTransferNonExistingFungibleTokenTokenNoValue() public { - vm.startPrank(alice); - uint256 baseID = 1 << 128; uint128 tokenID = 1; @@ -66,8 +60,6 @@ contract SemiFungible1155TransferTest is PRBTest, StdCheats, StdUtils { uint256 baseID = 1 << 128; uint128 tokenID = 1; - startHoax(alice, 100 ether); - semiFungible.mintValue(alice, 10000, _uri); assertEq(semiFungible.balanceOf(alice, baseID), 0); diff --git a/docs/docs/developer/api/contracts/HypercertTrader.md b/docs/docs/developer/api/contracts/HypercertTrader.md new file mode 100644 index 00000000..4a5c9b4e --- /dev/null +++ b/docs/docs/developer/api/contracts/HypercertTrader.md @@ -0,0 +1,416 @@ +# HypercertTrader + +_bitbeckers_ + +> Contract for managing hypercert trades + +Implementation of the HypercertTrader Interface + +## Methods + +### batchBuyUnits + +```solidity +function batchBuyUnits(address recipient, uint256[] offerIDs, uint256[] unitAmounts, address[] buyTokens, uint256[] tokenAmountsPerUnit) external payable +``` + +This function allows a user to buy Hypercert tokens from multiple existing offers in a single transaction. The function takes in several arrays of parameters, including the IDs of the offers to buy from, the number of units to buy for each offer, the tokens used for payment for each offer, and the amounts of tokens to pay per unit for each offer. The function then executes the trades and transfers the Hypercert tokens to the specified recipient. + +_Buys Hypercert tokens from multiple existing offers in a single transaction._ + +#### Parameters + +| Name | Type | Description | +| ------------------- | --------- | -------------------------------------------------------------------- | +| recipient | address | The address that will receive the Hypercert tokens. | +| offerIDs | uint256[] | The list of IDs of the offers to buy from. | +| unitAmounts | uint256[] | The list of numbers of units to buy for each offer. | +| buyTokens | address[] | The list of addresses of the tokens used for payment for each offer. | +| tokenAmountsPerUnit | uint256[] | The list of amounts of tokens to pay per unit for each offer. | + +### buyUnits + +```solidity +function buyUnits(address recipient, uint256 offerID, uint256 unitAmount, address buyToken, uint256 tokenAmountPerUnit) external payable +``` + +This function buys Hypercert tokens from an existing offer. The function verifies that the offer is valid and that the buyer has provided enough payment in the specified token. If the offer is for a fraction of a Hypercert token, the function splits the fraction and transfers the appropriate number of units to the buyer. If the offer is for a fixed number of units, the function transfers the units to the buyer. The function also transfers the payment to the offerer and emits a `Trade` event. + +_Buys Hypercert tokens from an existing offer._ + +#### Parameters + +| Name | Type | Description | +| ------------------ | ------- | --------------------------------------------------- | +| recipient | address | The address that will receive the Hypercert tokens. | +| offerID | uint256 | The ID of the offer to buy from. | +| unitAmount | uint256 | The number of units to buy. | +| buyToken | address | The address of the token used for payment. | +| tokenAmountPerUnit | uint256 | The amount of tokens to pay per unit. | + +### cancelOffer + +```solidity +function cancelOffer(uint256 offerID) external nonpayable +``` + +This function cancels an existing offer. The function verifies that the offer exists and that the caller is the offerer. The function sets the offer status to `Cancelled` and emits an `OfferCancelled` event. + +_Cancels an existing offer._ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ------------------------------ | +| offerID | uint256 | The ID of the offer to cancel. | + +### createOffer + +```solidity +function createOffer(address hypercertContract, uint256 fractionID, uint256 unitsForSale, uint256 minUnitsPerTrade, uint256 maxUnitsPerTrade, IHypercertTrader.AcceptedToken[] acceptedTokens) external payable returns (uint256 offerID) +``` + +#### Parameters + +| Name | Type | Description | +| ----------------- | -------------------------------- | ----------- | +| hypercertContract | address | undefined | +| fractionID | uint256 | undefined | +| unitsForSale | uint256 | undefined | +| minUnitsPerTrade | uint256 | undefined | +| maxUnitsPerTrade | uint256 | undefined | +| acceptedTokens | IHypercertTrader.AcceptedToken[] | undefined | + +#### Returns + +| Name | Type | Description | +| ------- | ------- | ----------- | +| offerID | uint256 | undefined | + +### initialize + +```solidity +function initialize() external nonpayable +``` + +_see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol }_ + +### offers + +```solidity +function offers(uint256) external view returns (address offerer, address hypercertContract, uint256 fractionID, uint256 unitsAvailable, uint256 minUnitsPerTrade, uint256 maxUnitsPerTrade, enum IHypercertTrader.OfferType offerType, enum IHypercertTrader.OfferStatus status) +``` + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ----------------- | --------------------------------- | ----------- | +| offerer | address | undefined | +| hypercertContract | address | undefined | +| fractionID | uint256 | undefined | +| unitsAvailable | uint256 | undefined | +| minUnitsPerTrade | uint256 | undefined | +| maxUnitsPerTrade | uint256 | undefined | +| offerType | enum IHypercertTrader.OfferType | undefined | +| status | enum IHypercertTrader.OfferStatus | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +_Returns the address of the current owner._ + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### pause + +```solidity +function pause() external nonpayable +``` + +PAUSABLE + +### paused + +```solidity +function paused() external view returns (bool) +``` + +_Returns true if the contract is paused, and false otherwise._ + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### proxiableUUID + +```solidity +function proxiableUUID() external view returns (bytes32) +``` + +_Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier._ + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + +_Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner._ + +### totalUnitsForSale + +```solidity +function totalUnitsForSale(address, uint256) external view returns (uint256) +``` + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | +| \_1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + +_Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner._ + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +### unpause + +```solidity +function unpause() external nonpayable +``` + +### upgradeTo + +```solidity +function upgradeTo(address newImplementation) external nonpayable +``` + +_Upgrade the implementation of the proxy to `newImplementation`. Calls {\_authorizeUpgrade}. Emits an {Upgraded} event._ + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| newImplementation | address | undefined | + +### upgradeToAndCall + +```solidity +function upgradeToAndCall(address newImplementation, bytes data) external payable +``` + +_Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {\_authorizeUpgrade}. Emits an {Upgraded} event._ + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| newImplementation | address | undefined | +| data | bytes | undefined | + +## Events + +### AdminChanged + +```solidity +event AdminChanged(address previousAdmin, address newAdmin) +``` + +#### Parameters + +| Name | Type | Description | +| ------------- | ------- | ----------- | +| previousAdmin | address | undefined | +| newAdmin | address | undefined | + +### BeaconUpgraded + +```solidity +event BeaconUpgraded(address indexed beacon) +``` + +#### Parameters + +| Name | Type | Description | +| ---------------- | ------- | ----------- | +| beacon `indexed` | address | undefined | + +### Initialized + +```solidity +event Initialized(uint8 version) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ----- | ----------- | +| version | uint8 | undefined | + +### OfferCancelled + +```solidity +event OfferCancelled(address indexed creator, address indexed hypercertContract, uint256 indexed fractionID, uint256 offerID) +``` + +#### Parameters + +| Name | Type | Description | +| --------------------------- | ------- | ----------- | +| creator `indexed` | address | undefined | +| hypercertContract `indexed` | address | undefined | +| fractionID `indexed` | uint256 | undefined | +| offerID | uint256 | undefined | + +### OfferCreated + +```solidity +event OfferCreated(address indexed offerer, address indexed hypercertContract, uint256 indexed fractionID, uint256 offerID) +``` + +#### Parameters + +| Name | Type | Description | +| --------------------------- | ------- | ----------- | +| offerer `indexed` | address | undefined | +| hypercertContract `indexed` | address | undefined | +| fractionID `indexed` | uint256 | undefined | +| offerID | uint256 | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + +#### Parameters + +| Name | Type | Description | +| ----------------------- | ------- | ----------- | +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + +### Paused + +```solidity +event Paused(address account) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | + +### Trade + +```solidity +event Trade(address indexed seller, address indexed buyer, address indexed hypercertContract, uint256 fractionID, uint256 unitsBought, address buyToken, uint256 tokenAmountPerUnit, uint256 offerID) +``` + +#### Parameters + +| Name | Type | Description | +| --------------------------- | ------- | ----------- | +| seller `indexed` | address | undefined | +| buyer `indexed` | address | undefined | +| hypercertContract `indexed` | address | undefined | +| fractionID | uint256 | undefined | +| unitsBought | uint256 | undefined | +| buyToken | address | undefined | +| tokenAmountPerUnit | uint256 | undefined | +| offerID | uint256 | undefined | + +### Unpaused + +```solidity +event Unpaused(address account) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | + +### Upgraded + +```solidity +event Upgraded(address indexed implementation) +``` + +#### Parameters + +| Name | Type | Description | +| ------------------------ | ------- | ----------- | +| implementation `indexed` | address | undefined | + +## Errors + +### InvalidBuy + +```solidity +error InvalidBuy(string) +``` + +#### Parameters + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | string | undefined | + +### InvalidOffer + +```solidity +error InvalidOffer(string) +``` + +#### Parameters + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | string | undefined | + +### NotAllowed + +```solidity +error NotAllowed() +``` diff --git a/docs/docs/developer/api/contracts/IHypercertMinter.md b/docs/docs/developer/api/contracts/IHypercertMinter.md new file mode 100644 index 00000000..13a84632 --- /dev/null +++ b/docs/docs/developer/api/contracts/IHypercertMinter.md @@ -0,0 +1,39 @@ +# IHypercertMinter + +## Methods + +### ownerOf + +```solidity +function ownerOf(uint256 id) external view returns (address) +``` + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| id | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### unitsOf + +```solidity +function unitsOf(uint256 id) external view returns (uint256) +``` + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| id | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | diff --git a/docs/docs/developer/api/contracts/interfaces/IHypercertTrader.md b/docs/docs/developer/api/contracts/interfaces/IHypercertTrader.md new file mode 100644 index 00000000..06fb700c --- /dev/null +++ b/docs/docs/developer/api/contracts/interfaces/IHypercertTrader.md @@ -0,0 +1,133 @@ +# IHypercertTrader + +_bitbeckers_ + +> Interface for hypercert token trading + +This interface declares the required functionality to interact with the hypercert marketplace + +## Methods + +### batchBuyUnits + +```solidity +function batchBuyUnits(address recipient, uint256[] offerIDs, uint256[] unitAmounts, address[] buyTokens, uint256[] tokenAmountsPerUnit) external payable +``` + +_Buys Hypercert tokens from multiple existing offers in a single transaction._ + +#### Parameters + +| Name | Type | Description | +| ------------------- | --------- | -------------------------------------------------------------------- | +| recipient | address | The address that will receive the Hypercert tokens. | +| offerIDs | uint256[] | The list of IDs of the offers to buy from. | +| unitAmounts | uint256[] | The list of numbers of units to buy for each offer. | +| buyTokens | address[] | The list of addresses of the tokens used for payment for each offer. | +| tokenAmountsPerUnit | uint256[] | The list of amounts of tokens to pay per unit for each offer. | + +### buyUnits + +```solidity +function buyUnits(address recipient, uint256 offerID, uint256 unitAmount, address buyToken, uint256 tokenAmountPerUnit) external payable +``` + +_Buys Hypercert tokens from an existing offer._ + +#### Parameters + +| Name | Type | Description | +| ------------------ | ------- | --------------------------------------------------- | +| recipient | address | The address that will receive the Hypercert tokens. | +| offerID | uint256 | The ID of the offer to buy from. | +| unitAmount | uint256 | The number of units to buy. | +| buyToken | address | The address of the token used for payment. | +| tokenAmountPerUnit | uint256 | The amount of tokens to pay per unit. | + +### cancelOffer + +```solidity +function cancelOffer(uint256 offerID) external nonpayable +``` + +_Cancels an existing offer._ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ------------------------------ | +| offerID | uint256 | The ID of the offer to cancel. | + +### createOffer + +```solidity +function createOffer(address hypercertContract, uint256 fractionID, uint256 units, uint256 minUnitsPerTrade, uint256 maxUnitsPerTrade, IHypercertTrader.AcceptedToken[] acceptedTokens) external payable returns (uint256 offerID) +``` + +#### Parameters + +| Name | Type | Description | +| ----------------- | -------------------------------- | ----------- | +| hypercertContract | address | undefined | +| fractionID | uint256 | undefined | +| units | uint256 | undefined | +| minUnitsPerTrade | uint256 | undefined | +| maxUnitsPerTrade | uint256 | undefined | +| acceptedTokens | IHypercertTrader.AcceptedToken[] | undefined | + +#### Returns + +| Name | Type | Description | +| ------- | ------- | ----------- | +| offerID | uint256 | undefined | + +## Events + +### OfferCancelled + +```solidity +event OfferCancelled(address indexed creator, address indexed hypercertContract, uint256 indexed fractionID, uint256 offerID) +``` + +#### Parameters + +| Name | Type | Description | +| --------------------------- | ------- | ----------- | +| creator `indexed` | address | undefined | +| hypercertContract `indexed` | address | undefined | +| fractionID `indexed` | uint256 | undefined | +| offerID | uint256 | undefined | + +### OfferCreated + +```solidity +event OfferCreated(address indexed offerer, address indexed hypercertContract, uint256 indexed fractionID, uint256 offerID) +``` + +#### Parameters + +| Name | Type | Description | +| --------------------------- | ------- | ----------- | +| offerer `indexed` | address | undefined | +| hypercertContract `indexed` | address | undefined | +| fractionID `indexed` | uint256 | undefined | +| offerID | uint256 | undefined | + +### Trade + +```solidity +event Trade(address indexed seller, address indexed buyer, address indexed hypercertContract, uint256 fractionID, uint256 unitsBought, address buyToken, uint256 tokenAmountPerUnit, uint256 offerID) +``` + +#### Parameters + +| Name | Type | Description | +| --------------------------- | ------- | ----------- | +| seller `indexed` | address | undefined | +| buyer `indexed` | address | undefined | +| hypercertContract `indexed` | address | undefined | +| fractionID | uint256 | undefined | +| unitsBought | uint256 | undefined | +| buyToken | address | undefined | +| tokenAmountPerUnit | uint256 | undefined | +| offerID | uint256 | undefined | diff --git a/frontend/hooks/mintFractionAllowlistBatch.ts b/frontend/hooks/mintFractionAllowlistBatch.ts index 34ee6c98..8f499c7e 100644 --- a/frontend/hooks/mintFractionAllowlistBatch.ts +++ b/frontend/hooks/mintFractionAllowlistBatch.ts @@ -3,14 +3,14 @@ import { mintInteractionLabels } from "../content/chainInteractions"; import { SUPABASE_TABLE } from "../lib/config"; import { useParseBlockchainError } from "../lib/parse-blockchain-error"; import { supabase } from "../lib/supabase-client"; -import { ClaimProof, useVerifyFractionClaim } from "./verifyFractionClaim"; import { HexString } from "../types/web3"; import { useAccountLowerCase } from "./account"; -import { useQuery } from "@tanstack/react-query"; -import { toast } from "react-toastify"; import { useHypercertClient } from "./hypercerts-client"; -import { useState } from "react"; +import { ClaimProof, useVerifyFractionClaim } from "./verifyFractionClaim"; +import { useQuery } from "@tanstack/react-query"; import _ from "lodash"; +import { useState } from "react"; +import { toast } from "react-toastify"; export const useMintFractionAllowlistBatch = ({ onComplete, @@ -116,7 +116,8 @@ export const useGetAllEligibility = (address: string) => { const { data, error } = await supabase .from(SUPABASE_TABLE) .select("*") - .eq("address", address.toLowerCase()); + .eq("address", address.toLowerCase()) + .eq("hidden", false); if (error) { console.error("Supabase error:"); console.error(error); diff --git a/graph/abis/HypercertTrader.json b/graph/abis/HypercertTrader.json new file mode 100644 index 00000000..4851032d --- /dev/null +++ b/graph/abis/HypercertTrader.json @@ -0,0 +1,456 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [{ "internalType": "string", "name": "", "type": "string" }], + "name": "InvalidBuy", + "type": "error" + }, + { + "inputs": [{ "internalType": "string", "name": "", "type": "string" }], + "name": "InvalidOffer", + "type": "error" + }, + { "inputs": [], "name": "NotAllowed", "type": "error" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "hypercertContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "fractionID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "offerID", + "type": "uint256" + } + ], + "name": "OfferCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "offerer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "hypercertContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "fractionID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "offerID", + "type": "uint256" + } + ], + "name": "OfferCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "seller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "buyer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "hypercertContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fractionID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "unitsBought", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "buyToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmountPerUnit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "offerID", + "type": "uint256" + } + ], + "name": "Trade", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [ + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256[]", "name": "offerIDs", "type": "uint256[]" }, + { + "internalType": "uint256[]", + "name": "unitAmounts", + "type": "uint256[]" + }, + { "internalType": "address[]", "name": "buyTokens", "type": "address[]" }, + { + "internalType": "uint256[]", + "name": "tokenAmountsPerUnit", + "type": "uint256[]" + } + ], + "name": "batchBuyUnits", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "offerID", "type": "uint256" }, + { "internalType": "uint256", "name": "unitAmount", "type": "uint256" }, + { "internalType": "address", "name": "buyToken", "type": "address" }, + { + "internalType": "uint256", + "name": "tokenAmountPerUnit", + "type": "uint256" + } + ], + "name": "buyUnits", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "offerID", "type": "uint256" } + ], + "name": "cancelOffer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "hypercertContract", + "type": "address" + }, + { "internalType": "uint256", "name": "fractionID", "type": "uint256" }, + { "internalType": "uint256", "name": "unitsForSale", "type": "uint256" }, + { + "internalType": "uint256", + "name": "minUnitsPerTrade", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxUnitsPerTrade", + "type": "uint256" + }, + { + "components": [ + { "internalType": "address", "name": "token", "type": "address" }, + { + "internalType": "uint256", + "name": "minimumAmountPerUnit", + "type": "uint256" + } + ], + "internalType": "struct IHypercertTrader.AcceptedToken[]", + "name": "acceptedTokens", + "type": "tuple[]" + } + ], + "name": "createOffer", + "outputs": [ + { "internalType": "uint256", "name": "offerID", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "offers", + "outputs": [ + { "internalType": "address", "name": "offerer", "type": "address" }, + { + "internalType": "address", + "name": "hypercertContract", + "type": "address" + }, + { "internalType": "uint256", "name": "fractionID", "type": "uint256" }, + { + "internalType": "uint256", + "name": "unitsAvailable", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minUnitsPerTrade", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxUnitsPerTrade", + "type": "uint256" + }, + { + "internalType": "enum IHypercertTrader.OfferType", + "name": "offerType", + "type": "uint8" + }, + { + "internalType": "enum IHypercertTrader.OfferStatus", + "name": "status", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "name": "totalUnitsForSale", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/graph/generated/HypercertTrader/HypercertTrader.ts b/graph/generated/HypercertTrader/HypercertTrader.ts new file mode 100644 index 00000000..58e780d5 --- /dev/null +++ b/graph/generated/HypercertTrader/HypercertTrader.ts @@ -0,0 +1,875 @@ +// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. + +import { + ethereum, + JSONValue, + TypedMap, + Entity, + Bytes, + Address, + BigInt, +} from "@graphprotocol/graph-ts"; + +export class AdminChanged extends ethereum.Event { + get params(): AdminChanged__Params { + return new AdminChanged__Params(this); + } +} + +export class AdminChanged__Params { + _event: AdminChanged; + + constructor(event: AdminChanged) { + this._event = event; + } + + get previousAdmin(): Address { + return this._event.parameters[0].value.toAddress(); + } + + get newAdmin(): Address { + return this._event.parameters[1].value.toAddress(); + } +} + +export class BeaconUpgraded extends ethereum.Event { + get params(): BeaconUpgraded__Params { + return new BeaconUpgraded__Params(this); + } +} + +export class BeaconUpgraded__Params { + _event: BeaconUpgraded; + + constructor(event: BeaconUpgraded) { + this._event = event; + } + + get beacon(): Address { + return this._event.parameters[0].value.toAddress(); + } +} + +export class Initialized extends ethereum.Event { + get params(): Initialized__Params { + return new Initialized__Params(this); + } +} + +export class Initialized__Params { + _event: Initialized; + + constructor(event: Initialized) { + this._event = event; + } + + get version(): i32 { + return this._event.parameters[0].value.toI32(); + } +} + +export class OfferCancelled extends ethereum.Event { + get params(): OfferCancelled__Params { + return new OfferCancelled__Params(this); + } +} + +export class OfferCancelled__Params { + _event: OfferCancelled; + + constructor(event: OfferCancelled) { + this._event = event; + } + + get creator(): Address { + return this._event.parameters[0].value.toAddress(); + } + + get hypercertContract(): Address { + return this._event.parameters[1].value.toAddress(); + } + + get fractionID(): BigInt { + return this._event.parameters[2].value.toBigInt(); + } + + get offerID(): BigInt { + return this._event.parameters[3].value.toBigInt(); + } +} + +export class OfferCreated extends ethereum.Event { + get params(): OfferCreated__Params { + return new OfferCreated__Params(this); + } +} + +export class OfferCreated__Params { + _event: OfferCreated; + + constructor(event: OfferCreated) { + this._event = event; + } + + get offerer(): Address { + return this._event.parameters[0].value.toAddress(); + } + + get hypercertContract(): Address { + return this._event.parameters[1].value.toAddress(); + } + + get fractionID(): BigInt { + return this._event.parameters[2].value.toBigInt(); + } + + get offerID(): BigInt { + return this._event.parameters[3].value.toBigInt(); + } +} + +export class OwnershipTransferred extends ethereum.Event { + get params(): OwnershipTransferred__Params { + return new OwnershipTransferred__Params(this); + } +} + +export class OwnershipTransferred__Params { + _event: OwnershipTransferred; + + constructor(event: OwnershipTransferred) { + this._event = event; + } + + get previousOwner(): Address { + return this._event.parameters[0].value.toAddress(); + } + + get newOwner(): Address { + return this._event.parameters[1].value.toAddress(); + } +} + +export class Paused extends ethereum.Event { + get params(): Paused__Params { + return new Paused__Params(this); + } +} + +export class Paused__Params { + _event: Paused; + + constructor(event: Paused) { + this._event = event; + } + + get account(): Address { + return this._event.parameters[0].value.toAddress(); + } +} + +export class Trade extends ethereum.Event { + get params(): Trade__Params { + return new Trade__Params(this); + } +} + +export class Trade__Params { + _event: Trade; + + constructor(event: Trade) { + this._event = event; + } + + get seller(): Address { + return this._event.parameters[0].value.toAddress(); + } + + get buyer(): Address { + return this._event.parameters[1].value.toAddress(); + } + + get hypercertContract(): Address { + return this._event.parameters[2].value.toAddress(); + } + + get fractionID(): BigInt { + return this._event.parameters[3].value.toBigInt(); + } + + get unitsBought(): BigInt { + return this._event.parameters[4].value.toBigInt(); + } + + get buyToken(): Address { + return this._event.parameters[5].value.toAddress(); + } + + get tokenAmountPerUnit(): BigInt { + return this._event.parameters[6].value.toBigInt(); + } + + get offerID(): BigInt { + return this._event.parameters[7].value.toBigInt(); + } +} + +export class Unpaused extends ethereum.Event { + get params(): Unpaused__Params { + return new Unpaused__Params(this); + } +} + +export class Unpaused__Params { + _event: Unpaused; + + constructor(event: Unpaused) { + this._event = event; + } + + get account(): Address { + return this._event.parameters[0].value.toAddress(); + } +} + +export class Upgraded extends ethereum.Event { + get params(): Upgraded__Params { + return new Upgraded__Params(this); + } +} + +export class Upgraded__Params { + _event: Upgraded; + + constructor(event: Upgraded) { + this._event = event; + } + + get implementation(): Address { + return this._event.parameters[0].value.toAddress(); + } +} + +export class HypercertTrader__offersResult { + value0: Address; + value1: Address; + value2: BigInt; + value3: BigInt; + value4: BigInt; + value5: BigInt; + value6: i32; + value7: i32; + + constructor( + value0: Address, + value1: Address, + value2: BigInt, + value3: BigInt, + value4: BigInt, + value5: BigInt, + value6: i32, + value7: i32, + ) { + this.value0 = value0; + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + this.value4 = value4; + this.value5 = value5; + this.value6 = value6; + this.value7 = value7; + } + + toMap(): TypedMap { + let map = new TypedMap(); + map.set("value0", ethereum.Value.fromAddress(this.value0)); + map.set("value1", ethereum.Value.fromAddress(this.value1)); + map.set("value2", ethereum.Value.fromUnsignedBigInt(this.value2)); + map.set("value3", ethereum.Value.fromUnsignedBigInt(this.value3)); + map.set("value4", ethereum.Value.fromUnsignedBigInt(this.value4)); + map.set("value5", ethereum.Value.fromUnsignedBigInt(this.value5)); + map.set( + "value6", + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(this.value6)), + ); + map.set( + "value7", + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(this.value7)), + ); + return map; + } + + getOfferer(): Address { + return this.value0; + } + + getHypercertContract(): Address { + return this.value1; + } + + getFractionID(): BigInt { + return this.value2; + } + + getUnitsAvailable(): BigInt { + return this.value3; + } + + getMinUnitsPerTrade(): BigInt { + return this.value4; + } + + getMaxUnitsPerTrade(): BigInt { + return this.value5; + } + + getOfferType(): i32 { + return this.value6; + } + + getStatus(): i32 { + return this.value7; + } +} + +export class HypercertTrader extends ethereum.SmartContract { + static bind(address: Address): HypercertTrader { + return new HypercertTrader("HypercertTrader", address); + } + + offers(param0: BigInt): HypercertTrader__offersResult { + let result = super.call( + "offers", + "offers(uint256):(address,address,uint256,uint256,uint256,uint256,uint8,uint8)", + [ethereum.Value.fromUnsignedBigInt(param0)], + ); + + return new HypercertTrader__offersResult( + result[0].toAddress(), + result[1].toAddress(), + result[2].toBigInt(), + result[3].toBigInt(), + result[4].toBigInt(), + result[5].toBigInt(), + result[6].toI32(), + result[7].toI32(), + ); + } + + try_offers( + param0: BigInt, + ): ethereum.CallResult { + let result = super.tryCall( + "offers", + "offers(uint256):(address,address,uint256,uint256,uint256,uint256,uint8,uint8)", + [ethereum.Value.fromUnsignedBigInt(param0)], + ); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue( + new HypercertTrader__offersResult( + value[0].toAddress(), + value[1].toAddress(), + value[2].toBigInt(), + value[3].toBigInt(), + value[4].toBigInt(), + value[5].toBigInt(), + value[6].toI32(), + value[7].toI32(), + ), + ); + } + + owner(): Address { + let result = super.call("owner", "owner():(address)", []); + + return result[0].toAddress(); + } + + try_owner(): ethereum.CallResult
{ + let result = super.tryCall("owner", "owner():(address)", []); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue(value[0].toAddress()); + } + + paused(): boolean { + let result = super.call("paused", "paused():(bool)", []); + + return result[0].toBoolean(); + } + + try_paused(): ethereum.CallResult { + let result = super.tryCall("paused", "paused():(bool)", []); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue(value[0].toBoolean()); + } + + proxiableUUID(): Bytes { + let result = super.call("proxiableUUID", "proxiableUUID():(bytes32)", []); + + return result[0].toBytes(); + } + + try_proxiableUUID(): ethereum.CallResult { + let result = super.tryCall( + "proxiableUUID", + "proxiableUUID():(bytes32)", + [], + ); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue(value[0].toBytes()); + } + + totalUnitsForSale(param0: Address, param1: BigInt): BigInt { + let result = super.call( + "totalUnitsForSale", + "totalUnitsForSale(address,uint256):(uint256)", + [ + ethereum.Value.fromAddress(param0), + ethereum.Value.fromUnsignedBigInt(param1), + ], + ); + + return result[0].toBigInt(); + } + + try_totalUnitsForSale( + param0: Address, + param1: BigInt, + ): ethereum.CallResult { + let result = super.tryCall( + "totalUnitsForSale", + "totalUnitsForSale(address,uint256):(uint256)", + [ + ethereum.Value.fromAddress(param0), + ethereum.Value.fromUnsignedBigInt(param1), + ], + ); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue(value[0].toBigInt()); + } +} + +export class ConstructorCall extends ethereum.Call { + get inputs(): ConstructorCall__Inputs { + return new ConstructorCall__Inputs(this); + } + + get outputs(): ConstructorCall__Outputs { + return new ConstructorCall__Outputs(this); + } +} + +export class ConstructorCall__Inputs { + _call: ConstructorCall; + + constructor(call: ConstructorCall) { + this._call = call; + } +} + +export class ConstructorCall__Outputs { + _call: ConstructorCall; + + constructor(call: ConstructorCall) { + this._call = call; + } +} + +export class BatchBuyUnitsCall extends ethereum.Call { + get inputs(): BatchBuyUnitsCall__Inputs { + return new BatchBuyUnitsCall__Inputs(this); + } + + get outputs(): BatchBuyUnitsCall__Outputs { + return new BatchBuyUnitsCall__Outputs(this); + } +} + +export class BatchBuyUnitsCall__Inputs { + _call: BatchBuyUnitsCall; + + constructor(call: BatchBuyUnitsCall) { + this._call = call; + } + + get recipient(): Address { + return this._call.inputValues[0].value.toAddress(); + } + + get offerIDs(): Array { + return this._call.inputValues[1].value.toBigIntArray(); + } + + get unitAmounts(): Array { + return this._call.inputValues[2].value.toBigIntArray(); + } + + get buyTokens(): Array
{ + return this._call.inputValues[3].value.toAddressArray(); + } + + get tokenAmountsPerUnit(): Array { + return this._call.inputValues[4].value.toBigIntArray(); + } +} + +export class BatchBuyUnitsCall__Outputs { + _call: BatchBuyUnitsCall; + + constructor(call: BatchBuyUnitsCall) { + this._call = call; + } +} + +export class BuyUnitsCall extends ethereum.Call { + get inputs(): BuyUnitsCall__Inputs { + return new BuyUnitsCall__Inputs(this); + } + + get outputs(): BuyUnitsCall__Outputs { + return new BuyUnitsCall__Outputs(this); + } +} + +export class BuyUnitsCall__Inputs { + _call: BuyUnitsCall; + + constructor(call: BuyUnitsCall) { + this._call = call; + } + + get recipient(): Address { + return this._call.inputValues[0].value.toAddress(); + } + + get offerID(): BigInt { + return this._call.inputValues[1].value.toBigInt(); + } + + get unitAmount(): BigInt { + return this._call.inputValues[2].value.toBigInt(); + } + + get buyToken(): Address { + return this._call.inputValues[3].value.toAddress(); + } + + get tokenAmountPerUnit(): BigInt { + return this._call.inputValues[4].value.toBigInt(); + } +} + +export class BuyUnitsCall__Outputs { + _call: BuyUnitsCall; + + constructor(call: BuyUnitsCall) { + this._call = call; + } +} + +export class CancelOfferCall extends ethereum.Call { + get inputs(): CancelOfferCall__Inputs { + return new CancelOfferCall__Inputs(this); + } + + get outputs(): CancelOfferCall__Outputs { + return new CancelOfferCall__Outputs(this); + } +} + +export class CancelOfferCall__Inputs { + _call: CancelOfferCall; + + constructor(call: CancelOfferCall) { + this._call = call; + } + + get offerID(): BigInt { + return this._call.inputValues[0].value.toBigInt(); + } +} + +export class CancelOfferCall__Outputs { + _call: CancelOfferCall; + + constructor(call: CancelOfferCall) { + this._call = call; + } +} + +export class CreateOfferCall extends ethereum.Call { + get inputs(): CreateOfferCall__Inputs { + return new CreateOfferCall__Inputs(this); + } + + get outputs(): CreateOfferCall__Outputs { + return new CreateOfferCall__Outputs(this); + } +} + +export class CreateOfferCall__Inputs { + _call: CreateOfferCall; + + constructor(call: CreateOfferCall) { + this._call = call; + } + + get hypercertContract(): Address { + return this._call.inputValues[0].value.toAddress(); + } + + get fractionID(): BigInt { + return this._call.inputValues[1].value.toBigInt(); + } + + get unitsForSale(): BigInt { + return this._call.inputValues[2].value.toBigInt(); + } + + get minUnitsPerTrade(): BigInt { + return this._call.inputValues[3].value.toBigInt(); + } + + get maxUnitsPerTrade(): BigInt { + return this._call.inputValues[4].value.toBigInt(); + } + + get acceptedTokens(): Array { + return this._call.inputValues[5].value.toTupleArray(); + } +} + +export class CreateOfferCall__Outputs { + _call: CreateOfferCall; + + constructor(call: CreateOfferCall) { + this._call = call; + } + + get offerID(): BigInt { + return this._call.outputValues[0].value.toBigInt(); + } +} + +export class CreateOfferCallAcceptedTokensStruct extends ethereum.Tuple { + get token(): Address { + return this[0].toAddress(); + } + + get minimumAmountPerUnit(): BigInt { + return this[1].toBigInt(); + } +} + +export class InitializeCall extends ethereum.Call { + get inputs(): InitializeCall__Inputs { + return new InitializeCall__Inputs(this); + } + + get outputs(): InitializeCall__Outputs { + return new InitializeCall__Outputs(this); + } +} + +export class InitializeCall__Inputs { + _call: InitializeCall; + + constructor(call: InitializeCall) { + this._call = call; + } +} + +export class InitializeCall__Outputs { + _call: InitializeCall; + + constructor(call: InitializeCall) { + this._call = call; + } +} + +export class PauseCall extends ethereum.Call { + get inputs(): PauseCall__Inputs { + return new PauseCall__Inputs(this); + } + + get outputs(): PauseCall__Outputs { + return new PauseCall__Outputs(this); + } +} + +export class PauseCall__Inputs { + _call: PauseCall; + + constructor(call: PauseCall) { + this._call = call; + } +} + +export class PauseCall__Outputs { + _call: PauseCall; + + constructor(call: PauseCall) { + this._call = call; + } +} + +export class RenounceOwnershipCall extends ethereum.Call { + get inputs(): RenounceOwnershipCall__Inputs { + return new RenounceOwnershipCall__Inputs(this); + } + + get outputs(): RenounceOwnershipCall__Outputs { + return new RenounceOwnershipCall__Outputs(this); + } +} + +export class RenounceOwnershipCall__Inputs { + _call: RenounceOwnershipCall; + + constructor(call: RenounceOwnershipCall) { + this._call = call; + } +} + +export class RenounceOwnershipCall__Outputs { + _call: RenounceOwnershipCall; + + constructor(call: RenounceOwnershipCall) { + this._call = call; + } +} + +export class TransferOwnershipCall extends ethereum.Call { + get inputs(): TransferOwnershipCall__Inputs { + return new TransferOwnershipCall__Inputs(this); + } + + get outputs(): TransferOwnershipCall__Outputs { + return new TransferOwnershipCall__Outputs(this); + } +} + +export class TransferOwnershipCall__Inputs { + _call: TransferOwnershipCall; + + constructor(call: TransferOwnershipCall) { + this._call = call; + } + + get newOwner(): Address { + return this._call.inputValues[0].value.toAddress(); + } +} + +export class TransferOwnershipCall__Outputs { + _call: TransferOwnershipCall; + + constructor(call: TransferOwnershipCall) { + this._call = call; + } +} + +export class UnpauseCall extends ethereum.Call { + get inputs(): UnpauseCall__Inputs { + return new UnpauseCall__Inputs(this); + } + + get outputs(): UnpauseCall__Outputs { + return new UnpauseCall__Outputs(this); + } +} + +export class UnpauseCall__Inputs { + _call: UnpauseCall; + + constructor(call: UnpauseCall) { + this._call = call; + } +} + +export class UnpauseCall__Outputs { + _call: UnpauseCall; + + constructor(call: UnpauseCall) { + this._call = call; + } +} + +export class UpgradeToCall extends ethereum.Call { + get inputs(): UpgradeToCall__Inputs { + return new UpgradeToCall__Inputs(this); + } + + get outputs(): UpgradeToCall__Outputs { + return new UpgradeToCall__Outputs(this); + } +} + +export class UpgradeToCall__Inputs { + _call: UpgradeToCall; + + constructor(call: UpgradeToCall) { + this._call = call; + } + + get newImplementation(): Address { + return this._call.inputValues[0].value.toAddress(); + } +} + +export class UpgradeToCall__Outputs { + _call: UpgradeToCall; + + constructor(call: UpgradeToCall) { + this._call = call; + } +} + +export class UpgradeToAndCallCall extends ethereum.Call { + get inputs(): UpgradeToAndCallCall__Inputs { + return new UpgradeToAndCallCall__Inputs(this); + } + + get outputs(): UpgradeToAndCallCall__Outputs { + return new UpgradeToAndCallCall__Outputs(this); + } +} + +export class UpgradeToAndCallCall__Inputs { + _call: UpgradeToAndCallCall; + + constructor(call: UpgradeToAndCallCall) { + this._call = call; + } + + get newImplementation(): Address { + return this._call.inputValues[0].value.toAddress(); + } + + get data(): Bytes { + return this._call.inputValues[1].value.toBytes(); + } +} + +export class UpgradeToAndCallCall__Outputs { + _call: UpgradeToAndCallCall; + + constructor(call: UpgradeToAndCallCall) { + this._call = call; + } +} diff --git a/graph/generated/schema.ts b/graph/generated/schema.ts index a1ae231d..de8e18a1 100644 --- a/graph/generated/schema.ts +++ b/graph/generated/schema.ts @@ -332,3 +332,360 @@ export class ClaimToken extends Entity { this.set("units", Value.fromBigInt(value)); } } + +export class Token extends Entity { + constructor(id: string) { + super(); + this.set("id", Value.fromString(id)); + } + + save(): void { + let id = this.get("id"); + assert(id != null, "Cannot save Token entity without an ID"); + if (id) { + assert( + id.kind == ValueKind.STRING, + `Entities of type Token must have an ID of type String but the id '${id.displayData()}' is of type ${id.displayKind()}`, + ); + store.set("Token", id.toString(), this); + } + } + + static loadInBlock(id: string): Token | null { + return changetype(store.get_in_block("Token", id)); + } + + static load(id: string): Token | null { + return changetype(store.get("Token", id)); + } + + get id(): string { + let value = this.get("id"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set id(value: string) { + this.set("id", Value.fromString(value)); + } + + get name(): string { + let value = this.get("name"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set name(value: string) { + this.set("name", Value.fromString(value)); + } +} + +export class AcceptedToken extends Entity { + constructor(id: string) { + super(); + this.set("id", Value.fromString(id)); + } + + save(): void { + let id = this.get("id"); + assert(id != null, "Cannot save AcceptedToken entity without an ID"); + if (id) { + assert( + id.kind == ValueKind.STRING, + `Entities of type AcceptedToken must have an ID of type String but the id '${id.displayData()}' is of type ${id.displayKind()}`, + ); + store.set("AcceptedToken", id.toString(), this); + } + } + + static loadInBlock(id: string): AcceptedToken | null { + return changetype( + store.get_in_block("AcceptedToken", id), + ); + } + + static load(id: string): AcceptedToken | null { + return changetype(store.get("AcceptedToken", id)); + } + + get id(): string { + let value = this.get("id"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set id(value: string) { + this.set("id", Value.fromString(value)); + } + + get token(): string { + let value = this.get("token"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set token(value: string) { + this.set("token", Value.fromString(value)); + } + + get minimumAmountPerUnit(): BigInt { + let value = this.get("minimumAmountPerUnit"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toBigInt(); + } + } + + set minimumAmountPerUnit(value: BigInt) { + this.set("minimumAmountPerUnit", Value.fromBigInt(value)); + } + + get accepted(): boolean { + let value = this.get("accepted"); + if (!value || value.kind == ValueKind.NULL) { + return false; + } else { + return value.toBoolean(); + } + } + + set accepted(value: boolean) { + this.set("accepted", Value.fromBoolean(value)); + } +} + +export class Offer extends Entity { + constructor(id: string) { + super(); + this.set("id", Value.fromString(id)); + } + + save(): void { + let id = this.get("id"); + assert(id != null, "Cannot save Offer entity without an ID"); + if (id) { + assert( + id.kind == ValueKind.STRING, + `Entities of type Offer must have an ID of type String but the id '${id.displayData()}' is of type ${id.displayKind()}`, + ); + store.set("Offer", id.toString(), this); + } + } + + static loadInBlock(id: string): Offer | null { + return changetype(store.get_in_block("Offer", id)); + } + + static load(id: string): Offer | null { + return changetype(store.get("Offer", id)); + } + + get id(): string { + let value = this.get("id"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set id(value: string) { + this.set("id", Value.fromString(value)); + } + + get fractionID(): string { + let value = this.get("fractionID"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set fractionID(value: string) { + this.set("fractionID", Value.fromString(value)); + } + + get unitsAvailable(): BigInt { + let value = this.get("unitsAvailable"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toBigInt(); + } + } + + set unitsAvailable(value: BigInt) { + this.set("unitsAvailable", Value.fromBigInt(value)); + } + + get minUnitsPerTrade(): BigInt { + let value = this.get("minUnitsPerTrade"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toBigInt(); + } + } + + set minUnitsPerTrade(value: BigInt) { + this.set("minUnitsPerTrade", Value.fromBigInt(value)); + } + + get maxUnitsPerTrade(): BigInt { + let value = this.get("maxUnitsPerTrade"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toBigInt(); + } + } + + set maxUnitsPerTrade(value: BigInt) { + this.set("maxUnitsPerTrade", Value.fromBigInt(value)); + } + + get status(): string { + let value = this.get("status"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set status(value: string) { + this.set("status", Value.fromString(value)); + } + + get acceptedTokens(): Array { + let value = this.get("acceptedTokens"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toStringArray(); + } + } + + set acceptedTokens(value: Array) { + this.set("acceptedTokens", Value.fromStringArray(value)); + } +} + +export class Trade extends Entity { + constructor(id: string) { + super(); + this.set("id", Value.fromString(id)); + } + + save(): void { + let id = this.get("id"); + assert(id != null, "Cannot save Trade entity without an ID"); + if (id) { + assert( + id.kind == ValueKind.STRING, + `Entities of type Trade must have an ID of type String but the id '${id.displayData()}' is of type ${id.displayKind()}`, + ); + store.set("Trade", id.toString(), this); + } + } + + static loadInBlock(id: string): Trade | null { + return changetype(store.get_in_block("Trade", id)); + } + + static load(id: string): Trade | null { + return changetype(store.get("Trade", id)); + } + + get id(): string { + let value = this.get("id"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set id(value: string) { + this.set("id", Value.fromString(value)); + } + + get buyer(): Bytes { + let value = this.get("buyer"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toBytes(); + } + } + + set buyer(value: Bytes) { + this.set("buyer", Value.fromBytes(value)); + } + + get offerID(): string { + let value = this.get("offerID"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set offerID(value: string) { + this.set("offerID", Value.fromString(value)); + } + + get unitsSold(): BigInt { + let value = this.get("unitsSold"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toBigInt(); + } + } + + set unitsSold(value: BigInt) { + this.set("unitsSold", Value.fromBigInt(value)); + } + + get token(): string { + let value = this.get("token"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set token(value: string) { + this.set("token", Value.fromString(value)); + } + + get amountPerUnit(): BigInt { + let value = this.get("amountPerUnit"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toBigInt(); + } + } + + set amountPerUnit(value: BigInt) { + this.set("amountPerUnit", Value.fromBigInt(value)); + } +} diff --git a/graph/networks.json b/graph/networks.json index 3097fa96..4c3e2c9f 100644 --- a/graph/networks.json +++ b/graph/networks.json @@ -3,6 +3,10 @@ "HypercertMinter": { "address": "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", "startBlock": 8537999 + }, + "HypercertTrader": { + "address": "0x689587461AA3103D3D7975c5e4B352Ab711C14C2", + "startBlock": 9638007 } }, "optimism": { diff --git a/graph/schema.graphql b/graph/schema.graphql index c2c8b8d5..e42546a0 100644 --- a/graph/schema.graphql +++ b/graph/schema.graphql @@ -23,3 +23,40 @@ type ClaimToken @entity { owner: Bytes! units: BigInt! } + +type Token @entity { + id: String! + name: String! +} + +type AcceptedToken @entity { + id: String! + token: Token! + minimumAmountPerUnit: BigInt! + accepted: Boolean! +} + +enum OfferStatus { + Open + Fulfilled + Cancelled +} + +type Offer @entity { + id: String! + fractionID: ClaimToken! + unitsAvailable: BigInt! + minUnitsPerTrade: BigInt! + maxUnitsPerTrade: BigInt! + status: OfferStatus! + acceptedTokens: [AcceptedToken!]! +} + +type Trade @entity { + id: String! + buyer: Bytes! + offerID: Offer! + unitsSold: BigInt! + token: Token! + amountPerUnit: BigInt! +} diff --git a/graph/src/hypercert-trader.ts b/graph/src/hypercert-trader.ts new file mode 100644 index 00000000..ac19cad3 --- /dev/null +++ b/graph/src/hypercert-trader.ts @@ -0,0 +1,69 @@ +import { + OfferCancelled as OfferCancelledEvent, + OfferCreated as OfferCreatedEvent, + Trade as TradeEvent, +} from "../generated/HypercertTrader/HypercertTrader"; +import { Trade } from "../generated/schema"; +import { getOrCreateOffer, getOrCreateOfferByID } from "./utils"; +import { log } from "@graphprotocol/graph-ts"; + +export function handleOfferCancelled(event: OfferCancelledEvent): void { + const offer = getOrCreateOfferByID( + event.params.hypercertContract, + event.params.fractionID, + event.params.offerID, + ); + + if (!offer) { + return; + } + + offer.status = "Cancelled"; + + offer.save(); +} + +export function handleOfferCreated(event: OfferCreatedEvent): void { + const offer = getOrCreateOffer( + event.params.hypercertContract, + event.address, + event.params.fractionID, + event.params.offerID, + ); + + // TODO get accepted tokens + offer.save(); +} + +export function handleTrade(event: TradeEvent): void { + const offer = getOrCreateOfferByID( + event.params.hypercertContract, + event.params.fractionID, + event.params.offerID, + ); + + if (!offer) { + log.error("Offer with ID {} not found", [ + event.params.offerID.toHexString(), + ]); + return; + } + + const tradeID = offer.id.concat(event.transaction.hash.toHexString()); + + let trade = Trade.load(tradeID); + + if (trade == null) { + trade = new Trade(tradeID); + + trade.buyer = event.params.buyer; + trade.offerID = offer.id; + trade.unitsSold = event.params.unitsBought; + trade.token = event.params.buyToken.toHexString(); + trade.amountPerUnit = event.params.tokenAmountPerUnit; + + trade.offerID = offer.id; + } + + trade.save(); +} diff --git a/graph/src/utils.ts b/graph/src/utils.ts index f60642b5..4511dcaa 100644 --- a/graph/src/utils.ts +++ b/graph/src/utils.ts @@ -1,6 +1,18 @@ -import { Address, BigInt, Bytes, log } from "@graphprotocol/graph-ts"; -import { Allowlist, Claim, ClaimToken } from "../generated/schema"; import { HypercertMinter } from "../generated/HypercertMinter/HypercertMinter"; +import { HypercertTrader } from "../generated/HypercertTrader/HypercertTrader"; +import { + AcceptedToken, + Allowlist, + Claim, + ClaimToken, + Offer, + Token, +} from "../generated/schema"; +import { Address, BigInt, Bytes, log } from "@graphprotocol/graph-ts"; + +export const ZERO_ADDRESS = Address.fromString( + "0x0000000000000000000000000000000000000000", +); export function getID(tokenID: BigInt, contract: Address): string { return contract.toHexString().concat("-".concat(tokenID.toString())); @@ -80,3 +92,83 @@ export function getOrCreateClaimToken( return fraction; } + +export function getOrCreateToken(token: Address): Token { + const _tokenID = token.toHexString(); + let _token = Token.load(_tokenID); + + if (_token == null) { + _token = new Token(_tokenID); + //TODO get token name + _token.name = "Native"; + _token.save(); + } + + return _token; +} + +export function getOrCreateAcceptedToken( + offerID: BigInt, + token: Address, +): AcceptedToken { + const _acceptedTokenID = offerID + .toHexString() + .concat("-".concat(token.toHexString())); + let acceptedToken = AcceptedToken.load(_acceptedTokenID); + + if (acceptedToken == null) { + acceptedToken = new AcceptedToken(_acceptedTokenID); + acceptedToken.token = getOrCreateToken(token).id; + acceptedToken.minimumAmountPerUnit = BigInt.fromI32(0); + acceptedToken.accepted = true; + acceptedToken.save(); + } + + return acceptedToken; +} + +export function getOrCreateOffer( + hypercertContract: Address, + traderContract: Address, + fractionID: BigInt, + offerID: BigInt, +): Offer { + const _traderContract = HypercertTrader.bind(traderContract); + + const _fractionID = getID(fractionID, hypercertContract); + const _offerID = fractionID + .toHexString() + .concat("-".concat(offerID.toString())); + let offer = Offer.load(_offerID); + + if (offer == null) { + const offerOnChain = _traderContract.offers(offerID); + offer = new Offer(_offerID); + offer.fractionID = _fractionID; + offer.unitsAvailable = offerOnChain.getUnitsAvailable(); + offer.minUnitsPerTrade = offerOnChain.getMinUnitsPerTrade(); + offer.maxUnitsPerTrade = offerOnChain.getMaxUnitsPerTrade(); + offer.status = "Open"; + offer.acceptedTokens = [getOrCreateAcceptedToken(offerID, ZERO_ADDRESS).id]; + offer.save(); + log.debug("Created offerID: {}", [_offerID]); + } + + return offer; +} + +export function getOrCreateOfferByID( + hypercertContract: Address, + fractionID: BigInt, + offerID: BigInt, +): Offer | null { + const _fractionID = getID(fractionID, hypercertContract); + const _offerID = _fractionID.concat("-".concat(offerID.toString())); + const offer = Offer.load(_offerID); + + if (offer == null) { + log.error("Offer with ID {} does not exist", [_offerID]); + } + + return offer; +} diff --git a/graph/subgraph.yaml b/graph/subgraph.yaml index 17951fcf..788e2dde 100644 --- a/graph/subgraph.yaml +++ b/graph/subgraph.yaml @@ -4,7 +4,7 @@ schema: dataSources: - kind: ethereum/contract name: HypercertMinter - network: optimism + network: goerli source: abi: HypercertMinter address: "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07" @@ -33,11 +33,9 @@ dataSources: handler: handleLeafClaimed - event: OwnershipTransferred(indexed address,indexed address) handler: handleOwnershipTransferred - - event: TransferBatch(indexed address,indexed address,indexed - address,uint256[],uint256[]) + - event: TransferBatch(indexed address,indexed address,indexed address,uint256[],uint256[]) handler: handleTransferBatch - - event: TransferSingle(indexed address,indexed address,indexed - address,uint256,uint256) + - event: TransferSingle(indexed address,indexed address,indexed address,uint256,uint256) handler: handleTransferSingle - event: URI(string,indexed uint256) handler: handleURI @@ -46,3 +44,27 @@ dataSources: - event: BatchValueTransfer(uint256[],uint256[],uint256[],uint256[]) handler: handleBatchValueTransfer file: ./src/hypercert-minter.ts + - kind: ethereum + name: HypercertTrader + network: goerli + source: + address: "0xFf3F27c6132c30d1098b97FfeC05C3150dA90432" + abi: HypercertTrader + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + entities: + - Offer + abis: + - name: HypercertTrader + file: ./abis/HypercertTrader.json + eventHandlers: + - event: OfferCancelled(indexed address,indexed address,indexed uint256,uint256) + handler: handleOfferCancelled + - event: OfferCreated(indexed address,indexed address,indexed uint256,uint256) + handler: handleOfferCreated + - event: Trade(indexed address,indexed address,indexed + address,uint256,uint256,address,uint256,uint256) + handler: handleTrade + file: ./src/hypercert-trader.ts diff --git a/graph/tests/.latest.json b/graph/tests/.latest.json index 113c99a7..1e6a7350 100644 --- a/graph/tests/.latest.json +++ b/graph/tests/.latest.json @@ -1,4 +1,4 @@ { "version": "0.5.4", - "timestamp": 1693308593418 + "timestamp": 1693949703219 } diff --git a/graph/tests/hypercert-minter-burn.test.ts b/graph/tests/hypercert-minter-burn.test.ts index 496b7c8b..09d35de4 100644 --- a/graph/tests/hypercert-minter-burn.test.ts +++ b/graph/tests/hypercert-minter-burn.test.ts @@ -5,9 +5,6 @@ import { handleTransferBatch, } from "../src/hypercert-minter"; import { - buildIDs, - buildValues, - buildZeroes, createBatchValueTransferEvent, createTransferBatchEvent, createTransferSingleEvent, @@ -23,7 +20,6 @@ import { test, clearStore, beforeAll, - afterAll, createMockedFunction, afterEach, } from "matchstick-as/assembly/index"; diff --git a/graph/tests/hypercert-minter-claim.test.ts b/graph/tests/hypercert-minter-claim.test.ts index 38c403c0..b7a6e45a 100644 --- a/graph/tests/hypercert-minter-claim.test.ts +++ b/graph/tests/hypercert-minter-claim.test.ts @@ -20,7 +20,7 @@ describe("Describe entity assertions", () => { let claimStoredEvent = createClaimStoredEvent( BigInt.fromI64(1), "ipfs://exampleshash", - BigInt.fromI64(10000) + BigInt.fromI64(10000), ); handleClaimStored(claimStoredEvent); }); @@ -43,13 +43,13 @@ describe("Describe entity assertions", () => { "Claim", claimId, "creator", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a" + "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", ); assert.fieldEquals( "Claim", claimId, "owner", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a" + "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", ); assert.fieldEquals("Claim", claimId, "totalUnits", "10000"); }); diff --git a/graph/tests/hypercert-trader-utils.ts b/graph/tests/hypercert-trader-utils.ts new file mode 100644 index 00000000..74ee37c1 --- /dev/null +++ b/graph/tests/hypercert-trader-utils.ts @@ -0,0 +1,261 @@ +import { + AdminChanged, + BeaconUpgraded, + Initialized, + OfferCancelled, + OfferCreated, + OwnershipTransferred, + Paused, + Trade, + Unpaused, + Upgraded, +} from "../generated/HypercertTrader/HypercertTrader"; +import { ethereum, Address, BigInt } from "@graphprotocol/graph-ts"; +import { newMockEvent } from "matchstick-as"; + +export const DEFAULT_TRADER_ADDRESS = Address.fromString( + "0x0000000000000000000000000000000000001337", +); + +export function createAdminChangedEvent( + previousAdmin: Address, + newAdmin: Address, +): AdminChanged { + let adminChangedEvent = changetype(newMockEvent()); + + adminChangedEvent.parameters = new Array(); + + adminChangedEvent.parameters.push( + new ethereum.EventParam( + "previousAdmin", + ethereum.Value.fromAddress(previousAdmin), + ), + ); + adminChangedEvent.parameters.push( + new ethereum.EventParam("newAdmin", ethereum.Value.fromAddress(newAdmin)), + ); + + return adminChangedEvent; +} + +export function createBeaconUpgradedEvent(beacon: Address): BeaconUpgraded { + let beaconUpgradedEvent = changetype(newMockEvent()); + + beaconUpgradedEvent.parameters = new Array(); + + beaconUpgradedEvent.parameters.push( + new ethereum.EventParam("beacon", ethereum.Value.fromAddress(beacon)), + ); + + return beaconUpgradedEvent; +} + +export function createInitializedEvent(version: i32): Initialized { + let initializedEvent = changetype(newMockEvent()); + + initializedEvent.parameters = new Array(); + + initializedEvent.parameters.push( + new ethereum.EventParam( + "version", + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(version)), + ), + ); + + return initializedEvent; +} + +export function createOfferCancelledEvent( + creator: Address, + hypercertContract: Address, + fractionID: BigInt, + offerID: BigInt, +): OfferCancelled { + let offerCancelledEvent = changetype(newMockEvent()); + + offerCancelledEvent.parameters = new Array(); + + offerCancelledEvent.parameters.push( + new ethereum.EventParam("creator", ethereum.Value.fromAddress(creator)), + ); + offerCancelledEvent.parameters.push( + new ethereum.EventParam( + "hypercertContract", + ethereum.Value.fromAddress(hypercertContract), + ), + ); + offerCancelledEvent.parameters.push( + new ethereum.EventParam( + "fractionID", + ethereum.Value.fromUnsignedBigInt(fractionID), + ), + ); + offerCancelledEvent.parameters.push( + new ethereum.EventParam( + "offerID", + ethereum.Value.fromUnsignedBigInt(offerID), + ), + ); + + offerCancelledEvent.address = DEFAULT_TRADER_ADDRESS; + + return offerCancelledEvent; +} + +export function createOfferCreatedEvent( + offerer: Address, + hypercertContract: Address, + fractionID: BigInt, + offerID: BigInt, +): OfferCreated { + let offerCreatedEvent = changetype(newMockEvent()); + + offerCreatedEvent.parameters = new Array(); + + offerCreatedEvent.parameters.push( + new ethereum.EventParam("offerer", ethereum.Value.fromAddress(offerer)), + ); + offerCreatedEvent.parameters.push( + new ethereum.EventParam( + "hypercertContract", + ethereum.Value.fromAddress(hypercertContract), + ), + ); + offerCreatedEvent.parameters.push( + new ethereum.EventParam( + "fractionID", + ethereum.Value.fromUnsignedBigInt(fractionID), + ), + ); + offerCreatedEvent.parameters.push( + new ethereum.EventParam( + "offerID", + ethereum.Value.fromUnsignedBigInt(offerID), + ), + ); + + offerCreatedEvent.address = DEFAULT_TRADER_ADDRESS; + + return offerCreatedEvent; +} + +export function createOwnershipTransferredEvent( + previousOwner: Address, + newOwner: Address, +): OwnershipTransferred { + let ownershipTransferredEvent = changetype( + newMockEvent(), + ); + + ownershipTransferredEvent.parameters = new Array(); + + ownershipTransferredEvent.parameters.push( + new ethereum.EventParam( + "previousOwner", + ethereum.Value.fromAddress(previousOwner), + ), + ); + ownershipTransferredEvent.parameters.push( + new ethereum.EventParam("newOwner", ethereum.Value.fromAddress(newOwner)), + ); + + return ownershipTransferredEvent; +} + +export function createPausedEvent(account: Address): Paused { + let pausedEvent = changetype(newMockEvent()); + + pausedEvent.parameters = new Array(); + + pausedEvent.parameters.push( + new ethereum.EventParam("account", ethereum.Value.fromAddress(account)), + ); + + return pausedEvent; +} + +export function createTradeEvent( + seller: Address, + buyer: Address, + hypercertContract: Address, + fractionID: BigInt, + unitsBought: BigInt, + buyToken: Address, + tokenAmountPerUnit: BigInt, + offerID: BigInt, +): Trade { + let tradeEvent = changetype(newMockEvent()); + + tradeEvent.parameters = new Array(); + + tradeEvent.parameters.push( + new ethereum.EventParam("seller", ethereum.Value.fromAddress(seller)), + ); + tradeEvent.parameters.push( + new ethereum.EventParam("buyer", ethereum.Value.fromAddress(buyer)), + ); + tradeEvent.parameters.push( + new ethereum.EventParam( + "hypercertContract", + ethereum.Value.fromAddress(hypercertContract), + ), + ); + tradeEvent.parameters.push( + new ethereum.EventParam( + "fractionID", + ethereum.Value.fromUnsignedBigInt(fractionID), + ), + ); + tradeEvent.parameters.push( + new ethereum.EventParam( + "unitsBought", + ethereum.Value.fromUnsignedBigInt(unitsBought), + ), + ); + tradeEvent.parameters.push( + new ethereum.EventParam("buyToken", ethereum.Value.fromAddress(buyToken)), + ); + tradeEvent.parameters.push( + new ethereum.EventParam( + "tokenAmountPerUnit", + ethereum.Value.fromUnsignedBigInt(tokenAmountPerUnit), + ), + ); + tradeEvent.parameters.push( + new ethereum.EventParam( + "offerID", + ethereum.Value.fromUnsignedBigInt(offerID), + ), + ); + + tradeEvent.address = DEFAULT_TRADER_ADDRESS; + + return tradeEvent; +} + +export function createUnpausedEvent(account: Address): Unpaused { + let unpausedEvent = changetype(newMockEvent()); + + unpausedEvent.parameters = new Array(); + + unpausedEvent.parameters.push( + new ethereum.EventParam("account", ethereum.Value.fromAddress(account)), + ); + + return unpausedEvent; +} + +export function createUpgradedEvent(implementation: Address): Upgraded { + let upgradedEvent = changetype(newMockEvent()); + + upgradedEvent.parameters = new Array(); + + upgradedEvent.parameters.push( + new ethereum.EventParam( + "implementation", + ethereum.Value.fromAddress(implementation), + ), + ); + + return upgradedEvent; +} diff --git a/graph/tests/hypercert-trader.test.ts b/graph/tests/hypercert-trader.test.ts new file mode 100644 index 00000000..691053dc --- /dev/null +++ b/graph/tests/hypercert-trader.test.ts @@ -0,0 +1,63 @@ +import { handleOfferCreated } from "../src/hypercert-trader"; +import { + DEFAULT_TRADER_ADDRESS, + createOfferCreatedEvent, +} from "./hypercert-trader-utils"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { + assert, + describe, + test, + clearStore, + beforeAll, + afterAll, + createMockedFunction, +} from "matchstick-as/assembly/index"; + +// Tests structure (matchstick-as >=0.5.0) +// https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0 + +describe("Describe entity assertions", () => { + beforeAll(() => { + createMockedFunction( + DEFAULT_TRADER_ADDRESS, + "offers", + "offers(uint256):(address,address,uint256,uint256,uint256,uint256,uint8,uint8)", + ) + .withArgs([ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1))]) + .returns([ + ethereum.Value.fromAddress( + Address.fromString("0x0000000000000000000000000000000000000003"), + ), + ethereum.Value.fromAddress( + Address.fromString("0x0000000000000000000000000000000000000004"), + ), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ]); + }); + + afterAll(() => { + clearStore(); + }); + + test("Offer created and stored", () => { + assert.entityCount("Offer", 0); + + // Create an OfferCreated event + let offerCreatedEvent = createOfferCreatedEvent( + Address.fromString("0x0000000000000000000000000000000000000001"), + Address.fromString("0x0000000000000000000000000000000000000002"), + BigInt.fromI32(1), + BigInt.fromI32(1), + ); + + handleOfferCreated(offerCreatedEvent); + + assert.entityCount("Offer", 1); + }); +}); From e27a63f8af4dab76d3494ccc597b8e409b43bb92 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Wed, 6 Sep 2023 23:35:35 +0200 Subject: [PATCH 07/49] feat(tokens): surface accepted tokens (#1065) * feat(tokens): surface accepted tokens * fix(tokens): acceptedTokens test and fix --- contracts/.openzeppelin/goerli.json | 275 +++++++++++++++++- contracts/src/HypercertTrader.sol | 4 + .../test/foundry/HypercertTrader.admin.t.sol | 4 - .../test/foundry/HypercertTrader.offers.t.sol | 6 +- .../test/foundry/HypercertTrader.sales.t.sol | 4 - .../api/contracts/HypercertTrader.md | 18 ++ graph/abis/HypercertTrader.json | 254 ++++++++++++++-- .../HypercertTrader/HypercertTrader.ts | 79 +++++ graph/generated/schema.ts | 56 ++++ graph/package.json | 2 +- graph/schema.graphql | 3 + graph/src/utils.ts | 27 +- graph/tests/hypercert-trader.test.ts | 51 ++-- 13 files changed, 708 insertions(+), 75 deletions(-) diff --git a/contracts/.openzeppelin/goerli.json b/contracts/.openzeppelin/goerli.json index abb0c675..4058c77b 100644 --- a/contracts/.openzeppelin/goerli.json +++ b/contracts/.openzeppelin/goerli.json @@ -5485,7 +5485,7 @@ "label": "offers", "offset": 0, "slot": "252", - "type": "t_mapping(t_uint256,t_struct(Offer)7990_storage)", + "type": "t_mapping(t_uint256,t_struct(Offer)2510_storage)", "contract": "HypercertTrader", "src": "src/HypercertTrader.sol:37" }, @@ -5511,7 +5511,7 @@ "label": "address", "numberOfBytes": "20" }, - "t_array(t_struct(AcceptedToken)8002_storage)dyn_storage": { + "t_array(t_struct(AcceptedToken)2522_storage)dyn_storage": { "label": "struct IHypercertTrader.AcceptedToken[]", "numberOfBytes": "32" }, @@ -5531,7 +5531,7 @@ "label": "bool", "numberOfBytes": "1" }, - "t_enum(OfferStatus)7997": { + "t_enum(OfferStatus)2517": { "label": "enum IHypercertTrader.OfferStatus", "members": [ "Open", @@ -5540,7 +5540,7 @@ ], "numberOfBytes": "1" }, - "t_enum(OfferType)7993": { + "t_enum(OfferType)2513": { "label": "enum IHypercertTrader.OfferType", "members": [ "Units", @@ -5552,7 +5552,7 @@ "label": "mapping(address => mapping(uint256 => uint256))", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Offer)7990_storage)": { + "t_mapping(t_uint256,t_struct(Offer)2510_storage)": { "label": "mapping(uint256 => struct IHypercertTrader.Offer)", "numberOfBytes": "32" }, @@ -5560,7 +5560,7 @@ "label": "mapping(uint256 => uint256)", "numberOfBytes": "32" }, - "t_struct(AcceptedToken)8002_storage": { + "t_struct(AcceptedToken)2522_storage": { "label": "struct IHypercertTrader.AcceptedToken", "members": [ { @@ -5578,7 +5578,7 @@ ], "numberOfBytes": "64" }, - "t_struct(Offer)7990_storage": { + "t_struct(Offer)2510_storage": { "label": "struct IHypercertTrader.Offer", "members": [ { @@ -5619,19 +5619,274 @@ }, { "label": "offerType", - "type": "t_enum(OfferType)7993", + "type": "t_enum(OfferType)2513", "offset": 0, "slot": "6" }, { "label": "status", - "type": "t_enum(OfferStatus)7997", + "type": "t_enum(OfferStatus)2517", "offset": 1, "slot": "6" }, { "label": "acceptedTokens", - "type": "t_array(t_struct(AcceptedToken)8002_storage)dyn_storage", + "type": "t_array(t_struct(AcceptedToken)2522_storage)dyn_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "c448a5dca6b776aedb55eb5857ea7c6a03d1ccd3ff709786879396d71bf7dbb2": { + "address": "0x038c990018b9Aab4aA2496E592E668EAD77aF72B", + "txHash": "0xe07f42a41b70affd1fdd08ce8011f55a35b0e62a9ef67d0b5c4daa04b6028f60", + "layout": { + "solcVersion": "0.8.16", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_paused", + "offset": 0, + "slot": "101", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "201", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol:107" + }, + { + "label": "totalUnitsForSale", + "offset": 0, + "slot": "251", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:36" + }, + { + "label": "offers", + "offset": 0, + "slot": "252", + "type": "t_mapping(t_uint256,t_struct(Offer)8003_storage)", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:37" + }, + { + "label": "_offerCounter", + "offset": 0, + "slot": "253", + "type": "t_uint256", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "254", + "type": "t_array(t_uint256)27_storage", + "contract": "HypercertTrader", + "src": "src/HypercertTrader.sol:392" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(AcceptedToken)8015_storage)dyn_storage": { + "label": "struct IHypercertTrader.AcceptedToken[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)27_storage": { + "label": "uint256[27]", + "numberOfBytes": "864" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_enum(OfferStatus)8010": { + "label": "enum IHypercertTrader.OfferStatus", + "members": [ + "Open", + "Fulfilled", + "Cancelled" + ], + "numberOfBytes": "1" + }, + "t_enum(OfferType)8006": { + "label": "enum IHypercertTrader.OfferType", + "members": [ + "Units", + "Fraction" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { + "label": "mapping(address => mapping(uint256 => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Offer)8003_storage)": { + "label": "mapping(uint256 => struct IHypercertTrader.Offer)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(AcceptedToken)8015_storage": { + "label": "struct IHypercertTrader.AcceptedToken", + "members": [ + { + "label": "token", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "minimumAmountPerUnit", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Offer)8003_storage": { + "label": "struct IHypercertTrader.Offer", + "members": [ + { + "label": "offerer", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "hypercertContract", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "fractionID", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "unitsAvailable", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "minUnitsPerTrade", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "maxUnitsPerTrade", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "offerType", + "type": "t_enum(OfferType)8006", + "offset": 0, + "slot": "6" + }, + { + "label": "status", + "type": "t_enum(OfferStatus)8010", + "offset": 1, + "slot": "6" + }, + { + "label": "acceptedTokens", + "type": "t_array(t_struct(AcceptedToken)8015_storage)dyn_storage", "offset": 0, "slot": "7" } diff --git a/contracts/src/HypercertTrader.sol b/contracts/src/HypercertTrader.sol index dfc08c1a..7f9aae3f 100644 --- a/contracts/src/HypercertTrader.sol +++ b/contracts/src/HypercertTrader.sol @@ -46,6 +46,10 @@ contract HypercertTrader is IHypercertTrader, Initializable, OwnableUpgradeable, __UUPSUpgradeable_init(); } + function getOffer(uint256 offerID) external view returns (Offer memory) { + return offers[offerID]; + } + /** * @dev Creates a new offer to sell Hypercert tokens. * @param hypercertContract The address of the Hypercert token contract. diff --git a/contracts/test/foundry/HypercertTrader.admin.t.sol b/contracts/test/foundry/HypercertTrader.admin.t.sol index 4cf645c6..3b7ee0eb 100644 --- a/contracts/test/foundry/HypercertTrader.admin.t.sol +++ b/contracts/test/foundry/HypercertTrader.admin.t.sol @@ -24,10 +24,6 @@ contract HypercertTraderHelper is HypercertTrader { HypercertMinter public hypercertMinter = new HypercertMinter(); - function getOffer(uint256 key) external view returns (Offer memory) { - return offers[key]; - } - function getOfferCount() external view returns (uint256) { return _offerCounter; } diff --git a/contracts/test/foundry/HypercertTrader.offers.t.sol b/contracts/test/foundry/HypercertTrader.offers.t.sol index 71c09133..6901b314 100644 --- a/contracts/test/foundry/HypercertTrader.offers.t.sol +++ b/contracts/test/foundry/HypercertTrader.offers.t.sol @@ -23,10 +23,6 @@ contract HypercertTraderHelper is HypercertTrader { HypercertMinter public hypercertMinter = new HypercertMinter(); - function getOffer(uint256 key) external view returns (Offer memory) { - return offers[key]; - } - function getOfferCount() external view returns (uint256) { return _offerCounter; } @@ -39,7 +35,7 @@ contract HypercertTraderHelper is HypercertTrader { uint256 minUnitsPerTrade, uint256 maxUnitsPerTrade, AcceptedToken[] memory acceptedTokens - ) external { + ) external payable { _validateOffer( offerer, hypercertContract, diff --git a/contracts/test/foundry/HypercertTrader.sales.t.sol b/contracts/test/foundry/HypercertTrader.sales.t.sol index c086fdd4..07c0216a 100644 --- a/contracts/test/foundry/HypercertTrader.sales.t.sol +++ b/contracts/test/foundry/HypercertTrader.sales.t.sol @@ -24,10 +24,6 @@ contract HypercertTraderHelper is HypercertTrader, PRBTest, StdCheats, StdUtils HypercertMinter public hypercertMinter = new HypercertMinter(); - function getOffer(uint256 key) external view returns (Offer memory) { - return offers[key]; - } - function getOfferCount() external view returns (uint256) { return _offerCounter; } diff --git a/docs/docs/developer/api/contracts/HypercertTrader.md b/docs/docs/developer/api/contracts/HypercertTrader.md index 4a5c9b4e..e31e8840 100644 --- a/docs/docs/developer/api/contracts/HypercertTrader.md +++ b/docs/docs/developer/api/contracts/HypercertTrader.md @@ -87,6 +87,24 @@ function createOffer(address hypercertContract, uint256 fractionID, uint256 unit | ------- | ------- | ----------- | | offerID | uint256 | undefined | +### getOffer + +```solidity +function getOffer(uint256 offerID) external view returns (struct IHypercertTrader.Offer) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| offerID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------- | ----------- | +| \_0 | IHypercertTrader.Offer | undefined | + ### initialize ```solidity diff --git a/graph/abis/HypercertTrader.json b/graph/abis/HypercertTrader.json index 4851032d..1f114e5e 100644 --- a/graph/abis/HypercertTrader.json +++ b/graph/abis/HypercertTrader.json @@ -1,16 +1,36 @@ [ - { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, { - "inputs": [{ "internalType": "string", "name": "", "type": "string" }], + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], "name": "InvalidBuy", "type": "error" }, { - "inputs": [{ "internalType": "string", "name": "", "type": "string" }], + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], "name": "InvalidOffer", "type": "error" }, - { "inputs": [], "name": "NotAllowed", "type": "error" }, + { + "inputs": [], + "name": "NotAllowed", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -233,14 +253,26 @@ }, { "inputs": [ - { "internalType": "address", "name": "recipient", "type": "address" }, - { "internalType": "uint256[]", "name": "offerIDs", "type": "uint256[]" }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "offerIDs", + "type": "uint256[]" + }, { "internalType": "uint256[]", "name": "unitAmounts", "type": "uint256[]" }, - { "internalType": "address[]", "name": "buyTokens", "type": "address[]" }, + { + "internalType": "address[]", + "name": "buyTokens", + "type": "address[]" + }, { "internalType": "uint256[]", "name": "tokenAmountsPerUnit", @@ -254,10 +286,26 @@ }, { "inputs": [ - { "internalType": "address", "name": "recipient", "type": "address" }, - { "internalType": "uint256", "name": "offerID", "type": "uint256" }, - { "internalType": "uint256", "name": "unitAmount", "type": "uint256" }, - { "internalType": "address", "name": "buyToken", "type": "address" }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "offerID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unitAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "buyToken", + "type": "address" + }, { "internalType": "uint256", "name": "tokenAmountPerUnit", @@ -271,7 +319,11 @@ }, { "inputs": [ - { "internalType": "uint256", "name": "offerID", "type": "uint256" } + { + "internalType": "uint256", + "name": "offerID", + "type": "uint256" + } ], "name": "cancelOffer", "outputs": [], @@ -285,8 +337,16 @@ "name": "hypercertContract", "type": "address" }, - { "internalType": "uint256", "name": "fractionID", "type": "uint256" }, - { "internalType": "uint256", "name": "unitsForSale", "type": "uint256" }, + { + "internalType": "uint256", + "name": "fractionID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unitsForSale", + "type": "uint256" + }, { "internalType": "uint256", "name": "minUnitsPerTrade", @@ -299,7 +359,11 @@ }, { "components": [ - { "internalType": "address", "name": "token", "type": "address" }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, { "internalType": "uint256", "name": "minimumAmountPerUnit", @@ -313,11 +377,93 @@ ], "name": "createOffer", "outputs": [ - { "internalType": "uint256", "name": "offerID", "type": "uint256" } + { + "internalType": "uint256", + "name": "offerID", + "type": "uint256" + } ], "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offerID", + "type": "uint256" + } + ], + "name": "getOffer", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "offerer", + "type": "address" + }, + { + "internalType": "address", + "name": "hypercertContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fractionID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unitsAvailable", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minUnitsPerTrade", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxUnitsPerTrade", + "type": "uint256" + }, + { + "internalType": "enum IHypercertTrader.OfferType", + "name": "offerType", + "type": "uint8" + }, + { + "internalType": "enum IHypercertTrader.OfferStatus", + "name": "status", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minimumAmountPerUnit", + "type": "uint256" + } + ], + "internalType": "struct IHypercertTrader.AcceptedToken[]", + "name": "acceptedTokens", + "type": "tuple[]" + } + ], + "internalType": "struct IHypercertTrader.Offer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "initialize", @@ -326,16 +472,30 @@ "type": "function" }, { - "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "name": "offers", "outputs": [ - { "internalType": "address", "name": "offerer", "type": "address" }, + { + "internalType": "address", + "name": "offerer", + "type": "address" + }, { "internalType": "address", "name": "hypercertContract", "type": "address" }, - { "internalType": "uint256", "name": "fractionID", "type": "uint256" }, + { + "internalType": "uint256", + "name": "fractionID", + "type": "uint256" + }, { "internalType": "uint256", "name": "unitsAvailable", @@ -368,7 +528,13 @@ { "inputs": [], "name": "owner", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], "stateMutability": "view", "type": "function" }, @@ -382,14 +548,26 @@ { "inputs": [], "name": "paused", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "proxiableUUID", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], "stateMutability": "view", "type": "function" }, @@ -402,17 +580,35 @@ }, { "inputs": [ - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "uint256", "name": "", "type": "uint256" } + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } ], "name": "totalUnitsForSale", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [ - { "internalType": "address", "name": "newOwner", "type": "address" } + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } ], "name": "transferOwnership", "outputs": [], @@ -446,7 +642,11 @@ "name": "newImplementation", "type": "address" }, - { "internalType": "bytes", "name": "data", "type": "bytes" } + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } ], "name": "upgradeToAndCall", "outputs": [], diff --git a/graph/generated/HypercertTrader/HypercertTrader.ts b/graph/generated/HypercertTrader/HypercertTrader.ts index 58e780d5..36aef88f 100644 --- a/graph/generated/HypercertTrader/HypercertTrader.ts +++ b/graph/generated/HypercertTrader/HypercertTrader.ts @@ -250,6 +250,54 @@ export class Upgraded__Params { } } +export class HypercertTrader__getOfferResultValue0Struct extends ethereum.Tuple { + get offerer(): Address { + return this[0].toAddress(); + } + + get hypercertContract(): Address { + return this[1].toAddress(); + } + + get fractionID(): BigInt { + return this[2].toBigInt(); + } + + get unitsAvailable(): BigInt { + return this[3].toBigInt(); + } + + get minUnitsPerTrade(): BigInt { + return this[4].toBigInt(); + } + + get maxUnitsPerTrade(): BigInt { + return this[5].toBigInt(); + } + + get offerType(): i32 { + return this[6].toI32(); + } + + get status(): i32 { + return this[7].toI32(); + } + + get acceptedTokens(): Array { + return this[8].toTupleArray(); + } +} + +export class HypercertTrader__getOfferResultValue0AcceptedTokensStruct extends ethereum.Tuple { + get token(): Address { + return this[0].toAddress(); + } + + get minimumAmountPerUnit(): BigInt { + return this[1].toBigInt(); + } +} + export class HypercertTrader__offersResult { value0: Address; value1: Address; @@ -337,6 +385,37 @@ export class HypercertTrader extends ethereum.SmartContract { return new HypercertTrader("HypercertTrader", address); } + getOffer(offerID: BigInt): HypercertTrader__getOfferResultValue0Struct { + let result = super.call( + "getOffer", + "getOffer(uint256):((address,address,uint256,uint256,uint256,uint256,uint8,uint8,(address,uint256)[]))", + [ethereum.Value.fromUnsignedBigInt(offerID)], + ); + + return changetype( + result[0].toTuple(), + ); + } + + try_getOffer( + offerID: BigInt, + ): ethereum.CallResult { + let result = super.tryCall( + "getOffer", + "getOffer(uint256):((address,address,uint256,uint256,uint256,uint256,uint8,uint8,(address,uint256)[]))", + [ethereum.Value.fromUnsignedBigInt(offerID)], + ); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue( + changetype( + value[0].toTuple(), + ), + ); + } + offers(param0: BigInt): HypercertTrader__offersResult { let result = super.call( "offers", diff --git a/graph/generated/schema.ts b/graph/generated/schema.ts index de8e18a1..cf492abf 100644 --- a/graph/generated/schema.ts +++ b/graph/generated/schema.ts @@ -331,6 +331,10 @@ export class ClaimToken extends Entity { set units(value: BigInt) { this.set("units", Value.fromBigInt(value)); } + + get offers(): OfferLoader { + return new OfferLoader("ClaimToken", this.get("id")!.toString(), "offers"); + } } export class Token extends Entity { @@ -384,6 +388,40 @@ export class Token extends Entity { set name(value: string) { this.set("name", Value.fromString(value)); } + + get symbol(): string | null { + let value = this.get("symbol"); + if (!value || value.kind == ValueKind.NULL) { + return null; + } else { + return value.toString(); + } + } + + set symbol(value: string | null) { + if (!value) { + this.unset("symbol"); + } else { + this.set("symbol", Value.fromString(value)); + } + } + + get decimals(): BigInt | null { + let value = this.get("decimals"); + if (!value || value.kind == ValueKind.NULL) { + return null; + } else { + return value.toBigInt(); + } + } + + set decimals(value: BigInt | null) { + if (!value) { + this.unset("decimals"); + } else { + this.set("decimals", Value.fromBigInt(value)); + } + } } export class AcceptedToken extends Entity { @@ -689,3 +727,21 @@ export class Trade extends Entity { this.set("amountPerUnit", Value.fromBigInt(value)); } } + +export class OfferLoader extends Entity { + _entity: string; + _field: string; + _id: string; + + constructor(entity: string, id: string, field: string) { + super(); + this._entity = entity; + this._id = id; + this._field = field; + } + + load(): Offer[] { + let value = store.loadRelated(this._entity, this._id, this._field); + return changetype(value); + } +} diff --git a/graph/package.json b/graph/package.json index e8f03fa3..8ff42396 100644 --- a/graph/package.json +++ b/graph/package.json @@ -24,7 +24,7 @@ "test": "graph test" }, "dependencies": { - "@graphprotocol/graph-cli": "0.56.0" + "@graphprotocol/graph-cli": "0.57.0" }, "devDependencies": { "@graphprotocol/graph-ts": "0.31.0", diff --git a/graph/schema.graphql b/graph/schema.graphql index e42546a0..d6ec32ef 100644 --- a/graph/schema.graphql +++ b/graph/schema.graphql @@ -22,11 +22,14 @@ type ClaimToken @entity { claim: Claim! owner: Bytes! units: BigInt! + offers: [Offer!] @derivedFrom(field: "fractionID") } type Token @entity { id: String! name: String! + symbol: String + decimals: BigInt } type AcceptedToken @entity { diff --git a/graph/src/utils.ts b/graph/src/utils.ts index 4511dcaa..e15b9054 100644 --- a/graph/src/utils.ts +++ b/graph/src/utils.ts @@ -110,6 +110,7 @@ export function getOrCreateToken(token: Address): Token { export function getOrCreateAcceptedToken( offerID: BigInt, token: Address, + minimumAmountPerUnit: BigInt, ): AcceptedToken { const _acceptedTokenID = offerID .toHexString() @@ -119,11 +120,12 @@ export function getOrCreateAcceptedToken( if (acceptedToken == null) { acceptedToken = new AcceptedToken(_acceptedTokenID); acceptedToken.token = getOrCreateToken(token).id; - acceptedToken.minimumAmountPerUnit = BigInt.fromI32(0); + acceptedToken.minimumAmountPerUnit = minimumAmountPerUnit; acceptedToken.accepted = true; acceptedToken.save(); } + log.debug("Returning acceptedToken: {}", [_acceptedTokenID]); return acceptedToken; } @@ -142,16 +144,27 @@ export function getOrCreateOffer( let offer = Offer.load(_offerID); if (offer == null) { - const offerOnChain = _traderContract.offers(offerID); + const offerOnChain = _traderContract.getOffer(offerID); offer = new Offer(_offerID); offer.fractionID = _fractionID; - offer.unitsAvailable = offerOnChain.getUnitsAvailable(); - offer.minUnitsPerTrade = offerOnChain.getMinUnitsPerTrade(); - offer.maxUnitsPerTrade = offerOnChain.getMaxUnitsPerTrade(); + offer.unitsAvailable = offerOnChain.unitsAvailable; + offer.minUnitsPerTrade = offerOnChain.minUnitsPerTrade; + offer.maxUnitsPerTrade = offerOnChain.maxUnitsPerTrade; + offer.acceptedTokens = []; offer.status = "Open"; - offer.acceptedTokens = [getOrCreateAcceptedToken(offerID, ZERO_ADDRESS).id]; - offer.save(); + + for (let i = 0; i < offerOnChain.acceptedTokens.length; i++) { + const _acceptedToken = offerOnChain.acceptedTokens[i]; + const parsedToken = getOrCreateAcceptedToken( + offerID, + _acceptedToken.token, + _acceptedToken.minimumAmountPerUnit, + ); + offer.acceptedTokens.push(parsedToken.id.toString()); + } + log.debug("Created offerID: {}", [_offerID]); + offer.save(); } return offer; diff --git a/graph/tests/hypercert-trader.test.ts b/graph/tests/hypercert-trader.test.ts index 691053dc..51230b74 100644 --- a/graph/tests/hypercert-trader.test.ts +++ b/graph/tests/hypercert-trader.test.ts @@ -1,9 +1,10 @@ import { handleOfferCreated } from "../src/hypercert-trader"; +import { ZERO_ADDRESS } from "../src/utils"; import { DEFAULT_TRADER_ADDRESS, createOfferCreatedEvent, } from "./hypercert-trader-utils"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Address, BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts"; import { assert, describe, @@ -19,26 +20,42 @@ import { describe("Describe entity assertions", () => { beforeAll(() => { + let acceptedToken: Array = [ + ethereum.Value.fromAddress( + Address.fromString("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7"), + ), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ]; + + let tuple = changetype(acceptedToken); + let tupleValue = ethereum.Value.fromTupleArray([tuple]); + + const returnValues = [ + ethereum.Value.fromAddress( + Address.fromString("0x0000000000000000000000000000000000000003"), + ), + ethereum.Value.fromAddress( + Address.fromString("0x0000000000000000000000000000000000000004"), + ), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), + ethereum.Value.fromTupleArray([tuple]), + ]; + + let returnValueTuple = changetype(returnValues); + let returnValue = ethereum.Value.fromTuple(returnValueTuple); + createMockedFunction( DEFAULT_TRADER_ADDRESS, - "offers", - "offers(uint256):(address,address,uint256,uint256,uint256,uint256,uint8,uint8)", + "getOffer", + "getOffer(uint256):((address,address,uint256,uint256,uint256,uint256,uint8,uint8,(address,uint256)[]))", ) .withArgs([ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1))]) - .returns([ - ethereum.Value.fromAddress( - Address.fromString("0x0000000000000000000000000000000000000003"), - ), - ethereum.Value.fromAddress( - Address.fromString("0x0000000000000000000000000000000000000004"), - ), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ]); + .returns([returnValue]); }); afterAll(() => { From e95571cc8df0c6336b9e0bcb87b830af32b0f2d1 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Thu, 7 Sep 2023 00:31:41 +0200 Subject: [PATCH 08/49] Feat/accepted tokens (#1066) * feat(tokens): surface accepted tokens * fix(tokens): acceptedTokens test and fix * chore(address): update trader address graph * fix(import): add bigint to import --- graph/src/hypercert-trader.ts | 8 ++++++-- graph/subgraph.yaml | 2 +- graph/tests/.latest.json | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/graph/src/hypercert-trader.ts b/graph/src/hypercert-trader.ts index ac19cad3..5c06f969 100644 --- a/graph/src/hypercert-trader.ts +++ b/graph/src/hypercert-trader.ts @@ -5,7 +5,7 @@ import { } from "../generated/HypercertTrader/HypercertTrader"; import { Trade } from "../generated/schema"; import { getOrCreateOffer, getOrCreateOfferByID } from "./utils"; -import { log } from "@graphprotocol/graph-ts"; +import { log, BigInt } from "@graphprotocol/graph-ts"; export function handleOfferCancelled(event: OfferCancelledEvent): void { const offer = getOrCreateOfferByID( @@ -31,7 +31,6 @@ export function handleOfferCreated(event: OfferCreatedEvent): void { event.params.offerID, ); - // TODO get accepted tokens offer.save(); } @@ -65,5 +64,10 @@ export function handleTrade(event: TradeEvent): void { trade.offerID = offer.id; } + offer.unitsAvailable = offer.unitsAvailable.minus(event.params.unitsBought); + if (offer.unitsAvailable.equals(BigInt.fromI32(0))) { + offer.status = "Fulfilled"; + } + trade.save(); } diff --git a/graph/subgraph.yaml b/graph/subgraph.yaml index 788e2dde..a83eb604 100644 --- a/graph/subgraph.yaml +++ b/graph/subgraph.yaml @@ -48,7 +48,7 @@ dataSources: name: HypercertTrader network: goerli source: - address: "0xFf3F27c6132c30d1098b97FfeC05C3150dA90432" + address: "0x689587461AA3103D3D7975c5e4B352Ab711C14C2" abi: HypercertTrader mapping: kind: ethereum/events diff --git a/graph/tests/.latest.json b/graph/tests/.latest.json index 1e6a7350..e3f41cde 100644 --- a/graph/tests/.latest.json +++ b/graph/tests/.latest.json @@ -1,4 +1,4 @@ { "version": "0.5.4", - "timestamp": 1693949703219 + "timestamp": 1694038457426 } From cf9da0a5278db43139e52a198d3547dc29a2f95a Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Thu, 7 Sep 2023 01:07:20 +0200 Subject: [PATCH 09/49] Feat/accepted tokens (#1067) * feat(tokens): surface accepted tokens * fix(tokens): acceptedTokens test and fix * chore(address): update trader address graph * fix(import): add bigint to import * fix(log): add logging to trader mapping --- graph/src/utils.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/graph/src/utils.ts b/graph/src/utils.ts index e15b9054..42b51fc5 100644 --- a/graph/src/utils.ts +++ b/graph/src/utils.ts @@ -99,11 +99,13 @@ export function getOrCreateToken(token: Address): Token { if (_token == null) { _token = new Token(_tokenID); - //TODO get token name + log.debug("Created Token: {}", [_tokenID]); _token.name = "Native"; _token.save(); } + log.debug("Returning Token: {}", [_tokenID]); + return _token; } @@ -119,6 +121,8 @@ export function getOrCreateAcceptedToken( if (acceptedToken == null) { acceptedToken = new AcceptedToken(_acceptedTokenID); + log.debug("Created acceptedToken: {}", [_acceptedTokenID]); + acceptedToken.token = getOrCreateToken(token).id; acceptedToken.minimumAmountPerUnit = minimumAmountPerUnit; acceptedToken.accepted = true; @@ -146,6 +150,8 @@ export function getOrCreateOffer( if (offer == null) { const offerOnChain = _traderContract.getOffer(offerID); offer = new Offer(_offerID); + log.debug("Created offer: {}", [_offerID]); + offer.fractionID = _fractionID; offer.unitsAvailable = offerOnChain.unitsAvailable; offer.minUnitsPerTrade = offerOnChain.minUnitsPerTrade; @@ -161,12 +167,18 @@ export function getOrCreateOffer( _acceptedToken.minimumAmountPerUnit, ); offer.acceptedTokens.push(parsedToken.id.toString()); + log.debug("Added accepted token to offer {} at place {}", [ + _offerID, + _acceptedToken.length.toString(), + ]); } log.debug("Created offerID: {}", [_offerID]); offer.save(); } + log.debug("Returning offer: {}", [_offerID]); + return offer; } From 0e8d6904d751101e3b91f37801c32c643abde7b3 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 23 Oct 2023 23:40:59 +0200 Subject: [PATCH 10/49] [Prod]:Deployed to Celo, updated Defender, version bumps for everyone (#1137) * Fix/package build (#1124) * chore(npm): sdk to workspace to stop link: * chore(npm): contracts in workspace, no link: * chore(bump): 0.8.7 * chore(bump): contracts 0.8.7 into sdk 0.8.8 * fix(ci): linting errors from updated ws * fix(doc): optimism chainId to 10 from 100 * chore(build): remove type module from package.json * chore(contracts): package sol files * chore(pack): add sol files to contracts package * chore(bump): contract 0.8.9 * chore(pack): exports setup * chore(pack): contracts dir in package * chore(pack): cleanup build scripts * chore(bump): contracts 0.8.10 * chore(pack): add all contracts for inheritence * chore(bump): contracts 0.8.11 * chore(bump): sdk 0.8.10 with updated contracts package * chore(bump): updated packages in frontend * chore(gha): run action on pr and push to develop * Feat/deploy to celo (#1135) * Add HC contracts to OpenZeppelin Defender (#1134) * Fix/package build (#1124) * chore(npm): sdk to workspace to stop link: * chore(npm): contracts in workspace, no link: * chore(bump): 0.8.7 * chore(bump): contracts 0.8.7 into sdk 0.8.8 * fix(ci): linting errors from updated ws * fix(doc): optimism chainId to 10 from 100 * chore(build): remove type module from package.json * chore(contracts): package sol files * chore(pack): add sol files to contracts package * chore(bump): contract 0.8.9 * chore(pack): exports setup * chore(pack): contracts dir in package * chore(pack): cleanup build scripts * chore(bump): contracts 0.8.10 * chore(pack): add all contracts for inheritence * chore(bump): contracts 0.8.11 * chore(bump): sdk 0.8.10 with updated contracts package * chore(bump): updated packages in frontend * chore(gha): run action on pr and push to develop * feat(defender): use hc packages in oz defender * feat(celo): graph deploy, sdk and defender config * chore(bump): SDK 0.8.14 Celo deployment * feat(celo): add celo support to frontend * chore(graph): fix turbo test flow * chore(graph): add comment to p.json * fix(gha): use pnpm cache in graph gha (#1138) --- .github/workflows/deploy-graph.yml | 2 +- README.md | 1 + contracts/.env.example | 2 + contracts/.openzeppelin/celo.json | 378 ++ contracts/contracts/AllowlistMinter.sol | 70 + contracts/contracts/HypercertMinter.sol | 229 + contracts/contracts/SemiFungible1155.sol | 433 ++ contracts/contracts/interfaces/IAllowlist.sol | 14 + .../contracts/interfaces/IHypercertToken.sol | 62 + contracts/contracts/libs/Errors.sol | 15 + contracts/hardhat.config.ts | 34 +- contracts/tasks/deploy.ts | 1 + defender/package.json | 2 +- defender/src/networks.ts | 6 + frontend/components/dapp-context.tsx | 21 +- frontend/package.json | 3 +- graph/networks.json | 6 + graph/package.json | 20 +- graph/subgraph.yaml | 6 +- graph/tests/.latest.json | 4 +- pnpm-lock.yaml | 5815 +++++++++-------- pnpm-workspace.yaml | 3 +- sdk/package.json | 2 +- sdk/src/constants.ts | 6 + sdk/src/types/client.ts | 2 +- sdk/src/utils/config.ts | 5 +- 26 files changed, 4290 insertions(+), 2852 deletions(-) create mode 100644 contracts/.openzeppelin/celo.json create mode 100644 contracts/contracts/AllowlistMinter.sol create mode 100644 contracts/contracts/HypercertMinter.sol create mode 100644 contracts/contracts/SemiFungible1155.sol create mode 100644 contracts/contracts/interfaces/IAllowlist.sol create mode 100644 contracts/contracts/interfaces/IHypercertToken.sol create mode 100644 contracts/contracts/libs/Errors.sol diff --git a/.github/workflows/deploy-graph.yml b/.github/workflows/deploy-graph.yml index b5ec5261..74727ea3 100644 --- a/.github/workflows/deploy-graph.yml +++ b/.github/workflows/deploy-graph.yml @@ -33,7 +33,7 @@ jobs: - name: Set up Node.js 18 uses: actions/setup-node@v3 with: - cache: "yarn" + cache: "pnpm" node-version: "18.x" - name: Install run: pnpm install --frozen-lockfile diff --git a/README.md b/README.md index d2bd54d3..d7eb1fad 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ For more details, check out our [website](https://hypercerts.org/). | -------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | Goerli | [0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07](https://goerli.etherscan.io/address/0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07) | [0x8CD35a62fF56A91485eBF97491612F1552dbc1c9](https://goerli.etherscan.io/address/0x8CD35a62fF56A91485eBF97491612F1552dbc1c9) | | Sepolia | [0xa16DFb32Eb140a6f3F2AC68f41dAd8c7e83C4941](https://goerli.etherscan.io/address/0xa16DFb32Eb140a6f3F2AC68f41dAd8c7e83C4941) | TBD | + | Celo | [0x16bA53B74c234C870c61EFC04cD418B8f2865959](https://celoscan.io/address/0x16bA53B74c234C870c61EFC04cD418B8f2865959) | TBD | | Optimism | [0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07](https://optimistic.etherscan.io/address/0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07) | [0x560adA72a80b4707e493cA8c3B7B7528930E7Be5](https://optimistic.etherscan.io/address/0x560adA72a80b4707e493cA8c3B7B7528930E7Be5) | - `/cors-proxy`: CORS proxy for Cloudflare Workers diff --git a/contracts/.env.example b/contracts/.env.example index 46bc688d..b7c57fac 100644 --- a/contracts/.env.example +++ b/contracts/.env.example @@ -1,5 +1,6 @@ # Deploy keys MNEMONIC="test test test test test test test test test test test junk" +MNEMONIC_CELO=="test test test test test test test test test test test junk" INFURA_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" ALCHEMY_OPTIMISM_URL="https://opt-mainnet.g.alchemy.com/v2/zzzzzzzzzzzzzzzzzzz" @@ -10,6 +11,7 @@ OPENZEPPELIN_SECRET_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" # Block explorer API keys ETHERSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" OPTIMISTIC_ETHERSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" +CELOSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" # Unused, ignore below POLYGONSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" diff --git a/contracts/.openzeppelin/celo.json b/contracts/.openzeppelin/celo.json new file mode 100644 index 00000000..2d9a5c85 --- /dev/null +++ b/contracts/.openzeppelin/celo.json @@ -0,0 +1,378 @@ +{ + "manifestVersion": "3.2", + "proxies": [ + { + "address": "0x16bA53B74c234C870c61EFC04cD418B8f2865959", + "txHash": "0x1b0d8fcde0a9ff343fa1c7eea5b8fe4432eb10731ebfeb5dfcb6fa3b2cec0046", + "kind": "uups" + } + ], + "impls": { + "31f9c6a26cf17ca4bb624cde3829d09c9a5a4a1d419afe174e7bd6d46cc5c0d9": { + "address": "0x620257e9301a813bE7CC5B75AAe8DDA3F6A926D2", + "txHash": "0x479853237255ea63bb7f1cadd7b72cc793444811a425cac2d6e10e9277ba4c18", + "layout": { + "solcVersion": "0.8.16", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_balances", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:25" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:28" + }, + { + "label": "_uri", + "offset": 0, + "slot": "103", + "type": "t_string_storage", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "104", + "type": "t_array(t_uint256)47_storage", + "contract": "ERC1155Upgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol:528" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1155BurnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol:52" + }, + { + "label": "_baseURI", + "offset": 0, + "slot": "201", + "type": "t_string_storage", + "contract": "ERC1155URIStorageUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol:27" + }, + { + "label": "_tokenURIs", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_uint256,t_string_storage)", + "contract": "ERC1155URIStorageUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol:30" + }, + { + "label": "__gap", + "offset": 0, + "slot": "203", + "type": "t_array(t_uint256)48_storage", + "contract": "ERC1155URIStorageUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol:77" + }, + { + "label": "_owner", + "offset": 0, + "slot": "251", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "__gap", + "offset": 0, + "slot": "301", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "351", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol:107" + }, + { + "label": "typeCounter", + "offset": 0, + "slot": "401", + "type": "t_uint256", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:27" + }, + { + "label": "owners", + "offset": 0, + "slot": "402", + "type": "t_mapping(t_uint256,t_address)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:38" + }, + { + "label": "creators", + "offset": 0, + "slot": "403", + "type": "t_mapping(t_uint256,t_address)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:41" + }, + { + "label": "tokenValues", + "offset": 0, + "slot": "404", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:44" + }, + { + "label": "maxIndex", + "offset": 0, + "slot": "405", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:47" + }, + { + "label": "__gap", + "offset": 0, + "slot": "406", + "type": "t_array(t_uint256)25_storage", + "contract": "SemiFungible1155", + "src": "src/SemiFungible1155.sol:432" + }, + { + "label": "merkleRoots", + "offset": 0, + "slot": "431", + "type": "t_mapping(t_uint256,t_bytes32)", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:17" + }, + { + "label": "hasBeenClaimed", + "offset": 0, + "slot": "432", + "type": "t_mapping(t_uint256,t_mapping(t_bytes32,t_bool))", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:18" + }, + { + "label": "maxUnits", + "offset": 0, + "slot": "433", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:19" + }, + { + "label": "minted", + "offset": 0, + "slot": "434", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "435", + "type": "t_array(t_uint256)26_storage", + "contract": "AllowlistMinter", + "src": "src/AllowlistMinter.sol:69" + }, + { + "label": "_paused", + "offset": 0, + "slot": "461", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "462", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol:116" + }, + { + "label": "typeRestrictions", + "offset": 0, + "slot": "511", + "type": "t_mapping(t_uint256,t_enum(TransferRestrictions)6761)", + "contract": "HypercertMinter", + "src": "src/HypercertMinter.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "512", + "type": "t_array(t_uint256)29_storage", + "contract": "HypercertMinter", + "src": "src/HypercertMinter.sol:228" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)25_storage": { + "label": "uint256[25]", + "numberOfBytes": "800" + }, + "t_array(t_uint256)26_storage": { + "label": "uint256[26]", + "numberOfBytes": "832" + }, + "t_array(t_uint256)29_storage": { + "label": "uint256[29]", + "numberOfBytes": "928" + }, + "t_array(t_uint256)47_storage": { + "label": "uint256[47]", + "numberOfBytes": "1504" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_enum(TransferRestrictions)6761": { + "label": "enum IHypercertToken.TransferRestrictions", + "members": [ + "AllowAll", + "DisallowAll", + "FromCreatorOnly" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_bytes32)": { + "label": "mapping(uint256 => bytes32)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_enum(TransferRestrictions)6761)": { + "label": "mapping(uint256 => enum IHypercertToken.TransferRestrictions)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_bytes32,t_bool))": { + "label": "mapping(uint256 => mapping(bytes32 => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_string_storage)": { + "label": "mapping(uint256 => string)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + } + } +} diff --git a/contracts/contracts/AllowlistMinter.sol b/contracts/contracts/AllowlistMinter.sol new file mode 100644 index 00000000..576b45ee --- /dev/null +++ b/contracts/contracts/AllowlistMinter.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +import { MerkleProofUpgradeable } from "oz-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol"; +import { IAllowlist } from "./interfaces/IAllowlist.sol"; + +import { Errors } from "./libs/Errors.sol"; + +/// @title Interface for hypercert token interactions +/// @author bitbeckers +/// @notice This interface declares the required functionality for a hypercert token +/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) +contract AllowlistMinter is IAllowlist { + event AllowlistCreated(uint256 tokenID, bytes32 root); + event LeafClaimed(uint256 tokenID, bytes32 leaf); + + mapping(uint256 => bytes32) internal merkleRoots; + mapping(uint256 => mapping(bytes32 => bool)) public hasBeenClaimed; + mapping(uint256 => uint256) internal maxUnits; + mapping(uint256 => uint256) internal minted; + + function isAllowedToClaim( + bytes32[] calldata proof, + uint256 claimID, + bytes32 leaf + ) external view returns (bool isAllowed) { + if (merkleRoots[claimID].length == 0) revert Errors.DoesNotExist(); + isAllowed = MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf); + } + + function _createAllowlist(uint256 claimID, bytes32 merkleRoot, uint256 units) internal { + if (merkleRoot == "" || units == 0) revert Errors.Invalid(); + if (merkleRoots[claimID] != "") revert Errors.DuplicateEntry(); + + merkleRoots[claimID] = merkleRoot; + maxUnits[claimID] = units; + emit AllowlistCreated(claimID, merkleRoot); + } + + function _processClaim(bytes32[] calldata proof, uint256 claimID, uint256 amount) internal { + if (merkleRoots[claimID].length == 0) revert Errors.DoesNotExist(); + + bytes32 leaf = _calculateLeaf(msg.sender, amount); + + if (hasBeenClaimed[claimID][leaf]) revert Errors.AlreadyClaimed(); + if ( + !MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf) || + (minted[claimID] + amount) > maxUnits[claimID] + ) revert Errors.Invalid(); + hasBeenClaimed[claimID][leaf] = true; + + emit LeafClaimed(claimID, leaf); + } + + function _calculateLeaf(address account, uint256 amount) internal pure returns (bytes32 leaf) { + leaf = keccak256(bytes.concat(keccak256(abi.encode(account, amount)))); + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + * Assuming 30 available slots (slots cost space, cost gas) + * 1. merkleRoots + * 2. hasBeenClaimed + * 3. maxUnits + * 4. minted + */ + uint256[26] private __gap; +} diff --git a/contracts/contracts/HypercertMinter.sol b/contracts/contracts/HypercertMinter.sol new file mode 100644 index 00000000..917c02c5 --- /dev/null +++ b/contracts/contracts/HypercertMinter.sol @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +import { IHypercertToken } from "./interfaces/IHypercertToken.sol"; +import { SemiFungible1155 } from "./SemiFungible1155.sol"; +import { AllowlistMinter } from "./AllowlistMinter.sol"; +import { PausableUpgradeable } from "oz-upgradeable/security/PausableUpgradeable.sol"; + +import { Errors } from "./libs/Errors.sol"; + +/// @title Contract for managing hypercert claims and whitelists +/// @author bitbeckers +/// @notice Implementation of the HypercertTokenInterface using { SemiFungible1155 } as underlying token. +/// @notice This contract supports whitelisted minting via { AllowlistMinter }. +/// @dev Wrapper contract to expose and chain functions. +contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, PausableUpgradeable { + // solhint-disable-next-line const-name-snakecase + string public constant name = "HypercertMinter"; + /// @dev from typeID to a transfer policy + mapping(uint256 => TransferRestrictions) internal typeRestrictions; + + /// INIT + + /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } + function initialize() public virtual initializer { + __SemiFungible1155_init(); + __Pausable_init(); + } + + /// EXTERNAL + + /// @notice Mint a semi-fungible token for the impact claim referenced via `uri` + /// @dev see {IHypercertToken} + function mintClaim( + address account, + uint256 units, + string memory _uri, + TransferRestrictions restrictions + ) external override whenNotPaused { + // This enables us to release this restriction in the future + if (msg.sender != account) revert Errors.NotAllowed(); + uint256 claimID = _mintNewTypeWithToken(account, units, _uri); + typeRestrictions[claimID] = restrictions; + emit ClaimStored(claimID, _uri, units); + } + + /// @notice Mint semi-fungible tokens for the impact claim referenced via `uri` + /// @dev see {IHypercertToken} + function mintClaimWithFractions( + address account, + uint256 units, + uint256[] calldata fractions, + string memory _uri, + TransferRestrictions restrictions + ) external override whenNotPaused { + // This enables us to release this restriction in the future + if (msg.sender != account) revert Errors.NotAllowed(); + //Using sum to compare units and fractions (sanity check) + if (_getSum(fractions) != units) revert Errors.Invalid(); + + uint256 claimID = _mintNewTypeWithTokens(account, fractions, _uri); + typeRestrictions[claimID] = restrictions; + emit ClaimStored(claimID, _uri, units); + } + + /// @notice Mint a semi-fungible token representing a fraction of the claim + /// @dev Calls AllowlistMinter to verify `proof`. + /// @dev Mints the `amount` of units for the hypercert stored under `claimID` + function mintClaimFromAllowlist( + address account, + bytes32[] calldata proof, + uint256 claimID, + uint256 units + ) external whenNotPaused { + _processClaim(proof, claimID, units); + _mintToken(account, claimID, units); + } + + /// @notice Mint semi-fungible tokens representing a fraction of the claims in `claimIDs` + /// @dev Calls AllowlistMinter to verify `proofs`. + /// @dev Mints the `amount` of units for the hypercert stored under `claimIDs` + function batchMintClaimsFromAllowlists( + address account, + bytes32[][] calldata proofs, + uint256[] calldata claimIDs, + uint256[] calldata units + ) external whenNotPaused { + uint256 len = claimIDs.length; + for (uint256 i; i < len; ) { + _processClaim(proofs[i], claimIDs[i], units[i]); + unchecked { + ++i; + } + } + _batchMintTokens(account, claimIDs, units); + } + + /// @notice Register a claim and the whitelist for minting token(s) belonging to that claim + /// @dev Calls SemiFungible1155 to store the claim referenced in `uri` with amount of `units` + /// @dev Calls AllowlistMinter to store the `merkleRoot` as proof to authorize claims + function createAllowlist( + address account, + uint256 units, + bytes32 merkleRoot, + string memory _uri, + TransferRestrictions restrictions + ) external whenNotPaused { + uint256 claimID = _createTokenType(account, units, _uri); + _createAllowlist(claimID, merkleRoot, units); + typeRestrictions[claimID] = restrictions; + emit ClaimStored(claimID, _uri, units); + } + + /// @notice Split a claimtokens value into parts with summed value equal to the original + /// @dev see {IHypercertToken} + function splitFraction( + address _account, + uint256 _tokenID, + uint256[] calldata _newFractions + ) external whenNotPaused { + _splitTokenUnits(_account, _tokenID, _newFractions); + } + + /// @notice Merge the value of tokens belonging to the same claim + /// @dev see {IHypercertToken} + function mergeFractions(address _account, uint256[] calldata _fractionIDs) external whenNotPaused { + _mergeTokensUnits(_account, _fractionIDs); + } + + /// @notice Burn a claimtoken + /// @dev see {IHypercertToken} + function burnFraction(address _account, uint256 _tokenID) external whenNotPaused { + _burnToken(_account, _tokenID); + } + + /// @dev see {IHypercertToken} + function unitsOf(uint256 tokenID) external view override returns (uint256 units) { + units = _unitsOf(tokenID); + } + + /// @dev see {IHypercertToken} + function unitsOf(address account, uint256 tokenID) external view override returns (uint256 units) { + units = _unitsOf(account, tokenID); + } + + /// PAUSABLE + + function pause() external onlyOwner { + _pause(); + } + + function unpause() external onlyOwner { + _unpause(); + } + + /// METADATA + + /// @dev see { IHypercertMetadata} + function uri(uint256 tokenID) public view override(IHypercertToken, SemiFungible1155) returns (string memory _uri) { + _uri = SemiFungible1155.uri(tokenID); + } + + /// TRANSFER RESTRICTIONS + + function readTransferRestriction(uint256 tokenID) external view returns (string memory) { + TransferRestrictions temp = typeRestrictions[getBaseType(tokenID)]; + if (temp == TransferRestrictions.AllowAll) return "AllowAll"; + if (temp == TransferRestrictions.DisallowAll) return "DisallowAll"; + if (temp == TransferRestrictions.FromCreatorOnly) return "FromCreatorOnly"; + return ""; + } + + /// INTERNAL + + /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol } + function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { + // solhint-disable-previous-line no-empty-blocks + } + + function _beforeTokenTransfer( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) internal virtual override { + super._beforeTokenTransfer(operator, from, to, ids, amounts, data); + + // By-pass transfer restrictions for minting and burning + if (from == address(0)) { + // Minting + return; + } else if (to == address(0)) { + // Burning + return; + } + + // Transfer case, where to and from are non-zero + uint256 len = ids.length; + for (uint256 i; i < len; ) { + uint256 typeID = getBaseType(ids[i]); + TransferRestrictions policy = typeRestrictions[typeID]; + if (policy == TransferRestrictions.DisallowAll) { + revert Errors.TransfersNotAllowed(); + } else if (policy == TransferRestrictions.FromCreatorOnly && from != creators[typeID]) { + revert Errors.TransfersNotAllowed(); + } + unchecked { + ++i; + } + } + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + * Assuming 30 available slots (slots cost space, cost gas) + * 1. typeRestrictions + */ + uint256[29] private __gap; +} diff --git a/contracts/contracts/SemiFungible1155.sol b/contracts/contracts/SemiFungible1155.sol new file mode 100644 index 00000000..cd88714a --- /dev/null +++ b/contracts/contracts/SemiFungible1155.sol @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: MIT +// Used components of Enjin example implementation for mixed fungibility +// /~https://github.com/enjin/erc-1155/blob/master/contracts/ERC1155MixedFungibleMintable.sol +pragma solidity 0.8.16; + +import { ERC1155Upgradeable } from "oz-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; +import { ERC1155BurnableUpgradeable } from "oz-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol"; +import { ERC1155URIStorageUpgradeable } from "oz-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol"; +import { OwnableUpgradeable } from "oz-upgradeable/access/OwnableUpgradeable.sol"; +import { Initializable } from "oz-upgradeable/proxy/utils/Initializable.sol"; +import { UUPSUpgradeable } from "oz-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import { Errors } from "./libs/Errors.sol"; + +/// @title Contract for minting semi-fungible EIP1155 tokens +/// @author bitbeckers +/// @notice Extends { Upgradeable1155 } token with semi-fungible properties and the concept of `units` +/// @dev Adds split bit strategy as described in [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155#non-fungible-tokens) +contract SemiFungible1155 is + Initializable, + ERC1155Upgradeable, + ERC1155BurnableUpgradeable, + ERC1155URIStorageUpgradeable, + OwnableUpgradeable, + UUPSUpgradeable +{ + /// @dev Counter used to generate next typeID. + uint256 internal typeCounter; + + /// @dev Bitmask used to expose only upper 128 bits of uint256 + uint256 internal constant TYPE_MASK = type(uint256).max << 128; + + /// @dev Bitmask used to expose only lower 128 bits of uint256 + uint256 internal constant NF_INDEX_MASK = type(uint256).max >> 128; + + uint256 internal constant FRACTION_LIMIT = 253; + + /// @dev Mapping of `tokenID` to address of `owner` + mapping(uint256 => address) internal owners; + + /// @dev Mapping of `tokenID` to address of `creator` + mapping(uint256 => address) internal creators; + + /// @dev Used to determine amount of `units` stored in token at `tokenID` + mapping(uint256 => uint256) internal tokenValues; + + /// @dev Used to find highest index of token belonging to token at `typeID` + mapping(uint256 => uint256) internal maxIndex; + + /// @dev Emitted on transfer of `value` between `fromTokenID` to `toTokenID` of the same `claimID` + event ValueTransfer(uint256 claimID, uint256 fromTokenID, uint256 toTokenID, uint256 value); + + /// @dev Emitted on transfer of `values` between `fromTokenIDs` to `toTokenIDs` of `claimIDs` + event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values); + + /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } + // solhint-disable-next-line func-name-mixedcase + function __SemiFungible1155_init() public virtual onlyInitializing { + __ERC1155_init(""); + __ERC1155Burnable_init(); + __ERC1155URIStorage_init(); + __Ownable_init(); + __UUPSUpgradeable_init(); + } + + /// @dev Get index of fractional token at `_id` by returning lower 128 bit values + /// @dev Returns 0 if `_id` is a baseType + function getItemIndex(uint256 tokenID) internal pure returns (uint256) { + return tokenID & NF_INDEX_MASK; + } + + /// @dev Get base type ID for token at `_id` by returning upper 128 bit values + function getBaseType(uint256 tokenID) internal pure returns (uint256) { + return tokenID & TYPE_MASK; + } + + /// @dev Identify that token at `_id` is base type. + /// @dev Upper 128 bits identify base type ID, lower bits should be 0 + function isBaseType(uint256 tokenID) internal pure returns (bool) { + return (tokenID & TYPE_MASK == tokenID) && (tokenID & NF_INDEX_MASK == 0); + } + + /// @dev Identify that token at `_id` is fraction of a claim. + /// @dev Upper 128 bits identify base type ID, lower bits should be > 0 + function isTypedItem(uint256 tokenID) internal pure returns (bool) { + return (tokenID & TYPE_MASK != 0) && (tokenID & NF_INDEX_MASK != 0); + } + + /// READ + function ownerOf(uint256 tokenID) public view returns (address _owner) { + _owner = owners[tokenID]; + } + + /// @dev see {IHypercertToken} + function _unitsOf(uint256 tokenID) internal view returns (uint256 units) { + units = tokenValues[tokenID]; + } + + /// @dev see {IHypercertToken} + function _unitsOf(address account, uint256 tokenID) internal view returns (uint256 units) { + // Check if fraction token and accounts owns it + if (ownerOf(tokenID) == account) { + units = tokenValues[tokenID]; + } + } + + /// MUTATE + + /// @dev create token type ID based of token counter + + function _createTokenType(address _account, uint256 units, string memory _uri) internal returns (uint256 typeID) { + _notMaxType(typeCounter); + typeID = ++typeCounter << 128; + + creators[typeID] = _account; + tokenValues[typeID] = units; + + _setURI(typeID, _uri); + + //Event emitted for indexing purposes + emit TransferSingle(_account, address(0), address(0), typeID, 0); + } + + /// @dev Mint a new token type and the initial units + function _mintNewTypeWithToken( + address _account, + uint256 _units, + string memory _uri + ) internal returns (uint256 typeID) { + if (_units == 0) { + revert Errors.NotAllowed(); + } + typeID = _createTokenType(_account, _units, _uri); + + uint256 tokenID = typeID + ++maxIndex[typeID]; //1 based indexing, 0 holds type data + + tokenValues[tokenID] = _units; + + _mint(_account, tokenID, 1, ""); + emit ValueTransfer(typeID, 0, tokenID, _units); + } + + /// @dev Mint a new token type and the initial fractions + function _mintNewTypeWithTokens( + address _account, + uint256[] calldata _fractions, + string memory _uri + ) internal returns (uint256 typeID) { + typeID = _mintNewTypeWithToken(_account, _getSum(_fractions), _uri); + _splitTokenUnits(_account, typeID + maxIndex[typeID], _fractions); + } + + /// @dev Mint a new token for an existing type + function _mintToken(address _account, uint256 _typeID, uint256 _units) internal returns (uint256 tokenID) { + if (!isBaseType(_typeID)) revert Errors.NotAllowed(); + + _notMaxItem(maxIndex[_typeID]); + + unchecked { + tokenID = _typeID + ++maxIndex[_typeID]; //1 based indexing, 0 holds type data + } + + tokenValues[tokenID] = _units; + + _mint(_account, tokenID, 1, ""); + emit ValueTransfer(_typeID, 0, tokenID, _units); + } + + /// @dev Mint new tokens for existing types + /// @notice Enables batch claiming from multiple allowlists + function _batchMintTokens( + address _account, + uint256[] calldata _typeIDs, + uint256[] calldata _units + ) internal returns (uint256[] memory tokenIDs) { + uint256 len = _typeIDs.length; + + tokenIDs = new uint256[](len); + uint256[] memory amounts = new uint256[](len); + uint256[] memory zeroes = new uint256[](len); + + for (uint256 i; i < len; ) { + uint256 _typeID = _typeIDs[i]; + if (!isBaseType(_typeID)) revert Errors.NotAllowed(); + _notMaxItem(maxIndex[_typeID]); + + unchecked { + uint256 tokenID = _typeID + ++maxIndex[_typeID]; //1 based indexing, 0 holds type data + tokenValues[tokenID] = _units[i]; + tokenIDs[i] = tokenID; + amounts[i] = 1; + ++i; + } + } + + _mintBatch(_account, tokenIDs, amounts, ""); + emit BatchValueTransfer(_typeIDs, zeroes, tokenIDs, _units); + } + + /// @dev Split the units of `_tokenID` owned by `account` across `_values` + /// @dev `_values` must sum to total `units` held at `_tokenID` + function _splitTokenUnits(address _account, uint256 _tokenID, uint256[] calldata _values) internal { + if (_values.length > FRACTION_LIMIT || _values.length < 2) revert Errors.ArraySize(); + if (tokenValues[_tokenID] != _getSum(_values)) revert Errors.NotAllowed(); + + // Current token + uint256 _typeID = getBaseType(_tokenID); + uint256 valueLeft = tokenValues[_tokenID]; + + // Prepare batch processing, we want to skip the first entry + uint256 len = _values.length - 1; + + uint256[] memory typeIDs = new uint256[](len); + uint256[] memory fromIDs = new uint256[](len); + uint256[] memory toIDs = new uint256[](len); + uint256[] memory amounts = new uint256[](len); + uint256[] memory values = new uint256[](len); + + { + uint256[] memory _valuesCache = _values; + uint256 swapValue = _valuesCache[len]; + _valuesCache[len] = _valuesCache[0]; + _valuesCache[0] = swapValue; + + for (uint256 i; i < len; ) { + _notMaxItem(maxIndex[_typeID]); + + typeIDs[i] = _typeID; + fromIDs[i] = _tokenID; + toIDs[i] = _typeID + ++maxIndex[_typeID]; + amounts[i] = 1; + values[i] = _valuesCache[i]; + + unchecked { + ++i; + } + } + } + + _beforeUnitTransfer(_msgSender(), _account, fromIDs, toIDs, values, ""); + + for (uint256 i; i < len; ) { + valueLeft -= values[i]; + + tokenValues[toIDs[i]] = values[i]; + + unchecked { + ++i; + } + } + + tokenValues[_tokenID] = valueLeft; + + _mintBatch(_account, toIDs, amounts, ""); + + emit BatchValueTransfer(typeIDs, fromIDs, toIDs, values); + } + + /// @dev Merge the units of `_fractionIDs`. + /// @dev Base type of `_fractionIDs` must be identical for all tokens. + function _mergeTokensUnits(address _account, uint256[] memory _fractionIDs) internal { + if (_fractionIDs.length > FRACTION_LIMIT || _fractionIDs.length < 2) { + revert Errors.ArraySize(); + } + uint256 len = _fractionIDs.length - 1; + + uint256 target = _fractionIDs[len]; + + uint256 _totalValue; + uint256[] memory fromIDs = new uint256[](len); + uint256[] memory toIDs = new uint256[](len); + uint256[] memory values = new uint256[](len); + uint256[] memory amounts = new uint256[](len); + + { + for (uint256 i; i < len; ) { + uint256 _fractionID = _fractionIDs[i]; + fromIDs[i] = _fractionID; + toIDs[i] = target; + amounts[i] = 1; + values[i] = tokenValues[_fractionID]; + + unchecked { + ++i; + } + } + } + + _beforeUnitTransfer(_msgSender(), _account, fromIDs, toIDs, values, ""); + + for (uint256 i; i < len; ) { + _totalValue += values[i]; + + delete tokenValues[fromIDs[i]]; + unchecked { + ++i; + } + } + + tokenValues[target] += _totalValue; + + _burnBatch(_account, fromIDs, amounts); + } + + /// @dev Burn the token at `_tokenID` owned by `_account` + /// @dev Not allowed to burn base type. + /// @dev `_tokenID` must hold all value declared at base type + function _burnToken(address _account, uint256 _tokenID) internal { + if (_account != _msgSender() && !isApprovedForAll(_account, _msgSender())) revert Errors.NotApprovedOrOwner(); + + uint256 value = tokenValues[_tokenID]; + + delete tokenValues[_tokenID]; + + _burn(_account, _tokenID, 1); + emit ValueTransfer(getBaseType(_tokenID), _tokenID, 0, value); + } + + /// TRANSFERS + + // The following functions are overrides required by Solidity. + function _afterTokenTransfer( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) internal virtual override { + super._afterTokenTransfer(operator, from, to, ids, amounts, data); + + uint256 len = ids.length; + + for (uint256 i; i < len; ) { + owners[ids[i]] = to; + unchecked { + ++i; + } + } + } + + function _beforeUnitTransfer( + address operator, + address from, + uint256[] memory fromIDs, + uint256[] memory toIDs, + uint256[] memory values, + bytes memory data + ) internal virtual { + uint256 len = fromIDs.length; + + for (uint256 i; i < len; ) { + uint256 _from = fromIDs[i]; + uint256 _to = toIDs[i]; + + if (isBaseType(_from)) revert Errors.NotAllowed(); + if (getBaseType(_from) != getBaseType(_to)) revert Errors.TypeMismatch(); + if (from != _msgSender() && !isApprovedForAll(from, _msgSender())) revert Errors.NotApprovedOrOwner(); + unchecked { + ++i; + } + } + } + + /// METADATA + + /// @dev see { openzeppelin-contracts-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol } + /// @dev Always returns the URI for the basetype so that it's managed in one place. + function uri( + uint256 tokenID + ) public view virtual override(ERC1155Upgradeable, ERC1155URIStorageUpgradeable) returns (string memory _uri) { + // All tokens share the same metadata at the moment + _uri = ERC1155URIStorageUpgradeable.uri(getBaseType(tokenID)); + } + + /// UTILS + + /** + * @dev Check if value is below max item index + */ + function _notMaxItem(uint256 tokenID) private pure { + uint128 _count = uint128(tokenID); + ++_count; + } + + /** + * @dev Check if value is below max type index + */ + function _notMaxType(uint256 tokenID) private pure { + uint128 _count = uint128(tokenID >> 128); + ++_count; + } + + /** + * @dev calculate the sum of the elements of an array + */ + function _getSum(uint256[] memory array) internal pure returns (uint256 sum) { + uint256 len = array.length; + for (uint256 i; i < len; ) { + if (array[i] == 0) revert Errors.NotAllowed(); + sum += array[i]; + unchecked { + ++i; + } + } + } + + function _getSingletonArray(uint256 element) private pure returns (uint256[] memory) { + uint256[] memory array = new uint256[](1); + array[0] = element; + + return array; + } + + // UUPS PROXY + + /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol } + function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { + // solhint-disable-previous-line no-empty-blocks + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + * Assuming 30 available slots (slots cost space, cost gas) + * 1. typeCounter + * 2. owners + * 3. creators + * 4. tokenValues + * 5. maxIndex + */ + uint256[25] private __gap; +} diff --git a/contracts/contracts/interfaces/IAllowlist.sol b/contracts/contracts/interfaces/IAllowlist.sol new file mode 100644 index 00000000..fe4a9ec4 --- /dev/null +++ b/contracts/contracts/interfaces/IAllowlist.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +/// @title Interface for allowlist +/// @author bitbeckers +/// @notice This interface declares the required functionality for a hypercert token +/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) +interface IAllowlist { + function isAllowedToClaim( + bytes32[] calldata proof, + uint256 tokenID, + bytes32 leaf + ) external view returns (bool isAllowed); +} diff --git a/contracts/contracts/interfaces/IHypercertToken.sol b/contracts/contracts/interfaces/IHypercertToken.sol new file mode 100644 index 00000000..1ed1e34e --- /dev/null +++ b/contracts/contracts/interfaces/IHypercertToken.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +/// @title Interface for hypercert token interactions +/// @author bitbeckers +/// @notice This interface declares the required functionality for a hypercert token +/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) +interface IHypercertToken { + /** + * AllowAll = Unrestricted + * DisallowAll = Transfers disabled after minting + * FromCreatorOnly = Only the original creator can transfer + */ + /// @dev Transfer restriction policies on hypercerts + enum TransferRestrictions { + AllowAll, + DisallowAll, + FromCreatorOnly + } + + /// @dev Emitted when token with tokenID `claimID` is stored, with external data reference via `uri`. + event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits); + + /// @dev Function called to store a claim referenced via `uri` with a maximum number of fractions `units`. + function mintClaim(address account, uint256 units, string memory uri, TransferRestrictions restrictions) external; + + /// @dev Function called to store a claim referenced via `uri` with a set of `fractions`. + /// @dev Fractions are internally summed to total units. + function mintClaimWithFractions( + address account, + uint256 units, + uint256[] memory fractions, + string memory uri, + TransferRestrictions restrictions + ) external; + + /// @dev Function called to split `tokenID` owned by `account` into units declared in `values`. + /// @notice The sum of `values` must equal the current value of `_tokenID`. + function splitFraction(address account, uint256 tokenID, uint256[] memory _values) external; + + /// @dev Function called to merge tokens within `tokenIDs`. + /// @notice Tokens that have been merged are burned. + function mergeFractions(address account, uint256[] memory tokenIDs) external; + + /// @dev Function to burn the token at `tokenID` for `account` + /// @notice Operator must be allowed by `creator` and the token must represent the total amount of available units. + function burnFraction(address account, uint256 tokenID) external; + + /// @dev Returns the `units` held by a (fractional) token at `claimID` + /// @dev If `tokenID` is a base type, the total amount of `units` for the claim is returned. + /// @dev If `tokenID` is a fractional token, the `units` held by the token is returned + function unitsOf(uint256 tokenID) external view returns (uint256 units); + + /// @dev Returns the `units` held by `account` of a (fractional) token at `claimID` + /// @dev If `tokenID` is a base type, the total amount of `units` held by `account` for the claim is returned. + /// @dev If `tokenID` is a fractional token, the `units` held by `account` the token is returned + function unitsOf(address account, uint256 tokenID) external view returns (uint256 units); + + /// @dev Returns the `uri` for metadata of the claim represented by `tokenID` + /// @dev Metadata must conform to { Hypercert Metadata } spec (based on ERC1155 Metadata) + function uri(uint256 tokenID) external view returns (string memory metadata); +} diff --git a/contracts/contracts/libs/Errors.sol b/contracts/contracts/libs/Errors.sol new file mode 100644 index 00000000..e19d6b5c --- /dev/null +++ b/contracts/contracts/libs/Errors.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +/// @author bitbeckers +library Errors { + error AlreadyClaimed(); + error ArraySize(); + error DoesNotExist(); + error DuplicateEntry(); + error Invalid(); + error NotAllowed(); + error NotApprovedOrOwner(); + error TransfersNotAllowed(); + error TypeMismatch(); +} diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index 83a3b04c..48f3d3d6 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -9,7 +9,6 @@ import { config as dotenvConfig } from "dotenv"; import fs from "fs"; import "hardhat-abi-exporter"; import "hardhat-preprocessor"; -import { HardhatUserConfig } from "hardhat/config"; import { resolve } from "path"; import "./tasks"; @@ -36,10 +35,14 @@ dotenvConfig({ path: resolve(__dirname, dotenvConfigPath) }); // Ensure that we have all the environment variables we need. const mnemonic = requireEnv(process.env.MNEMONIC, "MNEMONIC"); +const mnemonic_celo = requireEnv(process.env.MNEMONIC_CELO, "MNEMONIC_CELO"); const infuraApiKey = requireEnv(process.env.INFURA_API_KEY, "INFURA_API_KEY"); const alchemyOptimismUrl = requireEnv(process.env.ALCHEMY_OPTIMISM_URL, "ALCHEMY_OPTIMISM_URL"); + const etherscanApiKey = requireEnv(process.env.ETHERSCAN_API_KEY, "ETHERSCAN_API_KEY"); const optimisticEtherscanApiKey = requireEnv(process.env.OPTIMISTIC_ETHERSCAN_API_KEY, "OPTIMISTIC_ETHERSCAN_API_KEY"); +const celoscanApiKey = requireEnv(process.env.CELOSCAN_API_KEY, "CELOSCAN_API_KEY"); + const ozApiKey = requireEnv(process.env.OPENZEPPELIN_API_KEY, "OPENZEPPELIN_API_KEY"); const ozSecretKey = requireEnv(process.env.OPENZEPPELIN_SECRET_KEY, "OPENZEPPELIN_SECRET_KEY"); @@ -56,11 +59,13 @@ const chainIds = { // Optimism: https://docs.infura.io/infura/networks/optimism/how-to/choose-a-network "optimism-mainnet": 10, "optimism-goerli": 420, + // Celo + "celo-mainnet": 42220, }; function getChainConfig(chain: keyof typeof chainIds) { const jsonRpcUrl = "https://" + chain + ".infura.io/v3/" + infuraApiKey; - return { + let config = { accounts: { count: 10, mnemonic, @@ -69,6 +74,19 @@ function getChainConfig(chain: keyof typeof chainIds) { chainId: chainIds[chain], url: jsonRpcUrl, }; + + if (chain === "celo-mainnet") { + config = { + ...config, + accounts: { + count: 10, + mnemonic: mnemonic_celo, + path: "m/44'/52752'/0'/0", + }, + }; + } + + return config; } const config = { @@ -96,7 +114,18 @@ const config = { goerli: etherscanApiKey!, sepolia: etherscanApiKey!, optimisticEthereum: optimisticEtherscanApiKey!, + celo: celoscanApiKey!, }, + customChains: [ + { + network: "celo", + chainId: 42220, + urls: { + apiURL: "https://api.celoscan.io/api", + browserURL: "https://celoscan.io/", + }, + }, + ], }, networks: { hardhat: { @@ -111,6 +140,7 @@ const config = { localhost: { url: process.env.LOCALHOST_NETWORK_URL || "http://127.0.0.1:8545", }, + "celo-mainnet": getChainConfig("celo-mainnet"), goerli: getChainConfig("goerli"), sepolia: getChainConfig("sepolia"), mainnet: getChainConfig("mainnet"), diff --git a/contracts/tasks/deploy.ts b/contracts/tasks/deploy.ts index ea63c113..30927db5 100644 --- a/contracts/tasks/deploy.ts +++ b/contracts/tasks/deploy.ts @@ -4,6 +4,7 @@ import { writeFile } from "node:fs/promises"; task("deploy", "Deploy contracts and verify") .addOptionalParam("output", "write the details of the deployment to this file if this is set") .setAction(async ({ output }, { ethers, upgrades, network, run }) => { + console.log("Using address: ", await ethers.getSigners().then((res) => res[0])); const HypercertMinter = await ethers.getContractFactory("HypercertMinter"); const hypercertMinter = await upgrades.deployProxy(HypercertMinter, { kind: "uups", diff --git a/defender/package.json b/defender/package.json index b71b1b67..f2da4c70 100644 --- a/defender/package.json +++ b/defender/package.json @@ -10,7 +10,7 @@ "deploy:test": "pnpm build && pnpm setup:test", "deploy:prod": "pnpm build && pnpm setup:prod", "setup:test": "npx tsx src/setup.ts TEST", - "setup:prod": "npx tsx src/setup.ts src/setup.ts PROD" + "setup:prod": "npx tsx src/setup.ts PROD" }, "dependencies": { "@hypercerts-org/contracts": "0.8.11", diff --git a/defender/src/networks.ts b/defender/src/networks.ts index 8d49def0..ffbc1fba 100644 --- a/defender/src/networks.ts +++ b/defender/src/networks.ts @@ -42,6 +42,12 @@ export const NETWORKS: SupportedNetworks = { alchemyKeyEnvName: "ALCHEMY_OPTIMISM_KEY", chainId: 10, }, + { + networkKey: "celo", + contractAddress: "0x16ba53b74c234c870c61efc04cd418b8f2865959", + chainId: 42220, + rpc: "https://forno.celo.org", + }, ], }; diff --git a/frontend/components/dapp-context.tsx b/frontend/components/dapp-context.tsx index 86d1cf4b..e0d4c179 100644 --- a/frontend/components/dapp-context.tsx +++ b/frontend/components/dapp-context.tsx @@ -31,14 +31,21 @@ import { import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import React, { ReactNode, useEffect } from "react"; -import { Chain, goerli, optimism, sepolia } from "viem/chains"; +import { celo, Chain, goerli, optimism, sepolia } from "viem/chains"; import { configureChains, WagmiConfig, createConfig } from "wagmi"; import { publicProvider } from "wagmi/providers/public"; +import { + Valora, + CeloWallet, + CeloTerminal, + MetaMask as CeloMetaMask, +} from "@celo/rainbowkit-celo/wallets"; + const queryClient = new QueryClient(); const TEST_CHAINS = [goerli, sepolia]; -const PROD_CHAINS = [optimism]; +const PROD_CHAINS = [optimism, celo]; export const CHAINS = (isProduction ? PROD_CHAINS : TEST_CHAINS) as Chain[]; @@ -72,6 +79,16 @@ const connectors = connectorsForWallets([ zerionWallet({ chains, projectId }), ], }, + { + groupName: "Recommended with CELO", + wallets: [ + Valora({ chains, projectId }), + CeloWallet({ chains, projectId }), + CeloTerminal({ chains, projectId }), + CeloMetaMask({ chains, projectId }), + walletConnectWallet({ projectId, chains }), + ], + }, { groupName: "Injected", wallets: [injectedWallet({ chains })], diff --git a/frontend/package.json b/frontend/package.json index 975d0cff..c9d96480 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,12 +19,13 @@ }, "dependencies": { "@apollo/client": "^3.7.4", + "@celo/rainbowkit-celo": "^1.1.0", "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", "@graphprotocol/client-cli": "^2.2.16", "@hypercerts-org/contracts": "0.8.11", "@hypercerts-org/observabletreemap": "workspace: *", - "@hypercerts-org/sdk": "0.8.10", + "@hypercerts-org/sdk": "0.8.16", "@mui/icons-material": "^5.11.9", "@mui/material": "^5.11.2", "@mui/x-date-pickers": "^5.0.12", diff --git a/graph/networks.json b/graph/networks.json index 6e001089..28925338 100644 --- a/graph/networks.json +++ b/graph/networks.json @@ -1,4 +1,10 @@ { + "celo": { + "HypercertMinter": { + "address": "0x16ba53b74c234c870c61efc04cd418b8f2865959", + "startBlock": 22079542 + } + }, "goerli": { "HypercertMinter": { "address": "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", diff --git a/graph/package.json b/graph/package.json index 1eb107be..c6ab7e5f 100644 --- a/graph/package.json +++ b/graph/package.json @@ -3,11 +3,6 @@ "license": "Apache-2.0", "version": "0.0.1", "private": true, - "workspaces": { - "nohoist": [ - "**" - ] - }, "scripts": { "auth": "graph auth --product hosted-service $SUBGRAPH_ACCESS_TOKEN", "coverage": "graph test -- -c", @@ -15,7 +10,8 @@ "build:graph": "graph build", "build:codegen": "graph codegen", "deploy:test": "pnpm auth && pnpm deploy:goerli && pnpm deploy:sepolia", - "deploy:prod": "pnpm auth && pnpm deploy:optimism", + "deploy:prod": "pnpm auth && pnpm deploy:optimism && pnpm deploy:celo", + "deploy:celo": "graph deploy --node https://api.thegraph.com/deploy/ --network celo hypercerts-admin/hypercerts-celo", "deploy:goerli": "graph deploy --node https://api.thegraph.com/deploy/ --network goerli hypercerts-admin/hypercerts-testnet", "deploy:optimism": "graph deploy --node https://api.thegraph.com/deploy/ --network optimism hypercerts-admin/hypercerts-optimism-mainnet", "deploy:sepolia": "graph deploy --node https://api.thegraph.com/deploy/ --network sepolia hypercerts-admin/hypercerts-sepolia", @@ -25,11 +21,13 @@ "graph": "graph", "test": "graph test" }, - "dependencies": { - "@graphprotocol/graph-cli": "0.57.0" - }, "devDependencies": { + "@graphprotocol/graph-cli": "0.60.0", "@graphprotocol/graph-ts": "0.31.0", - "matchstick-as": "0.5.2" - } + "assemblyscript": "0.19.23", + "matchstick-as": "0.6.0" + }, + "//": [ + "Pinned assemblyscript verion: /~https://github.com/LimeChain/matchstick/issues/324" + ] } diff --git a/graph/subgraph.yaml b/graph/subgraph.yaml index 38924776..ada9aab5 100644 --- a/graph/subgraph.yaml +++ b/graph/subgraph.yaml @@ -4,11 +4,11 @@ schema: dataSources: - kind: ethereum/contract name: HypercertMinter - network: sepolia + network: celo source: abi: HypercertMinter - address: "0xa16DFb32Eb140a6f3F2AC68f41dAd8c7e83C4941" - startBlock: 4421942 + address: "0x16ba53b74c234c870c61efc04cd418b8f2865959" + startBlock: 22079542 mapping: kind: ethereum/events apiVersion: 0.0.7 diff --git a/graph/tests/.latest.json b/graph/tests/.latest.json index 1402a72b..4651dd06 100644 --- a/graph/tests/.latest.json +++ b/graph/tests/.latest.json @@ -1,4 +1,4 @@ { - "version": "0.5.4", - "timestamp": 1697021487648 + "version": "0.6.0", + "timestamp": 1698094053842 } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b2c31a9..531025b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,10 +14,10 @@ importers: devDependencies: '@playwright/test': specifier: ^1.35.1 - version: 1.38.1 + version: 1.39.0 '@synthetixio/synpress': specifier: ^3.7.1 - version: 3.7.1(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.6)(webpack@5.88.2) + version: 3.7.1(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.6)(webpack@5.89.0) husky: specifier: ^8.0.3 version: 8.0.3 @@ -29,16 +29,16 @@ importers: version: 2.8.8 turbo: specifier: ^1.10.15 - version: 1.10.15 + version: 1.10.16 contracts: devDependencies: '@commitlint/cli': specifier: ^17.1.2 - version: 17.8.0 + version: 17.8.1 '@commitlint/config-conventional': specifier: ^17.1.0 - version: 17.8.0 + version: 17.8.1 '@dlsl/hardhat-markup': specifier: ^1.0.0-rc.7 version: 1.0.0-rc.14(hardhat@2.13.1)(prettier@2.8.8) @@ -59,7 +59,7 @@ importers: version: 1.0.9(hardhat@2.13.1) '@nomicfoundation/hardhat-toolbox': specifier: ^2.0.0 - version: 2.0.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-chai-matchers@1.0.6)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(@typechain/ethers-v5@11.1.2)(@typechain/hardhat@9.1.0)(@types/chai@4.3.7)(@types/mocha@9.1.0)(@types/node@18.15.13)(chai@4.3.10)(ethers@5.7.2)(hardhat-gas-reporter@1.0.9)(hardhat@2.13.1)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.1)(typescript@4.9.5) + version: 2.0.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-chai-matchers@1.0.6)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(@typechain/ethers-v5@11.1.2)(@typechain/hardhat@9.1.0)(@types/chai@4.3.9)(@types/mocha@9.1.0)(@types/node@18.18.6)(chai@4.3.10)(ethers@5.7.2)(hardhat-gas-reporter@1.0.9)(hardhat@2.13.1)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.2)(typescript@4.9.5) '@nomiclabs/hardhat-ethers': specifier: ^2.2.1 version: 2.2.3(ethers@5.7.2)(hardhat@2.13.1) @@ -89,25 +89,25 @@ importers: version: 3.4.0(prettier@2.8.8) '@typechain/ethers-v5': specifier: ^11.1.1 - version: 11.1.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@4.9.5) + version: 11.1.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) '@typechain/hardhat': specifier: ^9.0.0 - version: 9.1.0(@typechain/ethers-v6@0.5.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.1) + version: 9.1.0(@typechain/ethers-v6@0.5.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2) '@types/chai': specifier: ^4.3.4 - version: 4.3.7 + version: 4.3.9 '@types/mocha': specifier: 9.1.0 version: 9.1.0 '@types/node': specifier: ^18.11.11 - version: 18.15.13 + version: 18.18.6 '@typescript-eslint/eslint-plugin': specifier: ^5.38.0 - version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.51.0)(typescript@4.9.5) + version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.52.0)(typescript@4.9.5) '@typescript-eslint/parser': specifier: ^5.38.0 - version: 5.62.0(eslint@8.51.0)(typescript@4.9.5) + version: 5.62.0(eslint@8.52.0)(typescript@4.9.5) chai: specifier: ^4.3.7 version: 4.3.10 @@ -128,10 +128,10 @@ importers: version: 16.3.1 eslint: specifier: ^8.23.1 - version: 8.51.0 + version: 8.52.0 eslint-config-prettier: specifier: ^8.5.0 - version: 8.10.0(eslint@8.51.0) + version: 8.10.0(eslint@8.52.0) ethers: specifier: ^5.7.2 version: 5.7.2 @@ -173,7 +173,7 @@ importers: version: 6.1.0(rollup@4.1.4)(typescript@4.9.5) rollup-plugin-esbuild: specifier: ^6.1.0 - version: 6.1.0(esbuild@0.18.20)(rollup@4.1.4) + version: 6.1.0(esbuild@0.19.5)(rollup@4.1.4) rollup-plugin-node-polyfills: specifier: ^0.2.1 version: 0.2.1 @@ -191,10 +191,10 @@ importers: version: 0.8.5(hardhat@2.13.1) ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.15.13)(typescript@4.9.5) + version: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) typechain: specifier: ^8.3.1 - version: 8.3.1(typescript@4.9.5) + version: 8.3.2(typescript@4.9.5) typescript: specifier: ^4.9.4 version: 4.9.5 @@ -203,7 +203,7 @@ importers: devDependencies: '@cloudflare/workers-types': specifier: ^4.20230115.0 - version: 4.20231002.0 + version: 4.20231016.0 typescript: specifier: ^4.9.5 version: 4.9.5 @@ -236,7 +236,7 @@ importers: version: 1.0.5 '@supabase/supabase-js': specifier: ^2.4.1 - version: 2.38.0 + version: 2.38.2 axios: specifier: ^1.2.6 version: 1.5.1(debug@4.3.4) @@ -252,19 +252,19 @@ importers: devDependencies: '@types/node': specifier: ^18.11.18 - version: 18.15.13 + version: 18.18.6 rimraf: specifier: ^5.0.5 version: 5.0.5 terser-webpack-plugin: specifier: ^5.3.9 - version: 5.3.9(webpack@5.88.2) + version: 5.3.9(webpack@5.89.0) ts-loader: specifier: ^9.4.2 - version: 9.5.0(typescript@4.9.5)(webpack@5.88.2) + version: 9.5.0(typescript@4.9.5)(webpack@5.89.0) ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.15.13)(typescript@4.9.5) + version: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) tsx: specifier: ^3.14.0 version: 3.14.0 @@ -273,10 +273,10 @@ importers: version: 4.9.5 webpack: specifier: ^5.75.0 - version: 5.88.2(webpack-cli@5.1.4) + version: 5.89.0(webpack-cli@5.1.4) webpack-cli: specifier: ^5.0.1 - version: 5.1.4(webpack@5.88.2) + version: 5.1.4(webpack@5.89.0) docs: dependencies: @@ -285,7 +285,7 @@ importers: version: 2.4.3(@docusaurus/types@2.4.3)(react-dom@18.2.0)(react@18.2.0)(typescript@4.9.5) '@docusaurus/preset-classic': specifier: ^2.4.1 - version: 2.4.3(@algolia/client-search@4.20.0)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.8.3)(typescript@4.9.5) + version: 2.4.3(@algolia/client-search@4.20.0)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.9.0)(typescript@4.9.5) '@docusaurus/theme-mermaid': specifier: ^2.4.1 version: 2.4.3(react-dom@18.2.0)(react@18.2.0)(typescript@4.9.5) @@ -328,16 +328,19 @@ importers: dependencies: '@apollo/client': specifier: ^3.7.4 - version: 3.8.5(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + version: 3.8.6(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + '@celo/rainbowkit-celo': + specifier: ^1.1.0 + version: 1.1.0(@rainbow-me/rainbowkit@1.0.8)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(wagmi@1.3.9)(zod@3.22.4) '@emotion/react': specifier: ^11.10.5 - version: 11.11.1(@types/react@18.2.28)(react@18.2.0) + version: 11.11.1(@types/react@18.2.31)(react@18.2.0) '@emotion/styled': specifier: ^11.10.5 - version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.28)(react@18.2.0) + version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) '@graphprotocol/client-cli': specifier: ^2.2.16 - version: 2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.15.13)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.5) + version: 2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) '@hypercerts-org/contracts': specifier: 0.8.11 version: 0.8.11 @@ -345,56 +348,56 @@ importers: specifier: 'workspace: *' version: link:../vendor/observabletreemap '@hypercerts-org/sdk': - specifier: 0.8.10 - version: 0.8.10(@babel/core@7.23.2)(@envelop/core@3.0.6)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.15.13)(graphql-tag@2.12.6)(node-fetch@3.3.2)(react-native@0.72.5)(typescript@5.1.6)(uint8arraylist@2.4.3) + specifier: 0.8.16 + version: 0.8.16(@envelop/core@3.0.6)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3) '@mui/icons-material': specifier: ^5.11.9 - version: 5.14.13(@mui/material@5.14.13)(@types/react@18.2.28)(react@18.2.0) + version: 5.14.14(@mui/material@5.14.14)(@types/react@18.2.31)(react@18.2.0) '@mui/material': specifier: ^5.11.2 - version: 5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0) + version: 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) '@mui/x-date-pickers': specifier: ^5.0.12 - version: 5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.13)(@mui/system@5.14.13)(@types/react@18.2.28)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) + version: 5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(@mui/system@5.14.14)(@types/react@18.2.31)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) '@next/eslint-plugin-next': specifier: ^13.4.12 - version: 13.5.4 + version: 13.5.6 '@observablehq/runtime': specifier: '5' - version: 5.9.3 + version: 5.9.4 '@openzeppelin/merkle-tree': specifier: ^1.0.2 version: 1.0.5 '@plasmicapp/host': specifier: ^1.0.171 - version: 1.0.171(react-dom@18.2.0)(react@18.2.0) + version: 1.0.177(react-dom@18.2.0)(react@18.2.0) '@plasmicapp/loader-nextjs': specifier: ^1.0.284 - version: 1.0.321(next@13.5.4)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.333(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) '@rainbow-me/rainbowkit': specifier: 1.0.8 - version: 1.0.8(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9) + version: 1.0.8(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9) '@sentry/nextjs': specifier: ^7.73.0 - version: 7.73.0(next@13.5.4)(react@18.2.0)(webpack@5.88.2) + version: 7.74.1(next@13.5.6)(react@18.2.0)(webpack@5.89.0) '@sentry/utils': specifier: ^7.73.0 - version: 7.73.0 + version: 7.74.1 '@supabase/supabase-js': specifier: ^2.1.2 - version: 2.38.0 + version: 2.38.2 '@tanstack/react-query': specifier: ^4.36.1 - version: 4.36.1(react-dom@18.2.0)(react-native@0.72.5)(react@18.2.0) + version: 4.36.1(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0) '@tanstack/react-query-devtools': specifier: ^4.29.12 version: 4.36.1(@tanstack/react-query@4.36.1)(react-dom@18.2.0)(react@18.2.0) '@types/bn.js': specifier: ^5.1.2 - version: 5.1.2 + version: 5.1.3 '@types/lodash': specifier: ^4.14.199 - version: 4.14.199 + version: 4.14.200 bn.js: specifier: ^5.2.1 version: 5.2.1 @@ -415,10 +418,10 @@ importers: version: 2.4.5(react@18.2.0) formik-mui: specifier: ^5.0.0-alpha.0 - version: 5.0.0-alpha.0(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.13)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3) + version: 5.0.0-alpha.0(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3) formik-mui-x-date-pickers: specifier: ^0.0.1 - version: 0.0.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.13)(@mui/system@5.14.13)(@mui/x-date-pickers@5.0.20)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3) + version: 0.0.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(@mui/system@5.14.14)(@mui/x-date-pickers@5.0.20)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3) graphql: specifier: ^16.6.0 version: 16.8.1 @@ -433,16 +436,16 @@ importers: version: 4.17.21 next: specifier: latest - version: 13.5.4(@babel/core@7.23.2)(react-dom@18.2.0)(react@18.2.0) + version: 13.5.6(@babel/core@7.23.2)(react-dom@18.2.0)(react@18.2.0) papaparse: specifier: ^5.4.1 version: 5.4.1 primereact: specifier: ^9.6.0 - version: 9.6.2(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0) + version: 9.6.3(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) qs: specifier: ^6.11.0 - version: 6.11.0 + version: 6.11.2 random-words: specifier: ^2.0.0 version: 2.0.0 @@ -457,7 +460,7 @@ importers: version: 14.2.3(react@18.2.0) react-markdown: specifier: ^8.0.7 - version: 8.0.7(@types/react@18.2.28)(react@18.2.0) + version: 8.0.7(@types/react@18.2.31)(react@18.2.0) react-toastify: specifier: ^9.1.1 version: 9.1.3(react-dom@18.2.0)(react@18.2.0) @@ -472,7 +475,7 @@ importers: version: 1.5.3(typescript@5.1.6)(zod@3.22.4) wagmi: specifier: 1.3.9 - version: 1.3.9(@types/react@18.2.28)(react-dom@18.2.0)(react-native@0.72.5)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + version: 1.3.9(@types/react@18.2.31)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) yup: specifier: ^0.32.11 version: 0.32.11 @@ -491,19 +494,19 @@ importers: version: 14.5.1(@testing-library/dom@9.3.3) '@types/node': specifier: ^18.0.0 - version: 18.15.13 + version: 18.18.6 '@types/papaparse': specifier: ^5.3.7 - version: 5.3.9 + version: 5.3.10 '@types/qs': specifier: ^6.9.7 - version: 6.9.8 + version: 6.9.9 '@types/react': specifier: ^18.0.14 - version: 18.2.28 + version: 18.2.31 '@types/react-dom': specifier: ^18.0.5 - version: 18.2.13 + version: 18.2.14 '@types/testing-library__jest-dom': specifier: ^5.14.5 version: 5.14.9 @@ -527,7 +530,7 @@ importers: version: 1.1.7 jest: specifier: ^29.5.0 - version: 29.7.0(@types/node@18.15.13)(ts-node@10.9.1) + version: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) jest-environment-jsdom: specifier: ^29.5.0 version: 29.7.0 @@ -535,6 +538,21 @@ importers: specifier: 5.1.6 version: 5.1.6 + graph: + devDependencies: + '@graphprotocol/graph-cli': + specifier: 0.60.0 + version: 0.60.0(@types/node@18.18.6)(node-fetch@3.3.2)(typescript@4.9.5) + '@graphprotocol/graph-ts': + specifier: 0.31.0 + version: 0.31.0 + assemblyscript: + specifier: 0.19.23 + version: 0.19.23 + matchstick-as: + specifier: 0.6.0 + version: 0.6.0 + sdk: dependencies: '@ethereum-attestation-service/eas-sdk': @@ -557,7 +575,7 @@ importers: version: 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) '@graphql-mesh/graphql': specifier: ^0.95.7 - version: 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.15.13)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2) + version: 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2) '@graphql-mesh/http': specifier: ^0.96.13 version: 0.96.13(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/runtime@0.96.12)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2) @@ -608,7 +626,7 @@ importers: version: 0.17.0(uint8arraylist@2.4.3) jest: specifier: ^29.3.1 - version: 29.7.0(@types/node@18.15.13)(ts-node@10.9.1) + version: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) loglevel: specifier: ^1.8.1 version: 1.8.1 @@ -636,7 +654,7 @@ importers: version: 8.2.0 '@graphprotocol/client-cli': specifier: ^3.0.0 - version: 3.0.0(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.15.13)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.5) + version: 3.0.0(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) '@jest/globals': specifier: ^29.7.0 version: 29.7.0 @@ -651,19 +669,19 @@ importers: version: 15.2.3(rollup@3.29.4) '@types/chai': specifier: ^4.3.4 - version: 4.3.7 + version: 4.3.9 '@types/chai-subset': specifier: ^1.3.3 - version: 1.3.3 + version: 1.3.4 '@types/jest': specifier: ^29.2.5 - version: 29.5.5 + version: 29.5.6 '@types/node': specifier: ^18.11.17 - version: 18.15.13 + version: 18.18.6 '@types/sinon': specifier: ^10.0.15 - version: 10.0.19 + version: 10.0.20 babel-jest: specifier: ^29.7.0 version: 29.7.0(@babel/core@7.23.2) @@ -729,7 +747,7 @@ importers: version: 10.0.0(mocha@10.2.0) ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.15.13)(typescript@4.9.5) + version: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) tslib: specifier: ^2.5.0 version: 2.6.2 @@ -753,7 +771,7 @@ importers: dependencies: '@observablehq/runtime': specifier: 4 - 5 - version: 5.9.3 + version: 5.9.4 packages: @@ -770,11 +788,10 @@ packages: sprintf-js: 1.1.2 dev: false - /@achingbrain/nat-port-mapper@1.0.11: - resolution: {integrity: sha512-Y2lwx0zmrwEl+IGu+V/QiVBdcdsWscYq1PMMEjvyuuaXnmnppbLWilO8LK1yoLdncxwJBuS0zZtHbpFeWBusRg==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} + /@achingbrain/nat-port-mapper@1.0.12: + resolution: {integrity: sha512-rU4G75TEOTIPlkeDnPEVwx/VmMMFta42kY2SMmVobRkrtNLnxtU08Yhriu6tSBc9oO0wXdfNNeuLnNnEnL7w/A==} dependencies: - '@achingbrain/ssdp': 4.0.4 + '@achingbrain/ssdp': 4.0.6 '@libp2p/logger': 3.0.3 default-gateway: 7.2.2 err-code: 3.0.1 @@ -786,14 +803,13 @@ packages: - supports-color dev: false - /@achingbrain/ssdp@4.0.4: - resolution: {integrity: sha512-fY/ShiYJmhLdr45Vn2+f88xTqZjBSH3X3F+EJu/89cjB1JIkMCVtD5CQaaS38YknIL8cEcNhjMZM4cdE3ckSSQ==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} + /@achingbrain/ssdp@4.0.6: + resolution: {integrity: sha512-Y4JE2L9150i50V6lg/Y8+ilhxRpUZKKv+PKo68Aj7MjPfaUAar6ZHilF9h4/Zb3q0fqGMXNc9o11cQLNI8J8bA==} dependencies: event-iterator: 2.0.0 freeport-promise: 2.0.0 merge-options: 3.0.4 - xml2js: 0.5.0 + xml2js: 0.6.2 dev: false /@adobe/css-tools@4.3.1: @@ -803,10 +819,10 @@ packages: /@adraffy/ens-normalize@1.9.0: resolution: {integrity: sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ==} - /@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.8.3): + /@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.9.0): resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} dependencies: - '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.8.3) + '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.9.0) '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) transitivePeerDependencies: - '@algolia/client-search' @@ -814,13 +830,13 @@ packages: - search-insights dev: false - /@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.8.3): + /@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.9.0): resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==} peerDependencies: search-insights: '>= 1 < 3' dependencies: '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) - search-insights: 2.8.3 + search-insights: 2.9.0 transitivePeerDependencies: - '@algolia/client-search' - algoliasearch @@ -946,10 +962,10 @@ packages: engines: {node: '>=6.0.0'} dependencies: '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.19 + '@jridgewell/trace-mapping': 0.3.20 - /@apollo/client@3.8.5(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-/ueWC3f1pFeH+tWbM1phz6pzUGGijyml6oQ+LKUcQzpXF6tVFPrb6oUIUQCbZpr6Xmv/dtNiFDohc39ra7Solg==} + /@apollo/client@3.8.6(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-FnHg3vhQP8tQzgBs6oTJCFFIbovelDGYujj6MK7CJneiHf62TJstCIO0Ot4A1h7XrgFEtgl8a/OgajQWqrTuYw==} peerDependencies: graphql: ^16.6.0 graphql-ws: ^5.5.5 @@ -1005,7 +1021,7 @@ packages: '@babel/core': 7.23.2 '@babel/generator': 7.23.0 '@babel/parser': 7.23.0 - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@babel/traverse': 7.23.2 '@babel/types': 7.23.0 babel-preset-fbjs: 3.4.0(@babel/core@7.23.2) @@ -1040,21 +1056,21 @@ packages: resolution: {integrity: sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g==} dependencies: '@aws-crypto/util': 1.2.2 - '@aws-sdk/types': 3.425.0 + '@aws-sdk/types': 3.433.0 tslib: 1.14.1 /@aws-crypto/util@1.2.2: resolution: {integrity: sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg==} dependencies: - '@aws-sdk/types': 3.425.0 + '@aws-sdk/types': 3.433.0 '@aws-sdk/util-utf8-browser': 3.259.0 tslib: 1.14.1 - /@aws-sdk/types@3.425.0: - resolution: {integrity: sha512-6lqbmorwerN4v+J5dqbHPAsjynI0mkEF+blf+69QTaKKGaxBBVaXgqoqul9RXYcK5MMrrYRbQIMd0zYOoy90kA==} + /@aws-sdk/types@3.433.0: + resolution: {integrity: sha512-0jEE2mSrNDd8VGFjTc1otYrwYPIkzZJEIK90ZxisKvQ/EURGBhNzWn7ejWB9XCMFT6XumYLBR0V9qq5UPisWtA==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/types': 2.3.5 + '@smithy/types': 2.4.0 tslib: 2.6.2 /@aws-sdk/util-utf8-browser@3.259.0: @@ -1069,10 +1085,6 @@ packages: '@babel/highlight': 7.22.20 chalk: 2.4.2 - /@babel/compat-data@7.22.20: - resolution: {integrity: sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==} - engines: {node: '>=6.9.0'} - /@babel/compat-data@7.23.2: resolution: {integrity: sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==} engines: {node: '>=6.9.0'} @@ -1084,10 +1096,10 @@ packages: '@babel/code-frame': 7.22.13 '@babel/generator': 7.23.0 '@babel/helper-module-transforms': 7.23.0(@babel/core@7.12.9) - '@babel/helpers': 7.23.1 + '@babel/helpers': 7.23.2 '@babel/parser': 7.23.0 '@babel/template': 7.22.15 - '@babel/traverse': 7.23.0 + '@babel/traverse': 7.23.2 '@babel/types': 7.23.0 convert-source-map: 1.9.0 debug: 4.3.4(supports-color@8.1.1) @@ -1107,14 +1119,14 @@ packages: dependencies: '@ampproject/remapping': 2.2.1 '@babel/code-frame': 7.22.13 - '@babel/generator': 7.23.0 + '@babel/generator': 7.17.7 '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-module-transforms': 7.23.0(@babel/core@7.17.8) '@babel/helpers': 7.23.2 - '@babel/parser': 7.23.0 + '@babel/parser': 7.18.9 '@babel/template': 7.22.15 - '@babel/traverse': 7.23.2 - '@babel/types': 7.23.0 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 convert-source-map: 1.9.0 debug: 4.3.4(supports-color@8.1.1) gensync: 1.0.0-beta.2 @@ -1124,29 +1136,6 @@ packages: - supports-color dev: true - /@babel/core@7.23.0: - resolution: {integrity: sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.23.0 - '@babel/helper-compilation-targets': 7.22.15 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.0) - '@babel/helpers': 7.23.1 - '@babel/parser': 7.23.0 - '@babel/template': 7.22.15 - '@babel/traverse': 7.23.0 - '@babel/types': 7.23.0 - convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: false - /@babel/core@7.23.2: resolution: {integrity: sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==} engines: {node: '>=6.9.0'} @@ -1173,7 +1162,7 @@ packages: resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.0 + '@babel/types': 7.17.0 jsesc: 2.5.2 source-map: 0.5.7 dev: true @@ -1184,7 +1173,7 @@ packages: dependencies: '@babel/types': 7.23.0 '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.19 + '@jridgewell/trace-mapping': 0.3.20 jsesc: 2.5.2 /@babel/helper-annotate-as-pure@7.22.5: @@ -1209,24 +1198,6 @@ packages: lru-cache: 5.1.1 semver: 6.3.1 - /@babel/helper-create-class-features-plugin@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.0) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - semver: 6.3.1 - dev: false - /@babel/helper-create-class-features-plugin@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==} engines: {node: '>=6.9.0'} @@ -1244,18 +1215,6 @@ packages: '@babel/helper-split-export-declaration': 7.22.6 semver: 6.3.1 - /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-annotate-as-pure': 7.22.5 - regexpu-core: 5.3.2 - semver: 6.3.1 - dev: false - /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} engines: {node: '>=6.9.0'} @@ -1267,21 +1226,6 @@ packages: regexpu-core: 5.3.2 semver: 6.3.1 - /@babel/helper-define-polyfill-provider@0.4.3(@babel/core@7.23.0): - resolution: {integrity: sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-compilation-targets': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 - debug: 4.3.4(supports-color@8.1.1) - lodash.debounce: 4.0.8 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: false - /@babel/helper-define-polyfill-provider@0.4.3(@babel/core@7.23.2): resolution: {integrity: sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==} peerDependencies: @@ -1353,20 +1297,6 @@ packages: '@babel/helper-validator-identifier': 7.22.20 dev: true - /@babel/helper-module-transforms@7.23.0(@babel/core@7.23.0): - resolution: {integrity: sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - dev: false - /@babel/helper-module-transforms@7.23.0(@babel/core@7.23.2): resolution: {integrity: sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==} engines: {node: '>=6.9.0'} @@ -1394,18 +1324,6 @@ packages: resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} engines: {node: '>=6.9.0'} - /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.23.0): - resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-wrap-function': 7.22.20 - dev: false - /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.23.2): resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} engines: {node: '>=6.9.0'} @@ -1417,18 +1335,6 @@ packages: '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-wrap-function': 7.22.20 - /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.0): - resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - dev: false - /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.2): resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} engines: {node: '>=6.9.0'} @@ -1478,17 +1384,6 @@ packages: '@babel/template': 7.22.15 '@babel/types': 7.23.0 - /@babel/helpers@7.23.1: - resolution: {integrity: sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.15 - '@babel/traverse': 7.23.0 - '@babel/types': 7.23.0 - transitivePeerDependencies: - - supports-color - dev: false - /@babel/helpers@7.23.2: resolution: {integrity: sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==} engines: {node: '>=6.9.0'} @@ -1502,7 +1397,6 @@ packages: /@babel/highlight@7.22.20: resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} engines: {node: '>=6.9.0'} - requiresBuild: true dependencies: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 @@ -1513,7 +1407,7 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.23.0 + '@babel/types': 7.17.0 dev: true /@babel/parser@7.23.0: @@ -1523,16 +1417,6 @@ packages: dependencies: '@babel/types': 7.23.0 - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==} engines: {node: '>=6.9.0'} @@ -1542,18 +1426,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.23.0(@babel/core@7.23.0) - dev: false - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==} engines: {node: '>=6.9.0'} @@ -1628,7 +1500,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-plugin-utils': 7.10.4 '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.12.9) '@babel/plugin-transform-parameters': 7.22.15(@babel/core@7.12.9) dev: false @@ -1670,15 +1542,6 @@ packages: '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.2) - /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.0): - resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - dev: false - /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.2): resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} engines: {node: '>=6.9.0'} @@ -1687,15 +1550,6 @@ packages: dependencies: '@babel/core': 7.23.2 - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.23.0): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.23.2): resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: @@ -1712,15 +1566,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.23.0): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.23.2): resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: @@ -1729,16 +1574,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.23.0): - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.23.2): resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} engines: {node: '>=6.9.0'} @@ -1748,15 +1583,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.23.0): - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.23.2): resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: @@ -1774,15 +1600,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.23.0): - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.23.2): resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} peerDependencies: @@ -1800,16 +1617,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-import-assertions@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-import-assertions@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==} engines: {node: '>=6.9.0'} @@ -1819,16 +1626,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-import-attributes@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-import-attributes@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==} engines: {node: '>=6.9.0'} @@ -1838,15 +1635,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.0): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.2): resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: @@ -1855,15 +1643,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.23.0): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.23.2): resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: @@ -1881,16 +1660,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: false - /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} engines: {node: '>=6.9.0'} @@ -1900,15 +1669,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.23.0): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.23.2): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: @@ -1917,15 +1677,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.23.0): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.23.2): resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: @@ -1934,15 +1685,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.23.0): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.23.2): resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: @@ -1960,86 +1702,39 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: false - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.0): + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.2): resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.2): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.2): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.0): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.2): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.2): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.23.2): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.0): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.2): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.2 - '@babel/helper-plugin-utils': 7.22.5 - - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.23.0): - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.23.2): - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.2 - '@babel/helper-plugin-utils': 7.22.5 - - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.23.0): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.23.2): resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} @@ -2049,16 +1744,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} engines: {node: '>=6.9.0'} @@ -2068,17 +1753,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.23.0): - resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.23.2): resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} engines: {node: '>=6.9.0'} @@ -2089,16 +1763,6 @@ packages: '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-arrow-functions@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-arrow-functions@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==} engines: {node: '>=6.9.0'} @@ -2108,19 +1772,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-async-generator-functions@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.0) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-async-generator-functions@7.23.2(@babel/core@7.23.2): resolution: {integrity: sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==} engines: {node: '>=6.9.0'} @@ -2133,18 +1784,6 @@ packages: '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.2) '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.2) - /@babel/plugin-transform-async-to-generator@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-async-to-generator@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==} engines: {node: '>=6.9.0'} @@ -2156,16 +1795,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.2) - /@babel/plugin-transform-block-scoped-functions@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-block-scoped-functions@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==} engines: {node: '>=6.9.0'} @@ -2175,16 +1804,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-block-scoping@7.23.0(@babel/core@7.23.0): - resolution: {integrity: sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-block-scoping@7.23.0(@babel/core@7.23.2): resolution: {integrity: sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==} engines: {node: '>=6.9.0'} @@ -2194,17 +1813,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-class-properties@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-class-properties@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==} engines: {node: '>=6.9.0'} @@ -2215,18 +1823,6 @@ packages: '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-class-static-block@7.22.11(@babel/core@7.23.0): - resolution: {integrity: sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.12.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-class-static-block@7.22.11(@babel/core@7.23.2): resolution: {integrity: sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==} engines: {node: '>=6.9.0'} @@ -2238,24 +1834,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.2) - /@babel/plugin-transform-classes@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.22.15 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.0) - '@babel/helper-split-export-declaration': 7.22.6 - globals: 11.12.0 - dev: false - /@babel/plugin-transform-classes@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==} engines: {node: '>=6.9.0'} @@ -2273,17 +1851,6 @@ packages: '@babel/helper-split-export-declaration': 7.22.6 globals: 11.12.0 - /@babel/plugin-transform-computed-properties@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/template': 7.22.15 - dev: false - /@babel/plugin-transform-computed-properties@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==} engines: {node: '>=6.9.0'} @@ -2294,16 +1861,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/template': 7.22.15 - /@babel/plugin-transform-destructuring@7.23.0(@babel/core@7.23.0): - resolution: {integrity: sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-destructuring@7.23.0(@babel/core@7.23.2): resolution: {integrity: sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==} engines: {node: '>=6.9.0'} @@ -2313,17 +1870,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-dotall-regex@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-dotall-regex@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==} engines: {node: '>=6.9.0'} @@ -2334,16 +1880,6 @@ packages: '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-duplicate-keys@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-duplicate-keys@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==} engines: {node: '>=6.9.0'} @@ -2353,17 +1889,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-dynamic-import@7.22.11(@babel/core@7.23.0): - resolution: {integrity: sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-dynamic-import@7.22.11(@babel/core@7.23.2): resolution: {integrity: sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==} engines: {node: '>=6.9.0'} @@ -2374,17 +1899,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.2) - /@babel/plugin-transform-exponentiation-operator@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-exponentiation-operator@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==} engines: {node: '>=6.9.0'} @@ -2395,17 +1909,6 @@ packages: '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-export-namespace-from@7.22.11(@babel/core@7.23.0): - resolution: {integrity: sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-export-namespace-from@7.22.11(@babel/core@7.23.2): resolution: {integrity: sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==} engines: {node: '>=6.9.0'} @@ -2426,16 +1929,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.23.2) - /@babel/plugin-transform-for-of@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-for-of@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==} engines: {node: '>=6.9.0'} @@ -2445,18 +1938,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-function-name@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-compilation-targets': 7.22.15 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-function-name@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==} engines: {node: '>=6.9.0'} @@ -2468,17 +1949,6 @@ packages: '@babel/helper-function-name': 7.23.0 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-json-strings@7.22.11(@babel/core@7.23.0): - resolution: {integrity: sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-json-strings@7.22.11(@babel/core@7.23.2): resolution: {integrity: sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==} engines: {node: '>=6.9.0'} @@ -2489,16 +1959,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.2) - /@babel/plugin-transform-literals@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-literals@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==} engines: {node: '>=6.9.0'} @@ -2508,17 +1968,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-logical-assignment-operators@7.22.11(@babel/core@7.23.0): - resolution: {integrity: sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-logical-assignment-operators@7.22.11(@babel/core@7.23.2): resolution: {integrity: sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==} engines: {node: '>=6.9.0'} @@ -2529,16 +1978,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.2) - /@babel/plugin-transform-member-expression-literals@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-member-expression-literals@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==} engines: {node: '>=6.9.0'} @@ -2548,17 +1987,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-modules-amd@7.23.0(@babel/core@7.23.0): - resolution: {integrity: sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-modules-amd@7.23.0(@babel/core@7.23.2): resolution: {integrity: sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==} engines: {node: '>=6.9.0'} @@ -2569,18 +1997,6 @@ packages: '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-modules-commonjs@7.23.0(@babel/core@7.23.0): - resolution: {integrity: sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-simple-access': 7.22.5 - dev: false - /@babel/plugin-transform-modules-commonjs@7.23.0(@babel/core@7.23.2): resolution: {integrity: sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==} engines: {node: '>=6.9.0'} @@ -2592,19 +2008,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-simple-access': 7.22.5 - /@babel/plugin-transform-modules-systemjs@7.23.0(@babel/core@7.23.0): - resolution: {integrity: sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-identifier': 7.22.20 - dev: false - /@babel/plugin-transform-modules-systemjs@7.23.0(@babel/core@7.23.2): resolution: {integrity: sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==} engines: {node: '>=6.9.0'} @@ -2617,17 +2020,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-validator-identifier': 7.22.20 - /@babel/plugin-transform-modules-umd@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-modules-umd@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==} engines: {node: '>=6.9.0'} @@ -2638,17 +2030,6 @@ packages: '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} engines: {node: '>=6.9.0'} @@ -2659,16 +2040,6 @@ packages: '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-new-target@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-new-target@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==} engines: {node: '>=6.9.0'} @@ -2678,17 +2049,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-nullish-coalescing-operator@7.22.11(@babel/core@7.23.0): - resolution: {integrity: sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-nullish-coalescing-operator@7.22.11(@babel/core@7.23.2): resolution: {integrity: sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==} engines: {node: '>=6.9.0'} @@ -2699,17 +2059,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.2) - /@babel/plugin-transform-numeric-separator@7.22.11(@babel/core@7.23.0): - resolution: {integrity: sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-numeric-separator@7.22.11(@babel/core@7.23.2): resolution: {integrity: sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==} engines: {node: '>=6.9.0'} @@ -2720,44 +2069,19 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.2) - /@babel/plugin-transform-object-rest-spread@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.22.20 - '@babel/core': 7.23.0 - '@babel/helper-compilation-targets': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.0) - '@babel/plugin-transform-parameters': 7.22.15(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-object-rest-spread@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.22.20 + '@babel/compat-data': 7.23.2 '@babel/core': 7.23.2 '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.2) '@babel/plugin-transform-parameters': 7.22.15(@babel/core@7.23.2) - /@babel/plugin-transform-object-super@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-object-super@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==} engines: {node: '>=6.9.0'} @@ -2768,17 +2092,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.2) - /@babel/plugin-transform-optional-catch-binding@7.22.11(@babel/core@7.23.0): - resolution: {integrity: sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-optional-catch-binding@7.22.11(@babel/core@7.23.2): resolution: {integrity: sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==} engines: {node: '>=6.9.0'} @@ -2789,18 +2102,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.2) - /@babel/plugin-transform-optional-chaining@7.23.0(@babel/core@7.23.0): - resolution: {integrity: sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-optional-chaining@7.23.0(@babel/core@7.23.2): resolution: {integrity: sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==} engines: {node: '>=6.9.0'} @@ -2822,16 +2123,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: false - /@babel/plugin-transform-parameters@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-parameters@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==} engines: {node: '>=6.9.0'} @@ -2841,17 +2132,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-private-methods@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-private-methods@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==} engines: {node: '>=6.9.0'} @@ -2862,19 +2142,6 @@ packages: '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-private-property-in-object@7.22.11(@babel/core@7.23.0): - resolution: {integrity: sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.0) - dev: false - /@babel/plugin-transform-private-property-in-object@7.22.11(@babel/core@7.23.2): resolution: {integrity: sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==} engines: {node: '>=6.9.0'} @@ -2887,16 +2154,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.2) - /@babel/plugin-transform-property-literals@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-property-literals@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==} engines: {node: '>=6.9.0'} @@ -2906,23 +2163,13 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-react-constant-elements@7.22.5(@babel/core@7.23.0): + /@babel/plugin-transform-react-constant-elements@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - - /@babel/plugin-transform-react-display-name@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 dev: false @@ -2935,14 +2182,14 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.23.0): + /@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 - '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.0) + '@babel/core': 7.23.2 + '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.2) dev: false /@babel/plugin-transform-react-jsx-self@7.22.5(@babel/core@7.23.2): @@ -2963,20 +2210,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-react-jsx@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.0) - '@babel/types': 7.23.0 - dev: false - /@babel/plugin-transform-react-jsx@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==} engines: {node: '>=6.9.0'} @@ -2990,28 +2223,17 @@ packages: '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.2) '@babel/types': 7.23.0 - /@babel/plugin-transform-react-pure-annotations@7.22.5(@babel/core@7.23.0): + /@babel/plugin-transform-react-pure-annotations@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 dev: false - /@babel/plugin-transform-regenerator@7.22.10(@babel/core@7.23.0): - resolution: {integrity: sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - regenerator-transform: 0.15.2 - dev: false - /@babel/plugin-transform-regenerator@7.22.10(@babel/core@7.23.2): resolution: {integrity: sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==} engines: {node: '>=6.9.0'} @@ -3022,16 +2244,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 regenerator-transform: 0.15.2 - /@babel/plugin-transform-reserved-words@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-reserved-words@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==} engines: {node: '>=6.9.0'} @@ -3041,25 +2253,8 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-runtime@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-tEVLhk8NRZSmwQ0DJtxxhTrCht1HVo8VaMzYT4w6lwyKBuHsgoioAUA7/6eT2fRfc5/23fuGdlwIxXhRVgWr4g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 - babel-plugin-polyfill-corejs2: 0.4.6(@babel/core@7.23.0) - babel-plugin-polyfill-corejs3: 0.8.5(@babel/core@7.23.0) - babel-plugin-polyfill-regenerator: 0.5.3(@babel/core@7.23.0) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: false - - /@babel/plugin-transform-runtime@7.22.15(@babel/core@7.23.2): - resolution: {integrity: sha512-tEVLhk8NRZSmwQ0DJtxxhTrCht1HVo8VaMzYT4w6lwyKBuHsgoioAUA7/6eT2fRfc5/23fuGdlwIxXhRVgWr4g==} + /@babel/plugin-transform-runtime@7.23.2(@babel/core@7.23.2): + resolution: {integrity: sha512-XOntj6icgzMS58jPVtQpiuF6ZFWxQiJavISGx5KGjRj+3gqZr8+N6Kx+N9BApWzgS+DOjIZfXXj0ZesenOWDyA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -3068,22 +2263,12 @@ packages: '@babel/helper-module-imports': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 babel-plugin-polyfill-corejs2: 0.4.6(@babel/core@7.23.2) - babel-plugin-polyfill-corejs3: 0.8.5(@babel/core@7.23.2) + babel-plugin-polyfill-corejs3: 0.8.6(@babel/core@7.23.2) babel-plugin-polyfill-regenerator: 0.5.3(@babel/core@7.23.2) semver: 6.3.1 transitivePeerDependencies: - supports-color - /@babel/plugin-transform-shorthand-properties@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-shorthand-properties@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==} engines: {node: '>=6.9.0'} @@ -3093,17 +2278,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-spread@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - dev: false - /@babel/plugin-transform-spread@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==} engines: {node: '>=6.9.0'} @@ -3114,16 +2288,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - /@babel/plugin-transform-sticky-regex@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-sticky-regex@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==} engines: {node: '>=6.9.0'} @@ -3133,16 +2297,6 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-template-literals@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-template-literals@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==} engines: {node: '>=6.9.0'} @@ -3152,62 +2306,8 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-typeof-symbol@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - - /@babel/plugin-transform-typeof-symbol@7.22.5(@babel/core@7.23.2): - resolution: {integrity: sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.2 - '@babel/helper-plugin-utils': 7.22.5 - - /@babel/plugin-transform-typescript@7.22.15(@babel/core@7.23.0): - resolution: {integrity: sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.23.0) - dev: false - - /@babel/plugin-transform-typescript@7.22.15(@babel/core@7.23.2): - resolution: {integrity: sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.2 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.2) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.23.2) - - /@babel/plugin-transform-unicode-escapes@7.22.10(@babel/core@7.23.0): - resolution: {integrity: sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - dev: false - - /@babel/plugin-transform-unicode-escapes@7.22.10(@babel/core@7.23.2): - resolution: {integrity: sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==} + /@babel/plugin-transform-typeof-symbol@7.22.5(@babel/core@7.23.2): + resolution: {integrity: sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -3215,37 +2315,36 @@ packages: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-unicode-property-regex@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==} + /@babel/plugin-transform-typescript@7.22.15(@babel/core@7.23.2): + resolution: {integrity: sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.0) + '@babel/core': 7.23.2 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - dev: false + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.23.2) - /@babel/plugin-transform-unicode-property-regex@7.22.5(@babel/core@7.23.2): - resolution: {integrity: sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==} + /@babel/plugin-transform-unicode-escapes@7.22.10(@babel/core@7.23.2): + resolution: {integrity: sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.23.2 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-unicode-regex@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==} + /@babel/plugin-transform-unicode-property-regex@7.22.5(@babel/core@7.23.2): + resolution: {integrity: sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.0) + '@babel/core': 7.23.2 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - dev: false /@babel/plugin-transform-unicode-regex@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==} @@ -3257,17 +2356,6 @@ packages: '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-transform-unicode-sets-regex@7.22.5(@babel/core@7.23.0): - resolution: {integrity: sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.0) - '@babel/helper-plugin-utils': 7.22.5 - dev: false - /@babel/plugin-transform-unicode-sets-regex@7.22.5(@babel/core@7.23.2): resolution: {integrity: sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==} engines: {node: '>=6.9.0'} @@ -3278,97 +2366,6 @@ packages: '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.22.5 - /@babel/preset-env@7.22.20(@babel/core@7.23.0): - resolution: {integrity: sha512-11MY04gGC4kSzlPHRfvVkNAZhUxOvm7DCJ37hPDnUENwe06npjIRAfInEMTGSb4LZK5ZgDFkv5hw0lGebHeTyg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.22.20 - '@babel/core': 7.23.0 - '@babel/helper-compilation-targets': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.22.15 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.22.15(@babel/core@7.23.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.22.15(@babel/core@7.23.0) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.0) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.0) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.23.0) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.0) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.0) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.23.0) - '@babel/plugin-syntax-import-assertions': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-syntax-import-attributes': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.23.0) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.0) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.0) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.0) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.0) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.0) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.0) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.0) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.0) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.23.0) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.23.0) - '@babel/plugin-transform-arrow-functions': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-async-generator-functions': 7.22.15(@babel/core@7.23.0) - '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-block-scoped-functions': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-block-scoping': 7.23.0(@babel/core@7.23.0) - '@babel/plugin-transform-class-properties': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-class-static-block': 7.22.11(@babel/core@7.23.0) - '@babel/plugin-transform-classes': 7.22.15(@babel/core@7.23.0) - '@babel/plugin-transform-computed-properties': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-destructuring': 7.23.0(@babel/core@7.23.0) - '@babel/plugin-transform-dotall-regex': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-duplicate-keys': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-dynamic-import': 7.22.11(@babel/core@7.23.0) - '@babel/plugin-transform-exponentiation-operator': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-export-namespace-from': 7.22.11(@babel/core@7.23.0) - '@babel/plugin-transform-for-of': 7.22.15(@babel/core@7.23.0) - '@babel/plugin-transform-function-name': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-json-strings': 7.22.11(@babel/core@7.23.0) - '@babel/plugin-transform-literals': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-logical-assignment-operators': 7.22.11(@babel/core@7.23.0) - '@babel/plugin-transform-member-expression-literals': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-modules-amd': 7.23.0(@babel/core@7.23.0) - '@babel/plugin-transform-modules-commonjs': 7.23.0(@babel/core@7.23.0) - '@babel/plugin-transform-modules-systemjs': 7.23.0(@babel/core@7.23.0) - '@babel/plugin-transform-modules-umd': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-new-target': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.22.11(@babel/core@7.23.0) - '@babel/plugin-transform-numeric-separator': 7.22.11(@babel/core@7.23.0) - '@babel/plugin-transform-object-rest-spread': 7.22.15(@babel/core@7.23.0) - '@babel/plugin-transform-object-super': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-optional-catch-binding': 7.22.11(@babel/core@7.23.0) - '@babel/plugin-transform-optional-chaining': 7.23.0(@babel/core@7.23.0) - '@babel/plugin-transform-parameters': 7.22.15(@babel/core@7.23.0) - '@babel/plugin-transform-private-methods': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-private-property-in-object': 7.22.11(@babel/core@7.23.0) - '@babel/plugin-transform-property-literals': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-regenerator': 7.22.10(@babel/core@7.23.0) - '@babel/plugin-transform-reserved-words': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-shorthand-properties': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-spread': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-sticky-regex': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-template-literals': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-typeof-symbol': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-unicode-escapes': 7.22.10(@babel/core@7.23.0) - '@babel/plugin-transform-unicode-property-regex': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-unicode-regex': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-unicode-sets-regex': 7.22.5(@babel/core@7.23.0) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.23.0) - '@babel/types': 7.23.0 - babel-plugin-polyfill-corejs2: 0.4.6(@babel/core@7.23.0) - babel-plugin-polyfill-corejs3: 0.8.5(@babel/core@7.23.0) - babel-plugin-polyfill-regenerator: 0.5.3(@babel/core@7.23.0) - core-js-compat: 3.33.0 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: false - /@babel/preset-env@7.23.2(@babel/core@7.23.2): resolution: {integrity: sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==} engines: {node: '>=6.9.0'} @@ -3452,9 +2449,9 @@ packages: '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.23.2) '@babel/types': 7.23.0 babel-plugin-polyfill-corejs2: 0.4.6(@babel/core@7.23.2) - babel-plugin-polyfill-corejs3: 0.8.5(@babel/core@7.23.2) + babel-plugin-polyfill-corejs3: 0.8.6(@babel/core@7.23.2) babel-plugin-polyfill-regenerator: 0.5.3(@babel/core@7.23.2) - core-js-compat: 3.33.0 + core-js-compat: 3.33.1 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -3470,17 +2467,6 @@ packages: '@babel/helper-validator-option': 7.22.15 '@babel/plugin-transform-flow-strip-types': 7.22.5(@babel/core@7.23.2) - /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.23.0): - resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} - peerDependencies: - '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/types': 7.23.0 - esutils: 2.0.3 - dev: false - /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.23.2): resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} peerDependencies: @@ -3491,33 +2477,19 @@ packages: '@babel/types': 7.23.0 esutils: 2.0.3 - /@babel/preset-react@7.22.15(@babel/core@7.23.0): + /@babel/preset-react@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-Csy1IJ2uEh/PecCBXXoZGAZBeCATTuePzCSB7dLYWS0vOEj6CNpjxIhW4duWwZodBNueH7QO14WbGn8YyeuN9w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.22.15 - '@babel/plugin-transform-react-display-name': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.0) - '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-react-pure-annotations': 7.22.5(@babel/core@7.23.0) - dev: false - - /@babel/preset-typescript@7.23.0(@babel/core@7.23.0): - resolution: {integrity: sha512-6P6VVa/NM/VlAYj5s2Aq/gdVg8FSENCg3wlZ6Qau9AcPaoF5LbN1nyGlR9DTRIw9PpxI94e+ReydsJHcjwAweg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-validator-option': 7.22.15 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.0) - '@babel/plugin-transform-modules-commonjs': 7.23.0(@babel/core@7.23.0) - '@babel/plugin-transform-typescript': 7.22.15(@babel/core@7.23.0) + '@babel/plugin-transform-react-display-name': 7.22.5(@babel/core@7.23.2) + '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.2) + '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.23.2) + '@babel/plugin-transform-react-pure-annotations': 7.22.5(@babel/core@7.23.2) dev: false /@babel/preset-typescript@7.23.2(@babel/core@7.23.2): @@ -3549,15 +2521,15 @@ packages: /@babel/regjsgen@0.8.0: resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - /@babel/runtime-corejs3@7.23.1: - resolution: {integrity: sha512-OKKfytwoc0tr7cDHwQm0RLVR3y+hDGFz3EPuvLNU/0fOeXJeKNIHj7ffNVFnncWt3sC58uyUCRSzf8nBQbyF6A==} + /@babel/runtime-corejs3@7.23.2: + resolution: {integrity: sha512-54cIh74Z1rp4oIjsHjqN+WM4fMyCBYe+LpZ9jWm51CZ1fbH3SkAzQD/3XLoNkjbJ7YEmjobLXyvQrFypRHOrXw==} engines: {node: '>=6.9.0'} dependencies: - core-js-pure: 3.33.0 + core-js-pure: 3.33.1 regenerator-runtime: 0.14.0 - /@babel/runtime@7.23.1: - resolution: {integrity: sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==} + /@babel/runtime@7.23.2: + resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.0 @@ -3575,37 +2547,19 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.22.13 - '@babel/generator': 7.23.0 + '@babel/generator': 7.17.7 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-function-name': 7.23.0 '@babel/helper-hoist-variables': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.0 - '@babel/types': 7.23.0 + '@babel/parser': 7.18.9 + '@babel/types': 7.17.0 debug: 4.3.4(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color dev: true - /@babel/traverse@7.23.0: - resolution: {integrity: sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.23.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.0 - '@babel/types': 7.23.0 - debug: 4.3.4(supports-color@8.1.1) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: false - /@babel/traverse@7.23.2: resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} engines: {node: '>=6.9.0'} @@ -3644,7 +2598,7 @@ packages: engines: {node: '>= 16'} dependencies: '@jsdevtools/ono': 7.1.3 - '@types/json-schema': 7.0.13 + '@types/json-schema': 7.0.14 call-me-maybe: 1.0.2 js-yaml: 4.1.0 dev: true @@ -3656,6 +2610,31 @@ packages: resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==} dev: false + /@celo/rainbowkit-celo@1.1.0(@rainbow-me/rainbowkit@1.0.8)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(wagmi@1.3.9)(zod@3.22.4): + resolution: {integrity: sha512-/G4HFhJNwUk6uU1yqGfQ/LIoNg9UAA4BUcEvFdd0M3DImnKlhodNLUdCmzqv96sjc/I7tMJqBeTnmbhwXdlsjQ==} + peerDependencies: + '@rainbow-me/rainbowkit': '>=1.0.2 && <=2.0.0' + viem: '>=1.2.8 && <=2.0.0' + wagmi: '>=1.0.0 && <=2.0.0' + dependencies: + '@metamask/providers': 11.1.2 + '@rainbow-me/rainbowkit': 1.0.8(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9) + '@wagmi/connectors': 2.6.6(@wagmi/chains@1.6.0)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) + wagmi: 1.3.9(@types/react@18.2.31)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - '@wagmi/chains' + - bufferutil + - encoding + - lokijs + - react + - supports-color + - typescript + - utf-8-validate + - zod + dev: false + /@chainsafe/as-sha256@0.3.1: resolution: {integrity: sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==} @@ -3756,8 +2735,8 @@ packages: mime: 3.0.0 dev: true - /@cloudflare/workers-types@4.20231002.0: - resolution: {integrity: sha512-gQMKf3THqAFWH426OXXfVx0gFLXiSiL2fo6mKjQYx4PU74MgmVDFh25NvpAIBK+XN+xXlrImClfYeqErXIT7jA==} + /@cloudflare/workers-types@4.20231016.0: + resolution: {integrity: sha512-eGB0cRVyoJpeyGJx2re5sbd9R316a61sY73xwnqm4cwGpb+OxCK2gc651RxGiN7H4w6LY1RpysUgeGLmj5B3+g==} dev: true /@coinbase/wallet-sdk@3.7.2: @@ -3765,7 +2744,7 @@ packages: engines: {node: '>= 10.0.0'} dependencies: '@metamask/safe-event-emitter': 2.0.0 - '@solana/web3.js': 1.87.1 + '@solana/web3.js': 1.87.2 bind-decorator: 1.0.11 bn.js: 5.2.1 buffer: 6.0.3 @@ -3776,7 +2755,7 @@ packages: json-rpc-engine: 6.1.0 keccak: 3.0.4 preact: 10.18.1 - qs: 6.11.0 + qs: 6.11.2 rxjs: 6.6.7 sha.js: 2.4.11 stream-browserify: 3.0.0 @@ -3794,16 +2773,16 @@ packages: requiresBuild: true optional: true - /@commitlint/cli@17.8.0: - resolution: {integrity: sha512-D3LdyZYbiRyAChfJMNlAd9f2P9vNQ7GWbI9gN2o7L5hF07QJDqj4z/pcJF3PjDbJWOaUUXla287RdDmmKqH2WQ==} + /@commitlint/cli@17.8.1: + resolution: {integrity: sha512-ay+WbzQesE0Rv4EQKfNbSMiJJ12KdKTDzIt0tcK4k11FdsWmtwP0Kp1NWMOUswfIWo6Eb7p7Ln721Nx9FLNBjg==} engines: {node: '>=v14'} hasBin: true dependencies: - '@commitlint/format': 17.4.4 - '@commitlint/lint': 17.8.0 - '@commitlint/load': 17.8.0 - '@commitlint/read': 17.5.1 - '@commitlint/types': 17.4.4 + '@commitlint/format': 17.8.1 + '@commitlint/lint': 17.8.1 + '@commitlint/load': 17.8.1 + '@commitlint/read': 17.8.1 + '@commitlint/types': 17.8.1 execa: 5.1.1 lodash.isfunction: 3.0.9 resolve-from: 5.0.0 @@ -3814,27 +2793,36 @@ packages: - '@swc/wasm' dev: true - /@commitlint/config-conventional@17.8.0: - resolution: {integrity: sha512-MgiFXujmqAvi7M33C7OSMTznwrVkckrbXe/aZWQ/+KFGLLF6IE50XIcjGrW0/uiDGb/im5qbqF2dh1dCFNa+sQ==} + /@commitlint/config-conventional@17.8.1: + resolution: {integrity: sha512-NxCOHx1kgneig3VLauWJcDWS40DVjg7nKOpBEEK9E5fjJpQqLCilcnKkIIjdBH98kEO1q3NpE5NSrZ2kl/QGJg==} engines: {node: '>=v14'} dependencies: conventional-changelog-conventionalcommits: 6.1.0 dev: true - /@commitlint/config-validator@17.6.7: - resolution: {integrity: sha512-vJSncmnzwMvpr3lIcm0I8YVVDJTzyjy7NZAeXbTXy+MPUdAr9pKyyg7Tx/ebOQ9kqzE6O9WT6jg2164br5UdsQ==} + /@commitlint/config-validator@17.8.1: + resolution: {integrity: sha512-UUgUC+sNiiMwkyiuIFR7JG2cfd9t/7MV8VB4TZ+q02ZFkHoduUS4tJGsCBWvBOGD9Btev6IecPMvlWUfJorkEA==} engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.8.1 + ajv: 8.12.0 + dev: true + + /@commitlint/config-validator@18.0.0: + resolution: {integrity: sha512-PlXy5QZzQeMgQM7jb0odIhxsI6GWcbGgfy+Hkz5ap31KES/oJgtEvgD8pjg0Z9Ri296bT6zK3ts6brS0MAcMgg==} + engines: {node: '>=v18'} requiresBuild: true dependencies: - '@commitlint/types': 17.4.4 + '@commitlint/types': 18.0.0 ajv: 8.12.0 dev: true + optional: true - /@commitlint/ensure@17.6.7: - resolution: {integrity: sha512-mfDJOd1/O/eIb/h4qwXzUxkmskXDL9vNPnZ4AKYKiZALz4vHzwMxBSYtyL2mUIDeU9DRSpEUins8SeKtFkYHSw==} + /@commitlint/ensure@17.8.1: + resolution: {integrity: sha512-xjafwKxid8s1K23NFpL8JNo6JnY/ysetKo8kegVM7c8vs+kWLP8VrQq+NbhgVlmCojhEDbzQKp4eRXSjVOGsow==} engines: {node: '>=v14'} dependencies: - '@commitlint/types': 17.4.4 + '@commitlint/types': 17.8.1 lodash.camelcase: 4.3.0 lodash.kebabcase: 4.1.1 lodash.snakecase: 4.1.1 @@ -3842,46 +2830,52 @@ packages: lodash.upperfirst: 4.3.1 dev: true - /@commitlint/execute-rule@17.4.0: - resolution: {integrity: sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==} + /@commitlint/execute-rule@17.8.1: + resolution: {integrity: sha512-JHVupQeSdNI6xzA9SqMF+p/JjrHTcrJdI02PwesQIDCIGUrv04hicJgCcws5nzaoZbROapPs0s6zeVHoxpMwFQ==} engines: {node: '>=v14'} + dev: true + + /@commitlint/execute-rule@18.0.0: + resolution: {integrity: sha512-eNUSaHajb+g3sgZeIrfc6cXNnKIkYN2SXtDVXuiE+hOa055T0bLdZK29gSd945JCztxPVwdOkPLDeLg3NfDubg==} + engines: {node: '>=v18'} requiresBuild: true dev: true + optional: true - /@commitlint/format@17.4.4: - resolution: {integrity: sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ==} + /@commitlint/format@17.8.1: + resolution: {integrity: sha512-f3oMTyZ84M9ht7fb93wbCKmWxO5/kKSbwuYvS867duVomoOsgrgljkGGIztmT/srZnaiGbaK8+Wf8Ik2tSr5eg==} engines: {node: '>=v14'} dependencies: - '@commitlint/types': 17.4.4 + '@commitlint/types': 17.8.1 chalk: 4.1.2 dev: true - /@commitlint/is-ignored@17.8.0: - resolution: {integrity: sha512-8bR6rxNcWaNprPBdE4ePIOwbxutTQGOsRPYWssX+zjGxnEljzaZSGzFUOMxapYILlf8Tts/O1wPQgG549Rdvdg==} + /@commitlint/is-ignored@17.8.1: + resolution: {integrity: sha512-UshMi4Ltb4ZlNn4F7WtSEugFDZmctzFpmbqvpyxD3la510J+PLcnyhf9chs7EryaRFJMdAKwsEKfNK0jL/QM4g==} engines: {node: '>=v14'} dependencies: - '@commitlint/types': 17.4.4 + '@commitlint/types': 17.8.1 semver: 7.5.4 dev: true - /@commitlint/lint@17.8.0: - resolution: {integrity: sha512-4ihwnqOY4TcJN6iz5Jv1LeYavvBllONwFyGxOIWmCT5s4PNMb43cws2TUdbXTZL1Vq59etGKd5LWYDFPVbs5EA==} + /@commitlint/lint@17.8.1: + resolution: {integrity: sha512-aQUlwIR1/VMv2D4GXSk7PfL5hIaFSfy6hSHV94O8Y27T5q+DlDEgd/cZ4KmVI+MWKzFfCTiTuWqjfRSfdRllCA==} engines: {node: '>=v14'} dependencies: - '@commitlint/is-ignored': 17.8.0 - '@commitlint/parse': 17.7.0 - '@commitlint/rules': 17.7.0 - '@commitlint/types': 17.4.4 + '@commitlint/is-ignored': 17.8.1 + '@commitlint/parse': 17.8.1 + '@commitlint/rules': 17.8.1 + '@commitlint/types': 17.8.1 dev: true - /@commitlint/load@17.8.0: - resolution: {integrity: sha512-9VnGXYJCP4tXmR4YrwP8n5oX6T5ZsHfPQq6WuUQOvAI+QsDQMaTGgTRXr7us+xsjz+b+mMBSagogqfUx2aixyw==} + /@commitlint/load@17.8.1: + resolution: {integrity: sha512-iF4CL7KDFstP1kpVUkT8K2Wl17h2yx9VaR1ztTc8vzByWWcbO/WaKwxsnCOqow9tVAlzPfo1ywk9m2oJ9ucMqA==} engines: {node: '>=v14'} dependencies: - '@commitlint/config-validator': 17.6.7 - '@commitlint/execute-rule': 17.4.0 - '@commitlint/resolve-extends': 17.6.7 - '@commitlint/types': 17.4.4 + '@commitlint/config-validator': 17.8.1 + '@commitlint/execute-rule': 17.8.1 + '@commitlint/resolve-extends': 17.8.1 + '@commitlint/types': 17.8.1 '@types/node': 20.5.1 chalk: 4.1.2 cosmiconfig: 8.3.6(typescript@4.9.5) @@ -3897,82 +2891,129 @@ packages: - '@swc/wasm' dev: true - /@commitlint/message@17.4.2: - resolution: {integrity: sha512-3XMNbzB+3bhKA1hSAWPCQA3lNxR4zaeQAQcHj0Hx5sVdO6ryXtgUBGGv+1ZCLMgAPRixuc6en+iNAzZ4NzAa8Q==} + /@commitlint/load@18.0.0: + resolution: {integrity: sha512-ocvMSkzNZCJ4yV673xjd4Y7sFVG/mg7S6yvL5ioM0OIG2XTbcCdzpmq+BeJcIwsRYU9g/b688yh7RDzGlbai6w==} + engines: {node: '>=v18'} + requiresBuild: true + dependencies: + '@commitlint/config-validator': 18.0.0 + '@commitlint/execute-rule': 18.0.0 + '@commitlint/resolve-extends': 18.0.0 + '@commitlint/types': 18.0.0 + '@types/node': 18.18.6 + chalk: 4.1.2 + cosmiconfig: 8.3.6(typescript@5.2.2) + cosmiconfig-typescript-loader: 4.4.0(@types/node@18.18.6)(cosmiconfig@8.3.6)(ts-node@10.9.1)(typescript@5.2.2) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + resolve-from: 5.0.0 + ts-node: 10.9.1(@types/node@18.18.6)(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + dev: true + optional: true + + /@commitlint/message@17.8.1: + resolution: {integrity: sha512-6bYL1GUQsD6bLhTH3QQty8pVFoETfFQlMn2Nzmz3AOLqRVfNNtXBaSY0dhZ0dM6A2MEq4+2d7L/2LP8TjqGRkA==} engines: {node: '>=v14'} dev: true - /@commitlint/parse@17.7.0: - resolution: {integrity: sha512-dIvFNUMCUHqq5Abv80mIEjLVfw8QNuA4DS7OWip4pcK/3h5wggmjVnlwGCDvDChkw2TjK1K6O+tAEV78oxjxag==} + /@commitlint/parse@17.8.1: + resolution: {integrity: sha512-/wLUickTo0rNpQgWwLPavTm7WbwkZoBy3X8PpkUmlSmQJyWQTj0m6bDjiykMaDt41qcUbfeFfaCvXfiR4EGnfw==} engines: {node: '>=v14'} dependencies: - '@commitlint/types': 17.4.4 + '@commitlint/types': 17.8.1 conventional-changelog-angular: 6.0.0 conventional-commits-parser: 4.0.0 dev: true - /@commitlint/read@17.5.1: - resolution: {integrity: sha512-7IhfvEvB//p9aYW09YVclHbdf1u7g7QhxeYW9ZHSO8Huzp8Rz7m05aCO1mFG7G8M+7yfFnXB5xOmG18brqQIBg==} + /@commitlint/read@17.8.1: + resolution: {integrity: sha512-Fd55Oaz9irzBESPCdMd8vWWgxsW3OWR99wOntBDHgf9h7Y6OOHjWEdS9Xzen1GFndqgyoaFplQS5y7KZe0kO2w==} engines: {node: '>=v14'} dependencies: - '@commitlint/top-level': 17.4.0 - '@commitlint/types': 17.4.4 + '@commitlint/top-level': 17.8.1 + '@commitlint/types': 17.8.1 fs-extra: 11.1.1 git-raw-commits: 2.0.11 minimist: 1.2.8 dev: true - /@commitlint/resolve-extends@17.6.7: - resolution: {integrity: sha512-PfeoAwLHtbOaC9bGn/FADN156CqkFz6ZKiVDMjuC2N5N0740Ke56rKU7Wxdwya8R8xzLK9vZzHgNbuGhaOVKIg==} + /@commitlint/resolve-extends@17.8.1: + resolution: {integrity: sha512-W/ryRoQ0TSVXqJrx5SGkaYuAaE/BUontL1j1HsKckvM6e5ZaG0M9126zcwL6peKSuIetJi7E87PRQF8O86EW0Q==} engines: {node: '>=v14'} + dependencies: + '@commitlint/config-validator': 17.8.1 + '@commitlint/types': 17.8.1 + import-fresh: 3.3.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + resolve-global: 1.0.0 + dev: true + + /@commitlint/resolve-extends@18.0.0: + resolution: {integrity: sha512-MD9+6GSiWvqgdJtfos+1gqz+zmy2vV7TbUVz2ETZzpfECgmUZSZSYzyivivBAQK6feS71KxmMLL8+YFF9+FFRQ==} + engines: {node: '>=v18'} requiresBuild: true dependencies: - '@commitlint/config-validator': 17.6.7 - '@commitlint/types': 17.4.4 + '@commitlint/config-validator': 18.0.0 + '@commitlint/types': 18.0.0 import-fresh: 3.3.0 lodash.mergewith: 4.6.2 resolve-from: 5.0.0 resolve-global: 1.0.0 dev: true + optional: true - /@commitlint/rules@17.7.0: - resolution: {integrity: sha512-J3qTh0+ilUE5folSaoK91ByOb8XeQjiGcdIdiB/8UT1/Rd1itKo0ju/eQVGyFzgTMYt8HrDJnGTmNWwcMR1rmA==} + /@commitlint/rules@17.8.1: + resolution: {integrity: sha512-2b7OdVbN7MTAt9U0vKOYKCDsOvESVXxQmrvuVUZ0rGFMCrCPJWWP1GJ7f0lAypbDAhaGb8zqtdOr47192LBrIA==} engines: {node: '>=v14'} dependencies: - '@commitlint/ensure': 17.6.7 - '@commitlint/message': 17.4.2 - '@commitlint/to-lines': 17.4.0 - '@commitlint/types': 17.4.4 + '@commitlint/ensure': 17.8.1 + '@commitlint/message': 17.8.1 + '@commitlint/to-lines': 17.8.1 + '@commitlint/types': 17.8.1 execa: 5.1.1 dev: true - /@commitlint/to-lines@17.4.0: - resolution: {integrity: sha512-LcIy/6ZZolsfwDUWfN1mJ+co09soSuNASfKEU5sCmgFCvX5iHwRYLiIuoqXzOVDYOy7E7IcHilr/KS0e5T+0Hg==} + /@commitlint/to-lines@17.8.1: + resolution: {integrity: sha512-LE0jb8CuR/mj6xJyrIk8VLz03OEzXFgLdivBytoooKO5xLt5yalc8Ma5guTWobw998sbR3ogDd+2jed03CFmJA==} engines: {node: '>=v14'} dev: true - /@commitlint/top-level@17.4.0: - resolution: {integrity: sha512-/1loE/g+dTTQgHnjoCy0AexKAEFyHsR2zRB4NWrZ6lZSMIxAhBJnmCqwao7b4H8888PsfoTBCLBYIw8vGnej8g==} + /@commitlint/top-level@17.8.1: + resolution: {integrity: sha512-l6+Z6rrNf5p333SHfEte6r+WkOxGlWK4bLuZKbtf/2TXRN+qhrvn1XE63VhD8Oe9oIHQ7F7W1nG2k/TJFhx2yA==} engines: {node: '>=v14'} dependencies: find-up: 5.0.0 dev: true - /@commitlint/types@17.4.4: - resolution: {integrity: sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==} + /@commitlint/types@17.8.1: + resolution: {integrity: sha512-PXDQXkAmiMEG162Bqdh9ChML/GJZo6vU+7F03ALKDK8zYc6SuAr47LjG7hGYRqUOz+WK0dU7bQ0xzuqFMdxzeQ==} engines: {node: '>=v14'} dependencies: chalk: 4.1.2 dev: true + /@commitlint/types@18.0.0: + resolution: {integrity: sha512-FDzAdSm7kIir0NW0bZLENdrEgf/9Ihs1AAqE9DK9R+dRFby4ookkxPMaz7elZmG+e5rBl7hGrWJzJINqG9cDDg==} + engines: {node: '>=v18'} + requiresBuild: true + dependencies: + chalk: 4.1.2 + dev: true + optional: true + /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} dependencies: '@jridgewell/trace-mapping': 0.3.9 - /@cypress/code-coverage@3.12.1(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(cypress@12.17.4)(webpack@5.88.2): - resolution: {integrity: sha512-4gSVkgcTo8NSWrOwLO0NxyvD2apIZFM/2k9sxdmP3eR3ko8tZVYrWfTdfxSXLDSkNnzVh+oXv7utaOLn+yemUg==} + /@cypress/code-coverage@3.12.5(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(cypress@12.17.4)(webpack@5.89.0): + resolution: {integrity: sha512-0hczq2kgzkh/fBLm74rHcDRX//W3bhJJw/aPWu57/pPaRp5c+LcatWuv8ZtIWNXit2kBClueOrVj0I20Arh80A==} peerDependencies: '@babel/core': ^7.0.1 '@babel/preset-env': ^7.0.0 @@ -3982,18 +3023,18 @@ packages: dependencies: '@babel/core': 7.23.2 '@babel/preset-env': 7.23.2(@babel/core@7.23.2) - '@cypress/webpack-preprocessor': 5.17.1(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(webpack@5.88.2) - babel-loader: 9.1.3(@babel/core@7.23.2)(webpack@5.88.2) + '@cypress/webpack-preprocessor': 6.0.0(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(webpack@5.89.0) + babel-loader: 9.1.3(@babel/core@7.23.2)(webpack@5.89.0) chalk: 4.1.2 cypress: 12.17.4 - dayjs: 1.11.9 + dayjs: 1.11.10 debug: 4.3.4(supports-color@8.1.1) execa: 4.1.0 globby: 11.0.4 istanbul-lib-coverage: 3.0.0 js-yaml: 4.1.0 nyc: 15.1.0 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - supports-color dev: true @@ -4022,19 +3063,19 @@ packages: uuid: 8.3.2 dev: true - /@cypress/webpack-dev-server@3.6.1(debug@4.3.4)(webpack@5.88.2): + /@cypress/webpack-dev-server@3.6.1(debug@4.3.4)(webpack@5.89.0): resolution: {integrity: sha512-v9tn8SW5ot9jxlei0LqnU1hmR8Cy/A4mOKJOmrcU8KI0qWH6cadwmtiifRMgn8obQCJxiBSAeSWP3l2P4XoSAA==} dependencies: find-up: 6.3.0 fs-extra: 9.1.0 - html-webpack-plugin-4: /html-webpack-plugin@4.5.2(webpack@5.88.2) - html-webpack-plugin-5: /html-webpack-plugin@5.5.3(webpack@5.88.2) + html-webpack-plugin-4: /html-webpack-plugin@4.5.2(webpack@5.89.0) + html-webpack-plugin-5: /html-webpack-plugin@5.5.3(webpack@5.89.0) local-pkg: 0.4.1 semver: 7.5.4 - speed-measure-webpack-plugin: 1.4.2(webpack@5.88.2) + speed-measure-webpack-plugin: 1.4.2(webpack@5.89.0) tslib: 2.6.2 - webpack-dev-server: 4.15.1(debug@4.3.4)(webpack@5.88.2) - webpack-merge: 5.9.0 + webpack-dev-server: 4.15.1(debug@4.3.4)(webpack@5.89.0) + webpack-merge: 5.10.0 transitivePeerDependencies: - bufferutil - debug @@ -4044,21 +3085,21 @@ packages: - webpack-cli dev: true - /@cypress/webpack-preprocessor@5.17.1(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(webpack@5.88.2): - resolution: {integrity: sha512-FE/e8ikPc8z4EVopJCaior3RGy0jd2q9Xcp5NtiwNG4XnLfEnUFTZlAGwXe75sEh4fNMPrBJW1KIz77PX5vGAw==} + /@cypress/webpack-preprocessor@6.0.0(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(webpack@5.89.0): + resolution: {integrity: sha512-1AS1Et5CNPJii0+DdBZBS8e0hlM2BkBNmYRdZO4/16A3KS3em1sjPZtFw7jJF00m6DYAdB9iy6QW/lLZ2bN0gg==} peerDependencies: '@babel/core': ^7.0.1 '@babel/preset-env': ^7.0.0 - babel-loader: ^8.0.2 || ^9 + babel-loader: ^8.3 || ^9 webpack: ^4 || ^5 dependencies: '@babel/core': 7.23.2 '@babel/preset-env': 7.23.2(@babel/core@7.23.2) - babel-loader: 9.1.3(@babel/core@7.23.2)(webpack@5.88.2) + babel-loader: 9.1.3(@babel/core@7.23.2)(webpack@5.89.0) bluebird: 3.7.1 debug: 4.3.4(supports-color@8.1.1) lodash: 4.17.21 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - supports-color dev: true @@ -4143,7 +3184,7 @@ packages: resolution: {integrity: sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==} dev: false - /@docsearch/react@3.5.2(@algolia/client-search@4.20.0)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.8.3): + /@docsearch/react@3.5.2(@algolia/client-search@4.20.0)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.9.0): resolution: {integrity: sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' @@ -4160,13 +3201,13 @@ packages: search-insights: optional: true dependencies: - '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.8.3) + '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.9.0) '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) '@docsearch/css': 3.5.2 algoliasearch: 4.20.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - search-insights: 2.8.3 + search-insights: 2.9.0 transitivePeerDependencies: - '@algolia/client-search' dev: false @@ -4179,16 +3220,16 @@ packages: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 '@babel/generator': 7.23.0 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.0) - '@babel/plugin-transform-runtime': 7.22.15(@babel/core@7.23.0) - '@babel/preset-env': 7.22.20(@babel/core@7.23.0) - '@babel/preset-react': 7.22.15(@babel/core@7.23.0) - '@babel/preset-typescript': 7.23.0(@babel/core@7.23.0) - '@babel/runtime': 7.23.1 - '@babel/runtime-corejs3': 7.23.1 - '@babel/traverse': 7.23.0 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.2) + '@babel/plugin-transform-runtime': 7.23.2(@babel/core@7.23.2) + '@babel/preset-env': 7.23.2(@babel/core@7.23.2) + '@babel/preset-react': 7.22.15(@babel/core@7.23.2) + '@babel/preset-typescript': 7.23.2(@babel/core@7.23.2) + '@babel/runtime': 7.23.2 + '@babel/runtime-corejs3': 7.23.2 + '@babel/traverse': 7.23.2 '@docusaurus/cssnano-preset': 2.4.3 '@docusaurus/logger': 2.4.3 '@docusaurus/mdx-loader': 2.4.3(@docusaurus/types@2.4.3)(react-dom@18.2.0)(react@18.2.0) @@ -4199,7 +3240,7 @@ packages: '@slorber/static-site-generator-webpack-plugin': 4.0.7 '@svgr/webpack': 6.5.1 autoprefixer: 10.4.16(postcss@8.4.31) - babel-loader: 8.3.0(@babel/core@7.23.0)(webpack@5.88.2) + babel-loader: 8.3.0(@babel/core@7.23.2)(webpack@5.89.0) babel-plugin-dynamic-import-node: 2.3.3 boxen: 6.2.1 chalk: 4.1.2 @@ -4208,33 +3249,33 @@ packages: cli-table3: 0.6.3 combine-promises: 1.2.0 commander: 5.1.0 - copy-webpack-plugin: 11.0.0(webpack@5.88.2) - core-js: 3.33.0 - css-loader: 6.8.1(webpack@5.88.2) - css-minimizer-webpack-plugin: 4.2.2(clean-css@5.3.2)(webpack@5.88.2) + copy-webpack-plugin: 11.0.0(webpack@5.89.0) + core-js: 3.33.1 + css-loader: 6.8.1(webpack@5.89.0) + css-minimizer-webpack-plugin: 4.2.2(clean-css@5.3.2)(webpack@5.89.0) cssnano: 5.1.15(postcss@8.4.31) del: 6.1.1 detect-port: 1.5.1 escape-html: 1.0.3 eta: 2.2.0 - file-loader: 6.2.0(webpack@5.88.2) + file-loader: 6.2.0(webpack@5.89.0) fs-extra: 10.1.0 html-minifier-terser: 6.1.0 html-tags: 3.3.1 - html-webpack-plugin: 5.5.3(webpack@5.88.2) + html-webpack-plugin: 5.5.3(webpack@5.89.0) import-fresh: 3.3.0 leven: 3.1.0 lodash: 4.17.21 - mini-css-extract-plugin: 2.7.6(webpack@5.88.2) + mini-css-extract-plugin: 2.7.6(webpack@5.89.0) postcss: 8.4.31 - postcss-loader: 7.3.3(postcss@8.4.31)(typescript@4.9.5)(webpack@5.88.2) + postcss-loader: 7.3.3(postcss@8.4.31)(typescript@4.9.5)(webpack@5.89.0) prompts: 2.4.2 react: 18.2.0 - react-dev-utils: 12.0.1(typescript@4.9.5)(webpack@5.88.2) + react-dev-utils: 12.0.1(typescript@4.9.5)(webpack@5.89.0) react-dom: 18.2.0(react@18.2.0) react-helmet-async: 1.3.0(react-dom@18.2.0)(react@18.2.0) react-loadable: /@docusaurus/react-loadable@5.5.2(react@18.2.0) - react-loadable-ssr-addon-v5-slorber: 1.0.1(@docusaurus/react-loadable@5.5.2)(webpack@5.88.2) + react-loadable-ssr-addon-v5-slorber: 1.0.1(@docusaurus/react-loadable@5.5.2)(webpack@5.89.0) react-router: 5.3.4(react@18.2.0) react-router-config: 5.1.1(react-router@5.3.4)(react@18.2.0) react-router-dom: 5.3.4(react@18.2.0) @@ -4242,16 +3283,16 @@ packages: semver: 7.5.4 serve-handler: 6.1.5 shelljs: 0.8.5 - terser-webpack-plugin: 5.3.9(webpack@5.88.2) + terser-webpack-plugin: 5.3.9(webpack@5.89.0) tslib: 2.6.2 update-notifier: 5.1.0 - url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.88.2) + url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.89.0) wait-on: 6.0.1 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) webpack-bundle-analyzer: 4.9.1 - webpack-dev-server: 4.15.1(debug@4.3.4)(webpack@5.88.2) - webpack-merge: 5.9.0 - webpackbar: 5.0.2(webpack@5.88.2) + webpack-dev-server: 4.15.1(debug@4.3.4)(webpack@5.89.0) + webpack-merge: 5.10.0 + webpackbar: 5.0.2(webpack@5.89.0) transitivePeerDependencies: - '@docusaurus/types' - '@parcel/css' @@ -4297,12 +3338,12 @@ packages: react-dom: ^16.8.4 || ^17.0.0 dependencies: '@babel/parser': 7.23.0 - '@babel/traverse': 7.23.0 + '@babel/traverse': 7.23.2 '@docusaurus/logger': 2.4.3 '@docusaurus/utils': 2.4.3(@docusaurus/types@2.4.3) '@mdx-js/mdx': 1.6.22 escape-html: 1.0.3 - file-loader: 6.2.0(webpack@5.88.2) + file-loader: 6.2.0(webpack@5.89.0) fs-extra: 10.1.0 image-size: 1.0.2 mdast-util-to-string: 2.0.0 @@ -4313,8 +3354,8 @@ packages: tslib: 2.6.2 unified: 9.2.2 unist-util-visit: 2.0.3 - url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.88.2) - webpack: 5.88.2(webpack-cli@5.1.4) + url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.89.0) + webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - '@docusaurus/types' - '@swc/core' @@ -4333,8 +3374,8 @@ packages: '@docusaurus/react-loadable': 5.5.2(react@18.2.0) '@docusaurus/types': 2.4.3(react-dom@18.2.0)(react@18.2.0) '@types/history': 4.7.11 - '@types/react': 18.2.28 - '@types/react-router-config': 5.0.8 + '@types/react': 18.2.31 + '@types/react-router-config': 5.0.9 '@types/react-router-dom': 5.3.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -4370,7 +3411,7 @@ packages: tslib: 2.6.2 unist-util-visit: 2.0.3 utility-types: 3.10.0 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - '@parcel/css' - '@swc/core' @@ -4403,7 +3444,7 @@ packages: '@docusaurus/types': 2.4.3(react-dom@18.2.0)(react@18.2.0) '@docusaurus/utils': 2.4.3(@docusaurus/types@2.4.3) '@docusaurus/utils-validation': 2.4.3(@docusaurus/types@2.4.3) - '@types/react-router-config': 5.0.8 + '@types/react-router-config': 5.0.9 combine-promises: 1.2.0 fs-extra: 10.1.0 import-fresh: 3.3.0 @@ -4413,7 +3454,7 @@ packages: react-dom: 18.2.0(react@18.2.0) tslib: 2.6.2 utility-types: 3.10.0 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - '@parcel/css' - '@swc/core' @@ -4448,7 +3489,7 @@ packages: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) tslib: 2.6.2 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - '@parcel/css' - '@swc/core' @@ -4631,7 +3672,7 @@ packages: - webpack-cli dev: false - /@docusaurus/preset-classic@2.4.3(@algolia/client-search@4.20.0)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.8.3)(typescript@4.9.5): + /@docusaurus/preset-classic@2.4.3(@algolia/client-search@4.20.0)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.9.0)(typescript@4.9.5): resolution: {integrity: sha512-tRyMliepY11Ym6hB1rAFSNGwQDpmszvWYJvlK1E+md4SW8i6ylNHtpZjaYFff9Mdk3i/Pg8ItQq9P0daOJAvQw==} engines: {node: '>=16.14'} peerDependencies: @@ -4649,7 +3690,7 @@ packages: '@docusaurus/plugin-sitemap': 2.4.3(react-dom@18.2.0)(react@18.2.0)(typescript@4.9.5) '@docusaurus/theme-classic': 2.4.3(react-dom@18.2.0)(react@18.2.0)(typescript@4.9.5) '@docusaurus/theme-common': 2.4.3(@docusaurus/types@2.4.3)(react-dom@18.2.0)(react@18.2.0)(typescript@4.9.5) - '@docusaurus/theme-search-algolia': 2.4.3(@algolia/client-search@4.20.0)(@docusaurus/types@2.4.3)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.8.3)(typescript@4.9.5) + '@docusaurus/theme-search-algolia': 2.4.3(@algolia/client-search@4.20.0)(@docusaurus/types@2.4.3)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.9.0)(typescript@4.9.5) '@docusaurus/types': 2.4.3(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -4680,7 +3721,7 @@ packages: peerDependencies: react: '*' dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 prop-types: 15.8.1 react: 18.2.0 @@ -4751,8 +3792,8 @@ packages: '@docusaurus/utils': 2.4.3(@docusaurus/types@2.4.3) '@docusaurus/utils-common': 2.4.3(@docusaurus/types@2.4.3) '@types/history': 4.7.11 - '@types/react': 18.2.28 - '@types/react-router-config': 5.0.8 + '@types/react': 18.2.31 + '@types/react-router-config': 5.0.9 clsx: 1.2.1 parse-numeric-range: 1.3.0 prism-react-renderer: 1.3.5(react@18.2.0) @@ -4815,14 +3856,14 @@ packages: - webpack-cli dev: false - /@docusaurus/theme-search-algolia@2.4.3(@algolia/client-search@4.20.0)(@docusaurus/types@2.4.3)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.8.3)(typescript@4.9.5): + /@docusaurus/theme-search-algolia@2.4.3(@algolia/client-search@4.20.0)(@docusaurus/types@2.4.3)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.9.0)(typescript@4.9.5): resolution: {integrity: sha512-jziq4f6YVUB5hZOB85ELATwnxBz/RmSLD3ksGQOLDPKVzat4pmI8tddNWtriPpxR04BNT+ZfpPUMFkNFetSW1Q==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docsearch/react': 3.5.2(@algolia/client-search@4.20.0)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.8.3) + '@docsearch/react': 3.5.2(@algolia/client-search@4.20.0)(react-dom@18.2.0)(react@18.2.0)(search-insights@2.9.0) '@docusaurus/core': 2.4.3(@docusaurus/types@2.4.3)(react-dom@18.2.0)(react@18.2.0)(typescript@4.9.5) '@docusaurus/logger': 2.4.3 '@docusaurus/plugin-content-docs': 2.4.3(react-dom@18.2.0)(react@18.2.0)(typescript@4.9.5) @@ -4877,15 +3918,15 @@ packages: react-dom: ^16.8.4 || ^17.0.0 dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.28 + '@types/react': 18.2.31 commander: 5.1.0 joi: 17.11.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-helmet-async: 1.3.0(react-dom@18.2.0)(react@18.2.0) utility-types: 3.10.0 - webpack: 5.88.2(webpack-cli@5.1.4) - webpack-merge: 5.9.0 + webpack: 5.89.0(webpack-cli@5.1.4) + webpack-merge: 5.10.0 transitivePeerDependencies: - '@swc/core' - esbuild @@ -4936,7 +3977,7 @@ packages: '@docusaurus/types': 2.4.3(react-dom@18.2.0)(react@18.2.0) '@svgr/webpack': 6.5.1 escape-string-regexp: 4.0.0 - file-loader: 6.2.0(webpack@5.88.2) + file-loader: 6.2.0(webpack@5.89.0) fs-extra: 10.1.0 github-slugger: 1.5.0 globby: 11.1.0 @@ -4947,8 +3988,8 @@ packages: resolve-pathname: 3.0.0 shelljs: 0.8.5 tslib: 2.6.2 - url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.88.2) - webpack: 5.88.2(webpack-cli@5.1.4) + url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.89.0) + webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - '@swc/core' - esbuild @@ -4961,14 +4002,14 @@ packages: resolution: {integrity: sha512-VWsdOZTsu8ABNVplFQUniHSLsCAQIJh+HDTUP6CllxXBe2pgFQKQ6RGxAS/QRTUcPprQCGpB3zH+gqNnvRRTmQ==} dependencies: chance: 1.1.11 - core-js: 3.33.0 + core-js: 3.33.1 dev: true /@emotion/babel-plugin@11.11.0: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: '@babel/helper-module-imports': 7.22.15 - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@emotion/hash': 0.9.1 '@emotion/memoize': 0.8.1 '@emotion/serialize': 1.1.2 @@ -5008,7 +4049,7 @@ packages: resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} dev: false - /@emotion/react@11.11.1(@types/react@18.2.28)(react@18.2.0): + /@emotion/react@11.11.1(@types/react@18.2.31)(react@18.2.0): resolution: {integrity: sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==} peerDependencies: '@types/react': '*' @@ -5017,14 +4058,14 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.2 '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) '@emotion/utils': 1.2.1 '@emotion/weak-memoize': 0.3.1 - '@types/react': 18.2.28 + '@types/react': 18.2.31 hoist-non-react-statics: 3.3.2 react: 18.2.0 dev: false @@ -5043,7 +4084,7 @@ packages: resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} dev: false - /@emotion/styled@11.11.0(@emotion/react@11.11.1)(@types/react@18.2.28)(react@18.2.0): + /@emotion/styled@11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0): resolution: {integrity: sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==} peerDependencies: '@emotion/react': ^11.0.0-rc.0 @@ -5053,14 +4094,14 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.1 - '@emotion/react': 11.11.1(@types/react@18.2.28)(react@18.2.0) + '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) '@emotion/serialize': 1.1.2 '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) '@emotion/utils': 1.2.1 - '@types/react': 18.2.28 + '@types/react': 18.2.31 react: 18.2.0 dev: false @@ -5092,7 +4133,7 @@ packages: eth-ens-namehash: 2.0.8 solc: 0.4.26 testrpc: 0.0.1 - web3-utils: 1.10.2 + web3-utils: 1.10.3 dev: true /@ensdomains/resolver@0.2.4: @@ -5221,6 +4262,15 @@ packages: dev: true optional: true + /@esbuild/android-arm64@0.19.5: + resolution: {integrity: sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm@0.16.3: resolution: {integrity: sha512-mueuEoh+s1eRbSJqq9KNBQwI4QhQV6sRXIfTyLXSHGMpyew61rOK4qY21uKbXl1iBoMb0AdL1deWFCQVlN2qHA==} engines: {node: '>=12'} @@ -5248,6 +4298,15 @@ packages: dev: true optional: true + /@esbuild/android-arm@0.19.5: + resolution: {integrity: sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-x64@0.16.3: resolution: {integrity: sha512-SFpTUcIT1bIJuCCBMCQWq1bL2gPTjWoLZdjmIhjdcQHaUfV41OQfho6Ici5uvvkMmZRXIUGpM3GxysP/EU7ifQ==} engines: {node: '>=12'} @@ -5275,6 +4334,15 @@ packages: dev: true optional: true + /@esbuild/android-x64@0.19.5: + resolution: {integrity: sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-arm64@0.16.3: resolution: {integrity: sha512-DO8WykMyB+N9mIDfI/Hug70Dk1KipavlGAecxS3jDUwAbTpDXj0Lcwzw9svkhxfpCagDmpaTMgxWK8/C/XcXvw==} engines: {node: '>=12'} @@ -5302,6 +4370,15 @@ packages: dev: true optional: true + /@esbuild/darwin-arm64@0.19.5: + resolution: {integrity: sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-x64@0.16.3: resolution: {integrity: sha512-uEqZQ2omc6BvWqdCiyZ5+XmxuHEi1SPzpVxXCSSV2+Sh7sbXbpeNhHIeFrIpRjAs0lI1FmA1iIOxFozKBhKgRQ==} engines: {node: '>=12'} @@ -5329,6 +4406,15 @@ packages: dev: true optional: true + /@esbuild/darwin-x64@0.19.5: + resolution: {integrity: sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-arm64@0.16.3: resolution: {integrity: sha512-nJansp3sSXakNkOD5i5mIz2Is/HjzIhFs49b1tjrPrpCmwgBmH9SSzhC/Z1UqlkivqMYkhfPwMw1dGFUuwmXhw==} engines: {node: '>=12'} @@ -5356,6 +4442,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-arm64@0.19.5: + resolution: {integrity: sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-x64@0.16.3: resolution: {integrity: sha512-TfoDzLw+QHfc4a8aKtGSQ96Wa+6eimljjkq9HKR0rHlU83vw8aldMOUSJTUDxbcUdcgnJzPaX8/vGWm7vyV7ug==} engines: {node: '>=12'} @@ -5383,6 +4478,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-x64@0.19.5: + resolution: {integrity: sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm64@0.16.3: resolution: {integrity: sha512-7I3RlsnxEFCHVZNBLb2w7unamgZ5sVwO0/ikE2GaYvYuUQs9Qte/w7TqWcXHtCwxvZx/2+F97ndiUQAWs47ZfQ==} engines: {node: '>=12'} @@ -5410,6 +4514,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm64@0.19.5: + resolution: {integrity: sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm@0.16.3: resolution: {integrity: sha512-VwswmSYwVAAq6LysV59Fyqk3UIjbhuc6wb3vEcJ7HEJUtFuLK9uXWuFoH1lulEbE4+5GjtHi3MHX+w1gNHdOWQ==} engines: {node: '>=12'} @@ -5437,6 +4550,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm@0.19.5: + resolution: {integrity: sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ia32@0.16.3: resolution: {integrity: sha512-X8FDDxM9cqda2rJE+iblQhIMYY49LfvW4kaEjoFbTTQ4Go8G96Smj2w3BRTwA8IHGoi9dPOPGAX63dhuv19UqA==} engines: {node: '>=12'} @@ -5464,6 +4586,15 @@ packages: dev: true optional: true + /@esbuild/linux-ia32@0.19.5: + resolution: {integrity: sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-loong64@0.16.3: resolution: {integrity: sha512-hIbeejCOyO0X9ujfIIOKjBjNAs9XD/YdJ9JXAy1lHA+8UXuOqbFe4ErMCqMr8dhlMGBuvcQYGF7+kO7waj2KHw==} engines: {node: '>=12'} @@ -5491,6 +4622,15 @@ packages: dev: true optional: true + /@esbuild/linux-loong64@0.19.5: + resolution: {integrity: sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-mips64el@0.16.3: resolution: {integrity: sha512-znFRzICT/V8VZQMt6rjb21MtAVJv/3dmKRMlohlShrbVXdBuOdDrGb+C2cZGQAR8RFyRe7HS6klmHq103WpmVw==} engines: {node: '>=12'} @@ -5518,6 +4658,15 @@ packages: dev: true optional: true + /@esbuild/linux-mips64el@0.19.5: + resolution: {integrity: sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ppc64@0.16.3: resolution: {integrity: sha512-EV7LuEybxhXrVTDpbqWF2yehYRNz5e5p+u3oQUS2+ZFpknyi1NXxr8URk4ykR8Efm7iu04//4sBg249yNOwy5Q==} engines: {node: '>=12'} @@ -5545,6 +4694,15 @@ packages: dev: true optional: true + /@esbuild/linux-ppc64@0.19.5: + resolution: {integrity: sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-riscv64@0.16.3: resolution: {integrity: sha512-uDxqFOcLzFIJ+r/pkTTSE9lsCEaV/Y6rMlQjUI9BkzASEChYL/aSQjZjchtEmdnVxDKETnUAmsaZ4pqK1eE5BQ==} engines: {node: '>=12'} @@ -5572,6 +4730,15 @@ packages: dev: true optional: true + /@esbuild/linux-riscv64@0.19.5: + resolution: {integrity: sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-s390x@0.16.3: resolution: {integrity: sha512-NbeREhzSxYwFhnCAQOQZmajsPYtX71Ufej3IQ8W2Gxskfz9DK58ENEju4SbpIj48VenktRASC52N5Fhyf/aliQ==} engines: {node: '>=12'} @@ -5599,6 +4766,15 @@ packages: dev: true optional: true + /@esbuild/linux-s390x@0.19.5: + resolution: {integrity: sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-x64@0.16.3: resolution: {integrity: sha512-SDiG0nCixYO9JgpehoKgScwic7vXXndfasjnD5DLbp1xltANzqZ425l7LSdHynt19UWOcDjG9wJJzSElsPvk0w==} engines: {node: '>=12'} @@ -5617,8 +4793,17 @@ packages: dev: true optional: true - /@esbuild/linux-x64@0.18.20: - resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + /@esbuild/linux-x64@0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.19.5: + resolution: {integrity: sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -5653,6 +4838,15 @@ packages: dev: true optional: true + /@esbuild/netbsd-x64@0.19.5: + resolution: {integrity: sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/openbsd-x64@0.16.3: resolution: {integrity: sha512-gSABi8qHl8k3Cbi/4toAzHiykuBuWLZs43JomTcXkjMZVkp0gj3gg9mO+9HJW/8GB5H89RX/V0QP4JGL7YEEVg==} engines: {node: '>=12'} @@ -5680,6 +4874,15 @@ packages: dev: true optional: true + /@esbuild/openbsd-x64@0.19.5: + resolution: {integrity: sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/sunos-x64@0.16.3: resolution: {integrity: sha512-SF9Kch5Ete4reovvRO6yNjMxrvlfT0F0Flm+NPoUw5Z4Q3r1d23LFTgaLwm3Cp0iGbrU/MoUI+ZqwCv5XJijCw==} engines: {node: '>=12'} @@ -5707,6 +4910,15 @@ packages: dev: true optional: true + /@esbuild/sunos-x64@0.19.5: + resolution: {integrity: sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-arm64@0.16.3: resolution: {integrity: sha512-u5aBonZIyGopAZyOnoPAA6fGsDeHByZ9CnEzyML9NqntK6D/xl5jteZUKm/p6nD09+v3pTM6TuUIqSPcChk5gg==} engines: {node: '>=12'} @@ -5734,6 +4946,15 @@ packages: dev: true optional: true + /@esbuild/win32-arm64@0.19.5: + resolution: {integrity: sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-ia32@0.16.3: resolution: {integrity: sha512-GlgVq1WpvOEhNioh74TKelwla9KDuAaLZrdxuuUgsP2vayxeLgVc+rbpIv0IYF4+tlIzq2vRhofV+KGLD+37EQ==} engines: {node: '>=12'} @@ -5761,6 +4982,15 @@ packages: dev: true optional: true + /@esbuild/win32-ia32@0.19.5: + resolution: {integrity: sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-x64@0.16.3: resolution: {integrity: sha512-5/JuTd8OWW8UzEtyf19fbrtMJENza+C9JoPIkvItgTBQ1FO2ZLvjbPO6Xs54vk0s5JB5QsfieUEshRQfu7ZHow==} engines: {node: '>=12'} @@ -5788,6 +5018,15 @@ packages: dev: true optional: true + /@esbuild/win32-x64@0.19.5: + resolution: {integrity: sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.19.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5798,13 +5037,13 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.51.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.52.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.51.0 + eslint: 8.52.0 eslint-visitor-keys: 3.4.3 dev: true @@ -5847,18 +5086,18 @@ packages: - supports-color dev: true - /@eslint/js@8.51.0: - resolution: {integrity: sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==} + /@eslint/js@8.52.0: + resolution: {integrity: sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true /@ethereum-attestation-service/eas-contracts@0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(ts-node@10.9.1)(typescript@4.9.5): resolution: {integrity: sha512-ly1N/jLbXJjACDL7dnMSkzViBxxuVc+aMZ3EB1kpFxeMWrXkb7nN6w9gxGTH+m3gJztaKvyMsyr/13pA0OYq6Q==} dependencies: - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@4.9.5) - '@typechain/hardhat': 6.1.6(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@10.2.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.1) + '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) + '@typechain/hardhat': 6.1.6(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@10.2.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2) hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) - typechain: 8.3.1(typescript@4.9.5) + typechain: 8.3.2(typescript@4.9.5) transitivePeerDependencies: - '@ethersproject/abi' - '@ethersproject/providers' @@ -5873,10 +5112,10 @@ packages: /@ethereum-attestation-service/eas-contracts@0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.1.6): resolution: {integrity: sha512-ly1N/jLbXJjACDL7dnMSkzViBxxuVc+aMZ3EB1kpFxeMWrXkb7nN6w9gxGTH+m3gJztaKvyMsyr/13pA0OYq6Q==} dependencies: - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@5.1.6) - '@typechain/hardhat': 6.1.6(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@10.2.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.1) + '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.1.6) + '@typechain/hardhat': 6.1.6(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@10.2.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2) hardhat: 2.13.1(typescript@5.1.6) - typechain: 8.3.1(typescript@5.1.6) + typechain: 8.3.2(typescript@5.1.6) transitivePeerDependencies: - '@ethersproject/abi' - '@ethersproject/providers' @@ -5936,7 +5175,7 @@ packages: - supports-color dev: true - /@ethereum-waffle/compiler@4.0.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(solc@0.8.15)(typechain@8.3.1)(typescript@4.9.5): + /@ethereum-waffle/compiler@4.0.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(solc@0.8.15)(typechain@8.3.2)(typescript@4.9.5): resolution: {integrity: sha512-5x5U52tSvEVJS6dpCeXXKvRKyf8GICDwiTwUvGD3/WD+DpvgvaoHOL82XqpTSUHgV3bBq6ma5/8gKUJUIAnJCw==} engines: {node: '>=10.0'} peerDependencies: @@ -5946,14 +5185,14 @@ packages: dependencies: '@resolver-engine/imports': 0.3.3 '@resolver-engine/imports-fs': 0.3.3 - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@4.9.5) + '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) '@types/mkdirp': 0.5.2 - '@types/node-fetch': 2.6.6 + '@types/node-fetch': 2.6.7 ethers: 5.7.2 mkdirp: 0.5.6 node-fetch: 2.7.0 solc: 0.8.15 - typechain: 8.3.1(typescript@4.9.5) + typechain: 8.3.2(typescript@4.9.5) transitivePeerDependencies: - '@ethersproject/abi' - '@ethersproject/providers' @@ -6029,7 +5268,7 @@ packages: resolution: {integrity: sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA==} dependencies: crc-32: 1.2.2 - ethereumjs-util: 7.1.5 + ethereumjs-util: 7.1.3 dev: true /@ethereumjs/common@2.6.5: @@ -6059,7 +5298,7 @@ packages: resolution: {integrity: sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw==} dependencies: '@ethereumjs/common': 2.6.0 - ethereumjs-util: 7.1.5 + ethereumjs-util: 7.1.3 dev: true /@ethereumjs/tx@3.5.2: @@ -6086,9 +5325,9 @@ packages: '@ethereumjs/common': 2.6.0 '@ethereumjs/tx': 3.4.0 async-eventemitter: 0.2.4 - core-js-pure: 3.33.0 + core-js-pure: 3.33.1 debug: 2.6.9 - ethereumjs-util: 7.1.5 + ethereumjs-util: 7.1.3 functional-red-black-tree: 1.0.1 mcl-wasm: 0.7.9 merkle-patricia-tree: 4.2.4 @@ -6097,6 +5336,20 @@ packages: - supports-color dev: true + /@ethersproject/abi@5.0.7: + resolution: {integrity: sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==} + dependencies: + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 + dev: true + /@ethersproject/abi@5.7.0: resolution: {integrity: sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==} dependencies: @@ -6394,6 +5647,16 @@ packages: /@fastify/deepmerge@1.3.0: resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==} + /@float-capital/float-subgraph-uncrashable@0.0.0-internal-testing.5: + resolution: {integrity: sha512-yZ0H5e3EpAYKokX/AbtplzlvSxEJY7ZfpvQyDzyODkks0hakAAlDG6fQu1SlDJMWorY7bbq1j7fCiFeTWci6TA==} + hasBin: true + dependencies: + '@rescript/std': 9.0.0 + graphql: 16.8.1 + graphql-import-node: 0.0.5(graphql@16.8.1) + js-yaml: 4.1.0 + dev: true + /@floating-ui/core@1.5.0: resolution: {integrity: sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==} dependencies: @@ -6639,7 +5902,7 @@ packages: tslib: 2.6.2 dev: true - /@graphprotocol/client-cli@2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.15.13)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.5): + /@graphprotocol/client-cli@2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): resolution: {integrity: sha512-PIi8rFibYZVup+0jb08399RmbGF1ZrqUe6RXzLtKZBT57OWIMWwsFvdJyUAdr8Y8f0rrMn6A+Oy4nP1lf3hc1g==} hasBin: true peerDependencies: @@ -6650,8 +5913,8 @@ packages: '@graphprotocol/client-auto-type-merging': 1.0.25(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-block-tracking': 1.0.14(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-polling-live': 1.1.1(@envelop/core@3.0.6)(@graphql-tools/merge@8.4.2)(graphql@16.8.1) - '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.15.13)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.5) - '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.15.13)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) + '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(tslib@2.6.2) graphql: 16.8.1 tslib: 2.6.2 transitivePeerDependencies: @@ -6677,7 +5940,7 @@ packages: - utf-8-validate dev: false - /@graphprotocol/client-cli@3.0.0(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.15.13)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.5): + /@graphprotocol/client-cli@3.0.0(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): resolution: {integrity: sha512-hTISbOzKavlDifBNsR6JqQMfdYwY7++hflPy+c3WHRrZ4OMoxFmW7ZuvaP6LvgKdJV77O8w9dnT/uxeHs6a90g==} engines: {node: '>=16.0.0'} hasBin: true @@ -6689,8 +5952,8 @@ packages: '@graphprotocol/client-auto-type-merging': 2.0.0(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-block-tracking': 2.0.0(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-polling-live': 2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@9.0.0)(graphql@16.8.1) - '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.15.13)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.5) - '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.15.13)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) + '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(tslib@2.6.2) graphql: 16.8.1 tslib: 2.6.2 transitivePeerDependencies: @@ -6730,6 +5993,21 @@ packages: tslib: 2.6.2 dev: false + /@graphprotocol/client-polling-live@2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@8.4.2)(graphql@16.8.1): + resolution: {integrity: sha512-JQ0sKiFCX+ErR0fynBNUg/WDiVaaEndlS12fkgrFZrQA2vVpSyow9pW0nKMGVZJa4cN+VDskgwqK5BWXMvdeRA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@envelop/core': ^2.4.2 || ^3.0.0 || ^4.0.0 + '@graphql-tools/merge': ^8.3.14 || ^9.0.0 + graphql: ^16.6.0 + dependencies: + '@envelop/core': 3.0.6 + '@graphql-tools/merge': 8.4.2(graphql@16.8.1) + '@repeaterjs/repeater': 3.0.4 + graphql: 16.8.1 + tslib: 2.6.2 + dev: false + /@graphprotocol/client-polling-live@2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@9.0.0)(graphql@16.8.1): resolution: {integrity: sha512-JQ0sKiFCX+ErR0fynBNUg/WDiVaaEndlS12fkgrFZrQA2vVpSyow9pW0nKMGVZJa4cN+VDskgwqK5BWXMvdeRA==} engines: {node: '>=16.0.0'} @@ -6744,6 +6022,57 @@ packages: graphql: 16.8.1 tslib: 2.6.2 + /@graphprotocol/graph-cli@0.60.0(@types/node@18.18.6)(node-fetch@3.3.2)(typescript@4.9.5): + resolution: {integrity: sha512-8tGaQJ0EzAPtkDXCAijFGoVdJXM+pKFlGxjiU31TdG5bS4cIUoSB6yWojVsFFod0yETAwf+giel/0/8sudYsDw==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@float-capital/float-subgraph-uncrashable': 0.0.0-internal-testing.5 + '@oclif/core': 2.8.6(@types/node@18.18.6)(typescript@4.9.5) + '@oclif/plugin-autocomplete': 2.3.10(@types/node@18.18.6)(typescript@4.9.5) + '@oclif/plugin-not-found': 2.4.3(@types/node@18.18.6)(typescript@4.9.5) + '@whatwg-node/fetch': 0.8.8 + assemblyscript: 0.19.23 + binary-install-raw: 0.0.13(debug@4.3.4) + chalk: 3.0.0 + chokidar: 3.5.3 + debug: 4.3.4(supports-color@8.1.1) + docker-compose: 0.23.19 + dockerode: 2.5.8 + fs-extra: 9.1.0 + glob: 9.3.5 + gluegun: 5.1.2(debug@4.3.4) + graphql: 16.8.1 + immutable: 4.2.1 + ipfs-http-client: 55.0.0(node-fetch@3.3.2) + jayson: 4.0.0 + js-yaml: 3.14.1 + prettier: 1.19.1 + request: 2.88.2 + semver: 7.4.0 + sync-request: 6.1.0 + tmp-promise: 3.0.3 + web3-eth-abi: 1.7.0 + which: 2.0.2 + yaml: 1.10.2 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - bufferutil + - encoding + - node-fetch + - supports-color + - typescript + - utf-8-validate + dev: true + + /@graphprotocol/graph-ts@0.31.0: + resolution: {integrity: sha512-xreRVM6ho2BtolyOh2flDkNoGZximybnzUnF53zJVp0+Ed0KnAlO1/KOCUYw06euVI9tk0c9nA2Z/D5SIQV2Rg==} + dependencies: + assemblyscript: 0.19.10 + dev: true + /@graphql-codegen/core@3.1.0(graphql@16.8.1): resolution: {integrity: sha512-DH1/yaR7oJE6/B+c6ZF2Tbdh7LixF1K8L+8BoSubjNyQ8pNwR4a70mvc1sv6H7qgp6y1bPQ9tKE+aazRRshysw==} peerDependencies: @@ -6766,7 +6095,7 @@ packages: graphql: 16.8.1 import-from: 4.0.0 lodash: 4.17.21 - tslib: 2.4.0 + tslib: 2.4.1 /@graphql-codegen/plugin-helpers@3.1.2(graphql@16.8.1): resolution: {integrity: sha512-emOQiHyIliVOIjKVKdsI5MXj312zmRDwmHpyUTZMjfpvxq/UVAHUJIVdVf+lnjjrI+LXBTgMlTWTgHQfmICxjg==} @@ -6779,7 +6108,7 @@ packages: graphql: 16.8.1 import-from: 4.0.0 lodash: 4.17.21 - tslib: 2.4.0 + tslib: 2.4.1 /@graphql-codegen/plugin-helpers@4.2.0(graphql@16.8.1): resolution: {integrity: sha512-THFTCfg+46PXlXobYJ/OoCX6pzjI+9woQqCjdyKtgoI0tn3Xq2HUUCiidndxUpEYVrXb5pRiRXb7b/ZbMQqD0A==} @@ -6830,7 +6159,7 @@ packages: auto-bind: 4.0.0 graphql: 16.8.1 graphql-tag: 2.12.6(graphql@16.8.1) - tslib: 2.4.0 + tslib: 2.4.1 transitivePeerDependencies: - encoding - supports-color @@ -6896,7 +6225,7 @@ packages: graphql: 16.8.1 graphql-tag: 2.12.6(graphql@16.8.1) parse-filepath: 1.0.2 - tslib: 2.4.0 + tslib: 2.4.1 transitivePeerDependencies: - encoding - supports-color @@ -6972,7 +6301,7 @@ packages: tslib: 2.6.2 dev: false - /@graphql-mesh/cli@0.82.35(@babel/core@7.23.2)(@types/node@18.15.13)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.5): + /@graphql-mesh/cli@0.82.35(@babel/core@7.23.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): resolution: {integrity: sha512-5IuXpk+Zpg05u6qNPX19VzC5/HCiLdDRF6EPZ3ze57FIRgGA3YsB1CUGga6Ky3inalURYwx0kWqmdjbdKZYx1w==} hasBin: true peerDependencies: @@ -6985,7 +6314,7 @@ packages: '@graphql-codegen/typescript-operations': 3.0.4(graphql@16.8.1) '@graphql-codegen/typescript-resolvers': 3.2.1(graphql@16.8.1) '@graphql-mesh/config': 0.93.1(@babel/core@7.23.2)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/runtime@0.93.2)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.5) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) '@graphql-mesh/http': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/runtime@0.93.2)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6999,18 +6328,18 @@ packages: dotenv: 16.3.1 graphql: 16.8.1 graphql-import-node: 0.0.5(graphql@16.8.1) - graphql-ws: 5.14.1(graphql@16.8.1) + graphql-ws: 5.14.2(graphql@16.8.1) json-bigint-patch: 0.0.8 json5: 2.2.3 mkdirp: 3.0.1 open: 7.4.2 pascal-case: 3.1.2 rimraf: 5.0.5 - ts-node: 10.9.1(@types/node@18.15.13)(typescript@5.1.6) + ts-node: 10.9.1(@types/node@18.18.6)(typescript@5.1.6) tsconfig-paths: 4.2.0 tslib: 2.6.2 typescript: 5.1.6 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) yargs: 17.7.2 transitivePeerDependencies: - '@babel/core' @@ -7039,7 +6368,7 @@ packages: dependencies: '@envelop/core': 3.0.6 '@graphql-mesh/cache-localforage': 0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.5) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) '@graphql-mesh/merger-bare': 0.93.1(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/merger-stitching': 0.93.1(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -7060,7 +6389,7 @@ packages: - '@babel/core' - supports-color - /@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.5): + /@graphql-mesh/cross-helpers@0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6): resolution: {integrity: sha512-jseNppSNEwNWjcjDDwsxmRBK+ub8tz2qc/ca2ZfCTebuCk/+D3dI3LJ95ceNFOIhInK0g2HVq8BO8lMMX1pQtg==} peerDependencies: '@graphql-tools/utils': ^9.2.1 @@ -7069,7 +6398,7 @@ packages: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) graphql: 16.8.1 path-browserify: 1.0.1 - react-native-fs: 2.20.0(react-native@0.72.5) + react-native-fs: 2.20.0(react-native@0.72.6) react-native-path: 0.0.5 transitivePeerDependencies: - react-native @@ -7086,7 +6415,7 @@ packages: graphql: 16.8.1 path-browserify: 1.0.1 - /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.15.13)(graphql@16.8.1)(tslib@2.6.2): + /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-1G2/1jkl1VPWhsZsUBwFQI5d9OxxEc+CMxy5ef0qI2WEXqIocOxMhEY53cc+tCSbuXR99rxos+KD/8Z6ZasaOQ==} peerDependencies: '@graphql-mesh/cross-helpers': ^0.3.4 @@ -7097,13 +6426,13 @@ packages: graphql: ^16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.5) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) - '@graphql-tools/url-loader': 7.17.18(@types/node@18.15.13)(graphql@16.8.1) + '@graphql-tools/url-loader': 7.17.18(@types/node@18.18.6)(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) graphql: 16.8.1 @@ -7116,7 +6445,7 @@ packages: - utf-8-validate dev: false - /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.15.13)(graphql@16.8.1)(tslib@2.6.2): + /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-1G2/1jkl1VPWhsZsUBwFQI5d9OxxEc+CMxy5ef0qI2WEXqIocOxMhEY53cc+tCSbuXR99rxos+KD/8Z6ZasaOQ==} peerDependencies: '@graphql-mesh/cross-helpers': ^0.3.4 @@ -7133,7 +6462,7 @@ packages: '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) - '@graphql-tools/url-loader': 7.17.18(@types/node@18.15.13)(graphql@16.8.1) + '@graphql-tools/url-loader': 7.17.18(@types/node@18.18.6)(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) graphql: 16.8.1 @@ -7146,7 +6475,7 @@ packages: - utf-8-validate dev: true - /@graphql-mesh/graphql@0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.15.13)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2): + /@graphql-mesh/graphql@0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2): resolution: {integrity: sha512-Fjf1Ti2HYOEP+dFLVnVxafD/Z4Ev+sR6BUbx3E7Mw8r/XGY28KmCA/QftBOB6BRNKMLe5w7RsgjCrO+Qp0klNg==} engines: {node: '>=16.0.0'} peerDependencies: @@ -7164,8 +6493,8 @@ packages: '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) - '@graphql-tools/federation': 1.1.10(@types/node@18.15.13)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) - '@graphql-tools/url-loader': 8.0.0(@types/node@18.15.13)(graphql@16.8.1) + '@graphql-tools/federation': 1.1.10(@types/node@18.18.6)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + '@graphql-tools/url-loader': 8.0.0(@types/node@18.18.6)(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) graphql: 16.8.1 lodash.get: 4.4.2 @@ -7191,7 +6520,7 @@ packages: graphql: ^16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.5) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) '@graphql-mesh/runtime': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -7316,7 +6645,7 @@ packages: dependencies: '@envelop/core': 3.0.6 '@envelop/extended-validation': 2.0.6(@envelop/core@3.0.6)(graphql@16.8.1) - '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.5) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -7329,6 +6658,35 @@ packages: graphql: 16.8.1 tslib: 2.6.2 + /@graphql-mesh/runtime@0.96.12(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-b3a/XjbTtS8gF30wu35M4pA2KyUYkYcWlnYNGXWOObtdEtEXjj+GkX//yO2XzTGI/sGWKElAAKIv4asPsye4jA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.4.1 + '@graphql-mesh/types': ^0.95.7 + '@graphql-mesh/utils': ^0.95.7 + '@graphql-tools/utils': ^9.2.1 || ^10.0.0 + graphql: ^16.6.0 + tslib: ^2.4.0 + dependencies: + '@envelop/core': 5.0.0 + '@envelop/extended-validation': 4.0.0(@envelop/core@5.0.0)(graphql@16.8.1) + '@envelop/graphql-jit': 8.0.1(@envelop/core@5.0.0)(graphql@16.8.1) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) + '@graphql-mesh/string-interpolation': 0.5.2(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-tools/batch-delegate': 9.0.0(graphql@16.8.1) + '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) + '@graphql-tools/executor': 1.2.0(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@graphql-tools/wrap': 10.0.1(graphql@16.8.1) + '@whatwg-node/fetch': 0.9.13 + graphql: 16.8.1 + graphql-jit: 0.8.2(graphql@16.8.1) + tslib: 2.6.2 + dev: false + /@graphql-mesh/runtime@0.96.12(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-b3a/XjbTtS8gF30wu35M4pA2KyUYkYcWlnYNGXWOObtdEtEXjj+GkX//yO2XzTGI/sGWKElAAKIv4asPsye4jA==} engines: {node: '>=16.0.0'} @@ -7369,7 +6727,7 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-inspector/core': 3.3.0(graphql@16.8.1) - '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.5) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -7494,7 +6852,7 @@ packages: graphql: ^16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.5) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) @@ -7629,7 +6987,7 @@ packages: dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@repeaterjs/repeater': 3.0.4 - '@types/ws': 8.5.7 + '@types/ws': 8.5.8 graphql: 16.8.1 graphql-ws: 5.12.1(graphql@16.8.1) isomorphic-ws: 5.0.0(ws@8.13.0) @@ -7646,18 +7004,18 @@ packages: graphql: ^16.6.0 dependencies: '@graphql-tools/utils': 10.0.7(graphql@16.8.1) - '@types/ws': 8.5.7 + '@types/ws': 8.5.8 graphql: 16.8.1 - graphql-ws: 5.14.1(graphql@16.8.1) + graphql-ws: 5.14.2(graphql@16.8.1) isomorphic-ws: 5.0.0(ws@8.14.2) tslib: 2.6.2 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - utf-8-validate dev: false - /@graphql-tools/executor-http@0.1.10(@types/node@18.15.13)(graphql@16.8.1): + /@graphql-tools/executor-http@0.1.10(@types/node@18.18.6)(graphql@16.8.1): resolution: {integrity: sha512-hnAfbKv0/lb9s31LhWzawQ5hghBfHS+gYWtqxME6Rl0Aufq9GltiiLBcl7OVVOnkLF0KhwgbYP1mB5VKmgTGpg==} peerDependencies: graphql: ^16.6.0 @@ -7668,13 +7026,13 @@ packages: dset: 3.1.2 extract-files: 11.0.0 graphql: 16.8.1 - meros: 1.3.0(@types/node@18.15.13) + meros: 1.3.0(@types/node@18.18.6) tslib: 2.6.2 value-or-promise: 1.0.12 transitivePeerDependencies: - '@types/node' - /@graphql-tools/executor-http@1.0.3(@types/node@18.15.13)(graphql@16.8.1): + /@graphql-tools/executor-http@1.0.3(@types/node@18.18.6)(graphql@16.8.1): resolution: {integrity: sha512-5WZIMBevRaxMabZ8U2Ty0dTUPy/PpeYSlMNEmC/YJjKKykgSfc/AwSejx2sE4FFKZ0I2kxRKRenyoWMHRAV49Q==} engines: {node: '>=16.0.0'} peerDependencies: @@ -7685,7 +7043,7 @@ packages: '@whatwg-node/fetch': 0.9.13 extract-files: 11.0.0 graphql: 16.8.1 - meros: 1.3.0(@types/node@18.15.13) + meros: 1.3.0(@types/node@18.18.6) tslib: 2.6.2 value-or-promise: 1.0.12 transitivePeerDependencies: @@ -7698,7 +7056,7 @@ packages: graphql: ^16.6.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - '@types/ws': 8.5.7 + '@types/ws': 8.5.8 graphql: 16.8.1 isomorphic-ws: 5.0.0(ws@8.13.0) tslib: 2.6.2 @@ -7714,11 +7072,11 @@ packages: graphql: ^16.6.0 dependencies: '@graphql-tools/utils': 10.0.7(graphql@16.8.1) - '@types/ws': 8.5.7 + '@types/ws': 8.5.8 graphql: 16.8.1 isomorphic-ws: 5.0.0(ws@8.14.2) tslib: 2.6.2 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -7761,14 +7119,14 @@ packages: tslib: 2.6.2 value-or-promise: 1.0.12 - /@graphql-tools/federation@1.1.10(@types/node@18.15.13)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0): + /@graphql-tools/federation@1.1.10(@types/node@18.18.6)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-H51qTYwbtfIYBO1uHXlImRWzo9tknSoIGBgJckDh+hdxJx43sZaMjJiLHc2DjRc/A8d2Bf0bi0HbH++HqOos/w==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^16.6.0 dependencies: '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) - '@graphql-tools/executor-http': 1.0.3(@types/node@18.15.13)(graphql@16.8.1) + '@graphql-tools/executor-http': 1.0.3(@types/node@18.18.6)(graphql@16.8.1) '@graphql-tools/merge': 9.0.0(graphql@16.8.1) '@graphql-tools/schema': 10.0.0(graphql@16.8.1) '@graphql-tools/stitch': 9.0.3(graphql@16.8.1) @@ -7778,7 +7136,7 @@ packages: tslib: 2.6.2 value-or-promise: 1.0.12 optionalDependencies: - '@apollo/client': 3.8.5(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + '@apollo/client': 3.8.6(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) transitivePeerDependencies: - '@types/node' - graphql-ws @@ -7943,7 +7301,7 @@ packages: graphql: 16.8.1 tslib: 2.6.2 - /@graphql-tools/url-loader@7.17.18(@types/node@18.15.13)(graphql@16.8.1): + /@graphql-tools/url-loader@7.17.18(@types/node@18.18.6)(graphql@16.8.1): resolution: {integrity: sha512-ear0CiyTj04jCVAxi7TvgbnGDIN2HgqzXzwsfcqiVg9cvjT40NcMlZ2P1lZDgqMkZ9oyLTV8Bw6j+SyG6A+xPw==} peerDependencies: graphql: ^16.6.0 @@ -7951,24 +7309,24 @@ packages: '@ardatan/sync-fetch': 0.0.1 '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/executor-graphql-ws': 0.0.14(graphql@16.8.1) - '@graphql-tools/executor-http': 0.1.10(@types/node@18.15.13)(graphql@16.8.1) + '@graphql-tools/executor-http': 0.1.10(@types/node@18.18.6)(graphql@16.8.1) '@graphql-tools/executor-legacy-ws': 0.0.11(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) - '@types/ws': 8.5.7 + '@types/ws': 8.5.8 '@whatwg-node/fetch': 0.8.8 graphql: 16.8.1 isomorphic-ws: 5.0.0(ws@8.14.2) tslib: 2.6.2 value-or-promise: 1.0.12 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - '@types/node' - bufferutil - encoding - utf-8-validate - /@graphql-tools/url-loader@8.0.0(@types/node@18.15.13)(graphql@16.8.1): + /@graphql-tools/url-loader@8.0.0(@types/node@18.18.6)(graphql@16.8.1): resolution: {integrity: sha512-rPc9oDzMnycvz+X+wrN3PLrhMBQkG4+sd8EzaFN6dypcssiefgWKToXtRKI8HHK68n2xEq1PyrOpkjHFJB+GwA==} engines: {node: '>=16.0.0'} peerDependencies: @@ -7977,17 +7335,17 @@ packages: '@ardatan/sync-fetch': 0.0.1 '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/executor-graphql-ws': 1.1.0(graphql@16.8.1) - '@graphql-tools/executor-http': 1.0.3(@types/node@18.15.13)(graphql@16.8.1) + '@graphql-tools/executor-http': 1.0.3(@types/node@18.18.6)(graphql@16.8.1) '@graphql-tools/executor-legacy-ws': 1.0.4(graphql@16.8.1) '@graphql-tools/utils': 10.0.7(graphql@16.8.1) '@graphql-tools/wrap': 10.0.1(graphql@16.8.1) - '@types/ws': 8.5.7 + '@types/ws': 8.5.8 '@whatwg-node/fetch': 0.9.13 graphql: 16.8.1 isomorphic-ws: 5.0.0(ws@8.14.2) tslib: 2.6.2 value-or-promise: 1.0.12 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - '@types/node' - bufferutil @@ -8108,11 +7466,11 @@ packages: dependencies: '@hapi/hoek': 9.3.0 - /@humanwhocodes/config-array@0.11.11: - resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} + /@humanwhocodes/config-array@0.11.13: + resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} dependencies: - '@humanwhocodes/object-schema': 1.2.1 + '@humanwhocodes/object-schema': 2.0.1 debug: 4.3.4(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: @@ -8139,57 +7497,67 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true + /@humanwhocodes/object-schema@2.0.1: + resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + dev: true + /@hypercerts-org/contracts@0.8.11: resolution: {integrity: sha512-n6fwMsaoR50VITM2upR4OOi4EZJmZvU6vvXrHWCSakP9e1OeDuAOk+kHiK+egqDRYj6uKtg9VTUFKZBYvu3jRg==} dev: false - /@hypercerts-org/sdk@0.8.10(@babel/core@7.23.2)(@envelop/core@3.0.6)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.15.13)(graphql-tag@2.12.6)(node-fetch@3.3.2)(react-native@0.72.5)(typescript@5.1.6)(uint8arraylist@2.4.3): - resolution: {integrity: sha512-shgYIhwG93RenegpIXVDMAGiFE0hpKZynMTl9qc0Q1RjWptX3+UvaeqYK4PfSxAS9LmN9lytXt3L8JOml3WWAQ==} + /@hypercerts-org/sdk@0.8.16(@envelop/core@3.0.6)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3): + resolution: {integrity: sha512-WkxYb5RYhv3QI7+N5y4xg5IL4azLqCq4ia1/bgFB55vWJLjnmoMj3VYbiybMxyfgnPfh5O8n2DU86u8ClLgyhg==} dependencies: '@ethereum-attestation-service/eas-sdk': 0.28.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(typescript@5.1.6) '@ethersproject/abstract-signer': 5.7.0 - '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) - '@graphprotocol/client-cli': 2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.15.13)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.5) + '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) + '@graphprotocol/client-polling-live': 2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@8.4.2)(graphql@16.8.1) + '@graphql-mesh/cache-localforage': 0.95.7(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) + '@graphql-mesh/graphql': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2) + '@graphql-mesh/http': 0.96.13(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/runtime@0.96.12)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/merger-bare': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/runtime': 0.96.12(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/store': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) '@hypercerts-org/contracts': 0.8.11 '@openzeppelin/merkle-tree': 1.0.5 + '@whatwg-node/fetch': 0.9.13 ajv: 8.12.0 axios: 1.5.1(debug@4.3.4) dotenv: 16.3.1 ethers: 5.7.2 graphql: 16.8.1 ipfs-core: 0.17.0(uint8arraylist@2.4.3) - jest: 29.7.0(@types/node@18.15.13)(ts-node@10.9.1) + jest: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) loglevel: 1.8.1 mime: 3.0.0 nft.storage: 7.1.1(node-fetch@3.3.2) web3.storage: 4.5.5(node-fetch@3.3.2) transitivePeerDependencies: - - '@babel/core' - '@envelop/core' - '@ethersproject/abi' - '@ethersproject/providers' - - '@graphql-mesh/cross-helpers' - - '@graphql-mesh/store' - - '@graphql-mesh/types' - - '@graphql-mesh/utils' - '@graphql-tools/delegate' - '@graphql-tools/merge' - '@graphql-tools/utils' - '@graphql-tools/wrap' - - '@swc/core' - - '@swc/wasm' - '@types/node' - babel-plugin-macros - bufferutil - debug - encoding - - graphql-tag + - graphql-ws - node-fetch - node-notifier - - react-native - - react-native-windows + - react + - react-dom + - subscriptions-transport-ws - supports-color - ts-node + - tslib - typescript - uint8arraylist - utf-8-validate @@ -8212,7 +7580,7 @@ packages: engines: {node: '>=16.0.0', npm: '>=7.0.0'} dependencies: '@ipld/dag-cbor': 9.0.6 - cborg: 4.0.3 + cborg: 4.0.4 multiformats: 12.1.2 varint: 6.0.0 dev: false @@ -8229,7 +7597,6 @@ packages: dependencies: cborg: 1.10.2 multiformats: 9.9.0 - dev: false /@ipld/dag-cbor@8.0.1: resolution: {integrity: sha512-mHRuzgGXNk0Y5W7nNQdN37qJiig1Kdgf92icBVFRUNtBc9Ezl5DIdWfiGWBucHBrhqPBncxoH3As9cHPIRozxA==} @@ -8243,10 +7610,17 @@ packages: resolution: {integrity: sha512-3kNab5xMppgWw6DVYx2BzmFq8t7I56AGWfp5kaU1fIPkwHVpBRglJJTYsGtbVluCi/s/q97HZM3bC+aDW4sxbQ==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} dependencies: - cborg: 4.0.3 + cborg: 4.0.4 multiformats: 12.1.2 dev: false + /@ipld/dag-json@8.0.11: + resolution: {integrity: sha512-Pea7JXeYHTWXRTIhBqBlhw7G53PJ7yta3G/sizGEZyzdeEwhZRr0od5IQ0r2ZxOt1Do+2czddjeEPp+YTxDwCA==} + dependencies: + cborg: 1.10.2 + multiformats: 9.9.0 + dev: true + /@ipld/dag-json@9.1.1: resolution: {integrity: sha512-L0l+Osi8zAWUw2L/fWJjeZ75l7XojD0Mud1Xvo32q8AJeVuqvCQFdqqIFBiq8MwuqC8qS8kbysro3w5mphUiDQ==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -8259,7 +7633,6 @@ packages: resolution: {integrity: sha512-ZBnf2fuX9y3KccADURG5vb9FaOeMjFkCrNysB0PtftME/4iCTjxfaLoNq/IAh5fTqUOMXvryN6Jyka4ZGuMLIg==} dependencies: multiformats: 9.9.0 - dev: false /@ipld/dag-pb@3.0.2: resolution: {integrity: sha512-ge+llKU/CNc6rX5ZcUhCrPXJjKjN1DsolDOJ99zOsousGOhepoIgvT01iAP8s7QN9QFciOE+a1jHdccs+CyhBA==} @@ -8298,7 +7671,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -8318,14 +7691,14 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.15.13)(ts-node@10.9.1) + jest-config: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -8358,7 +7731,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 jest-mock: 29.7.0 /@jest/expect-utils@29.7.0: @@ -8382,7 +7755,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 18.15.13 + '@types/node': 18.18.6 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -8412,8 +7785,8 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.19 - '@types/node': 18.15.13 + '@jridgewell/trace-mapping': 0.3.20 + '@types/node': 18.18.6 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -8444,7 +7817,7 @@ packages: resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jridgewell/trace-mapping': 0.3.19 + '@jridgewell/trace-mapping': 0.3.20 callsites: 3.1.0 graceful-fs: 4.2.11 @@ -8454,7 +7827,7 @@ packages: dependencies: '@jest/console': 29.7.0 '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-lib-coverage': 2.0.5 collect-v8-coverage: 1.0.2 /@jest/test-sequencer@29.7.0: @@ -8472,7 +7845,7 @@ packages: dependencies: '@babel/core': 7.23.2 '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.19 + '@jridgewell/trace-mapping': 0.3.20 babel-plugin-istanbul: 6.1.1 chalk: 4.1.2 convert-source-map: 2.0.0 @@ -8492,20 +7865,20 @@ packages: resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==} engines: {node: '>= 10.14.2'} dependencies: - '@types/istanbul-lib-coverage': 2.0.4 - '@types/istanbul-reports': 3.0.2 - '@types/node': 18.15.13 - '@types/yargs': 15.0.16 + '@types/istanbul-lib-coverage': 2.0.5 + '@types/istanbul-reports': 3.0.3 + '@types/node': 18.18.6 + '@types/yargs': 15.0.17 chalk: 4.1.2 /@jest/types@27.5.1: resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@types/istanbul-lib-coverage': 2.0.4 - '@types/istanbul-reports': 3.0.2 - '@types/node': 18.15.13 - '@types/yargs': 16.0.6 + '@types/istanbul-lib-coverage': 2.0.5 + '@types/istanbul-reports': 3.0.3 + '@types/node': 18.18.6 + '@types/yargs': 16.0.7 chalk: 4.1.2 /@jest/types@29.6.3: @@ -8513,10 +7886,10 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.4 - '@types/istanbul-reports': 3.0.2 - '@types/node': 18.15.13 - '@types/yargs': 17.0.28 + '@types/istanbul-lib-coverage': 2.0.5 + '@types/istanbul-reports': 3.0.3 + '@types/node': 18.18.6 + '@types/yargs': 17.0.29 chalk: 4.1.2 /@jridgewell/gen-mapping@0.3.3: @@ -8525,7 +7898,7 @@ packages: dependencies: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.19 + '@jridgewell/trace-mapping': 0.3.20 /@jridgewell/resolve-uri@3.1.1: resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} @@ -8539,13 +7912,13 @@ packages: resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} dependencies: '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.19 + '@jridgewell/trace-mapping': 0.3.20 /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - /@jridgewell/trace-mapping@0.3.19: - resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==} + /@jridgewell/trace-mapping@0.3.20: + resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 @@ -8630,7 +8003,7 @@ packages: '@noble/secp256k1': 1.7.1 multiformats: 11.0.2 node-forge: 1.3.1 - protons-runtime: 5.0.2(uint8arraylist@2.4.3) + protons-runtime: 5.1.0 uint8arraylist: 2.4.3 uint8arrays: 4.0.6 dev: false @@ -9078,7 +8451,7 @@ packages: '@libp2p/logger': 2.1.1 '@libp2p/peer-id': 1.1.18 '@multiformats/multiaddr': 11.6.1 - '@types/multicast-dns': 7.2.2 + '@types/multicast-dns': 7.2.3 multicast-dns: 7.2.5 multiformats: 10.0.3 transitivePeerDependencies: @@ -9422,7 +8795,7 @@ packages: p-defer: 4.0.0 p-timeout: 6.1.2 wherearewe: 2.0.1 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - supports-color @@ -9487,15 +8860,46 @@ packages: tweetnacl: 1.0.3 tweetnacl-util: 0.15.1 + /@metamask/object-multiplex@1.2.0: + resolution: {integrity: sha512-hksV602d3NWE2Q30Mf2Np1WfVKaGqfJRy9vpHAmelbaD0OkDt06/0KQkRR6UVYdMbTbkuEu8xN5JDUU80inGwQ==} + engines: {node: '>=12.0.0'} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + readable-stream: 2.3.8 + dev: false + + /@metamask/providers@11.1.2: + resolution: {integrity: sha512-xjE4cKrGpKZjripkMKMStc0H4LXrWJPijfbaj1kKeDLVhRH2Yu3ZecV3iIhf1EIJePeA+Kx6Pcm7d0IVJ+ea7g==} + engines: {node: '>=16.0.0'} + dependencies: + '@metamask/object-multiplex': 1.2.0 + '@metamask/safe-event-emitter': 3.0.0 + detect-browser: 5.3.0 + eth-rpc-errors: 4.0.2 + extension-port-stream: 2.1.1 + fast-deep-equal: 3.1.3 + is-stream: 2.0.1 + json-rpc-engine: 6.1.0 + json-rpc-middleware-stream: 4.2.3 + pump: 3.0.0 + webextension-polyfill: 0.10.0 + dev: false + /@metamask/safe-event-emitter@2.0.0: resolution: {integrity: sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==} dev: false + /@metamask/safe-event-emitter@3.0.0: + resolution: {integrity: sha512-j6Z47VOmVyGMlnKXZmL0fyvWfEYtKWCA9yGZkU3FCsGZUT5lHGmvaV9JA5F2Y+010y7+ROtR3WMXIkvl/nVzqQ==} + engines: {node: '>=12.0.0'} + dev: false + /@metamask/utils@3.6.0: resolution: {integrity: sha512-9cIRrfkWvHblSiNDVXsjivqa9Ak0RYo/1H6tqTqTbAx+oBK2Sva0lWDHxGchOqA7bySGUJKAWSNJvH6gdHZ0gQ==} engines: {node: '>=14.0.0'} dependencies: - '@types/debug': 4.1.9 + '@types/debug': 4.1.10 debug: 4.3.4(supports-color@8.1.1) semver: 7.5.4 superstruct: 1.0.3 @@ -9575,7 +8979,7 @@ packages: kleur: 4.1.5 selfsigned: 2.1.1 undici: 5.9.1 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) youch: 2.2.2 transitivePeerDependencies: - bufferutil @@ -9624,7 +9028,7 @@ packages: resolution: {integrity: sha512-fWMqq3ZkWAg+k7CnyzMV/rZHugwn+/JxvVzCxrtvxzwotTN547THlOxgZe8JAP23U9BiTxOfpTfnLvFEjAmegw==} engines: {node: '>=16.13'} dependencies: - '@types/better-sqlite3': 7.6.5 + '@types/better-sqlite3': 7.6.6 kleur: 4.1.5 npx-import: 1.1.4 picomatch: 2.3.1 @@ -9668,7 +9072,7 @@ packages: '@miniflare/core': 2.11.0 '@miniflare/shared': 2.11.0 undici: 5.9.1 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -9739,7 +9143,7 @@ packages: resolution: {integrity: sha512-mlN83YSrcFgk7Dm1Mys40DLssI1KdJji2CMKN8eOlBqsTADYzj2+jWzsANsUTFbxDMWPD5e9bfA1RGqBpS3O1g==} engines: {node: '>=14'} dependencies: - '@types/set-cookie-parser': 2.4.4 + '@types/set-cookie-parser': 2.4.5 set-cookie-parser: 2.6.0 dev: true @@ -9748,7 +9152,7 @@ packages: engines: {node: '>=14'} dependencies: '@open-draft/until': 1.0.3 - '@types/debug': 4.1.9 + '@types/debug': 4.1.10 '@xmldom/xmldom': 0.8.10 debug: 4.3.4(supports-color@8.1.1) headers-polyfill: 3.2.5 @@ -9759,8 +9163,8 @@ packages: - supports-color dev: true - /@mui/base@5.0.0-beta.19(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-maNBgAscddyPNzFZQUJDF/puxM27Li+NqSBsr/lAP8TLns2VvWS2SoL3OKFOIoRnAMKGY/Ic6Aot6gCYeQnssA==} + /@mui/base@5.0.0-beta.20(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-CS2pUuqxST7ch9VNDCklRYDbJ3rru20Tx7na92QvVVKfu3RL4z/QLuVIc8jYGsdCnauMaeUSlFNLAJNb0yXe6w==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -9770,24 +9174,24 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0)(react@18.2.0) - '@mui/types': 7.2.6(@types/react@18.2.28) - '@mui/utils': 5.14.13(@types/react@18.2.28)(react@18.2.0) + '@mui/types': 7.2.6(@types/react@18.2.31) + '@mui/utils': 5.14.14(@types/react@18.2.31)(react@18.2.0) '@popperjs/core': 2.11.8 - '@types/react': 18.2.28 + '@types/react': 18.2.31 clsx: 2.0.0 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /@mui/core-downloads-tracker@5.14.13: - resolution: {integrity: sha512-3ZUbzcH4yloLKlV6Y+S0Edn2wef9t+EGHSfEkwVCn8E0ULdshifEFgfEroKRegQifDIwcKS/ofccxuZ8njTAYg==} + /@mui/core-downloads-tracker@5.14.14: + resolution: {integrity: sha512-Rw/xKiTOUgXD8hdKqj60aC6QcGprMipG7ne2giK6Mz7b4PlhL/xog9xLeclY3BxsRLkZQ05egFnIEY1CSibTbw==} dev: false - /@mui/icons-material@5.14.13(@mui/material@5.14.13)(@types/react@18.2.28)(react@18.2.0): - resolution: {integrity: sha512-fxKE1UrjI4xVxHe9IAGuVQZrc18dSBJg0P+Sqi2SZmcDUCShmgRq6Jq7l7GduvuMIkOSqAJdNgLtXmtmZkjtLg==} + /@mui/icons-material@5.14.14(@mui/material@5.14.14)(@types/react@18.2.31)(react@18.2.0): + resolution: {integrity: sha512-vwuaMsKvI7AWTeYqR8wYbpXijuU8PzMAJWRAq2DDIuOZPxjKyHlr8WQ25+azZYkIXtJ7AqnVb1ZmHdEyB4/kug==} engines: {node: '>=12.0.0'} peerDependencies: '@mui/material': ^5.0.0 @@ -9797,14 +9201,14 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.1 - '@mui/material': 5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0) - '@types/react': 18.2.28 + '@babel/runtime': 7.23.2 + '@mui/material': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.31 react: 18.2.0 dev: false - /@mui/material@5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-iPEFwhoVG789UVsXX4gqd1eJUlcLW1oceqwJYQN8Z4MpcAKfL9Lv3fda65AwG7pQ5lf+d7IbHzm4m48SWZxI2g==} + /@mui/material@5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cAmCwAHFQXxb44kWbVFkhKATN8tACgMsFwrXo8ro6WzYW73U/qsR5AcCiJIhCyYYg+gcftfkmNcpRaV3JjhHCg==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -9820,16 +9224,16 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.1 - '@emotion/react': 11.11.1(@types/react@18.2.28)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.28)(react@18.2.0) - '@mui/base': 5.0.0-beta.19(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0) - '@mui/core-downloads-tracker': 5.14.13 - '@mui/system': 5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.28)(react@18.2.0) - '@mui/types': 7.2.6(@types/react@18.2.28) - '@mui/utils': 5.14.13(@types/react@18.2.28)(react@18.2.0) - '@types/react': 18.2.28 - '@types/react-transition-group': 4.4.7 + '@babel/runtime': 7.23.2 + '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) + '@mui/base': 5.0.0-beta.20(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) + '@mui/core-downloads-tracker': 5.14.14 + '@mui/system': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react@18.2.0) + '@mui/types': 7.2.6(@types/react@18.2.31) + '@mui/utils': 5.14.14(@types/react@18.2.31)(react@18.2.0) + '@types/react': 18.2.31 + '@types/react-transition-group': 4.4.8 clsx: 2.0.0 csstype: 3.1.2 prop-types: 15.8.1 @@ -9839,8 +9243,8 @@ packages: react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: false - /@mui/private-theming@5.14.13(@types/react@18.2.28)(react@18.2.0): - resolution: {integrity: sha512-5EFqk4tqiSwPguj4NW/6bUf4u1qoUWXy9lrKfNh9H6oAohM+Ijv/7qSxFjnxPGBctj469/Sc5aKAR35ILBKZLQ==} + /@mui/private-theming@5.14.14(@types/react@18.2.31)(react@18.2.0): + resolution: {integrity: sha512-n77au3CQj9uu16hak2Y+rvbGSBaJKxziG/gEbOLVGrAuqZ+ycVSkorCfN6Y/4XgYOpG/xvmuiY3JwhAEOzY3iA==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -9849,15 +9253,15 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.1 - '@mui/utils': 5.14.13(@types/react@18.2.28)(react@18.2.0) - '@types/react': 18.2.28 + '@babel/runtime': 7.23.2 + '@mui/utils': 5.14.14(@types/react@18.2.31)(react@18.2.0) + '@types/react': 18.2.31 prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/styled-engine@5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): - resolution: {integrity: sha512-1ff/egFQl26hiwcUtCMKAkp4Sgqpm3qIewmXq+GN27fb44lDIACquehMFBuadOjceOFmbIXbayzbA46ZyqFYzA==} + /@mui/styled-engine@5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): + resolution: {integrity: sha512-sF3DS2PVG+cFWvkVHQQaGFpL1h6gSwOW3L91pdxPLQDHDZ5mZ/X0SlXU5XA+WjypoysG4urdAQC7CH/BRvUiqg==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.4.1 @@ -9869,17 +9273,17 @@ packages: '@emotion/styled': optional: true dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@emotion/cache': 11.11.0 - '@emotion/react': 11.11.1(@types/react@18.2.28)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.28)(react@18.2.0) + '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) csstype: 3.1.2 prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/system@5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.28)(react@18.2.0): - resolution: {integrity: sha512-+5+Dx50lG4csbx2sGjrKLozXQJeCpJ4dIBZolyFLkZ+XphD1keQWouLUvJkPQ3MSglLLKuD37pp52YjMncZMEQ==} + /@mui/system@5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react@18.2.0): + resolution: {integrity: sha512-y4InFmCgGGWXnz+iK4jRTWVikY0HgYnABjz4wgiUgEa2W1H8M4ow+27BegExUWPkj4TWthQ2qG9FOGSMtI+PKA==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -9894,21 +9298,21 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.1 - '@emotion/react': 11.11.1(@types/react@18.2.28)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.28)(react@18.2.0) - '@mui/private-theming': 5.14.13(@types/react@18.2.28)(react@18.2.0) - '@mui/styled-engine': 5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) - '@mui/types': 7.2.6(@types/react@18.2.28) - '@mui/utils': 5.14.13(@types/react@18.2.28)(react@18.2.0) - '@types/react': 18.2.28 + '@babel/runtime': 7.23.2 + '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) + '@mui/private-theming': 5.14.14(@types/react@18.2.31)(react@18.2.0) + '@mui/styled-engine': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) + '@mui/types': 7.2.6(@types/react@18.2.31) + '@mui/utils': 5.14.14(@types/react@18.2.31)(react@18.2.0) + '@types/react': 18.2.31 clsx: 2.0.0 csstype: 3.1.2 prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/types@7.2.6(@types/react@18.2.28): + /@mui/types@7.2.6(@types/react@18.2.31): resolution: {integrity: sha512-7sjLQrUmBwufm/M7jw/quNiPK/oor2+pGUQP2CULRcFCArYTq78oJ3D5esTaL0UMkXKJvDqXn6Ike69yAOBQng==} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -9916,11 +9320,11 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 dev: false - /@mui/utils@5.14.13(@types/react@18.2.28)(react@18.2.0): - resolution: {integrity: sha512-2AFpyXWw7uDCIqRu7eU2i/EplZtks5LAMzQvIhC79sPV9IhOZU2qwOWVnPtdctRXiQJOAaXulg+A37pfhEueQw==} + /@mui/utils@5.14.14(@types/react@18.2.31)(react@18.2.0): + resolution: {integrity: sha512-3AKp8uksje5sRfVrtgG9Q/2TBsHWVBUtA0NaXliZqGcXo8J+A+Agp0qUW2rJ+ivgPWTCCubz9FZVT2IQZ3bGsw==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -9929,15 +9333,15 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.1 - '@types/prop-types': 15.7.8 - '@types/react': 18.2.28 + '@babel/runtime': 7.23.2 + '@types/prop-types': 15.7.9 + '@types/react': 18.2.31 prop-types: 15.8.1 react: 18.2.0 react-is: 18.2.0 dev: false - /@mui/x-date-pickers@5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.13)(@mui/system@5.14.13)(@types/react@18.2.28)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0): + /@mui/x-date-pickers@5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(@mui/system@5.14.14)(@types/react@18.2.31)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-ERukSeHIoNLbI1C2XRhF9wRhqfsr+Q4B1SAw2ZlU7CWgcG8UBOxgqRKDEOVAIoSWL+DWT6GRuQjOKvj6UXZceA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -9965,18 +9369,18 @@ packages: moment: optional: true dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@date-io/core': 2.17.0 '@date-io/date-fns': 2.17.0 '@date-io/dayjs': 2.17.0(dayjs@1.11.10) '@date-io/luxon': 2.17.0 '@date-io/moment': 2.17.0 - '@emotion/react': 11.11.1(@types/react@18.2.28)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.28)(react@18.2.0) - '@mui/material': 5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0) - '@mui/system': 5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.28)(react@18.2.0) - '@mui/utils': 5.14.13(@types/react@18.2.28)(react@18.2.0) - '@types/react-transition-group': 4.4.7 + '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) + '@mui/material': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) + '@mui/system': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react@18.2.0) + '@mui/utils': 5.14.14(@types/react@18.2.31)(react@18.2.0) + '@types/react-transition-group': 4.4.8 clsx: 1.2.1 dayjs: 1.11.10 prop-types: 15.8.1 @@ -10058,8 +9462,8 @@ packages: murmurhash3js-revisited: 3.0.0 dev: false - /@next/env@13.5.4: - resolution: {integrity: sha512-LGegJkMvRNw90WWphGJ3RMHMVplYcOfRWf2Be3td3sUa+1AaxmsYyANsA+znrGCBjXJNi4XAQlSoEfUxs/4kIQ==} + /@next/env@13.5.6: + resolution: {integrity: sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==} dev: false /@next/eslint-plugin-next@12.2.0: @@ -10068,14 +9472,14 @@ packages: glob: 7.1.7 dev: true - /@next/eslint-plugin-next@13.5.4: - resolution: {integrity: sha512-vI94U+D7RNgX6XypSyjeFrOzxGlZyxOplU0dVE5norIfZGn/LDjJYPHdvdsR5vN1eRtl6PDAsOHmycFEOljK5A==} + /@next/eslint-plugin-next@13.5.6: + resolution: {integrity: sha512-ng7pU/DDsxPgT6ZPvuprxrkeew3XaRf4LAT4FabaEO/hAbvVx4P7wqnqdbTdDn1kgTvsI4tpIgT4Awn/m0bGbg==} dependencies: glob: 7.1.7 dev: false - /@next/swc-darwin-arm64@13.5.4: - resolution: {integrity: sha512-Df8SHuXgF1p+aonBMcDPEsaahNo2TCwuie7VXED4FVyECvdXfRT9unapm54NssV9tF3OQFKBFOdlje4T43VO0w==} + /@next/swc-darwin-arm64@13.5.6: + resolution: {integrity: sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -10083,8 +9487,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@13.5.4: - resolution: {integrity: sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==} + /@next/swc-darwin-x64@13.5.6: + resolution: {integrity: sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -10092,8 +9496,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@13.5.4: - resolution: {integrity: sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==} + /@next/swc-linux-arm64-gnu@13.5.6: + resolution: {integrity: sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -10101,8 +9505,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@13.5.4: - resolution: {integrity: sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==} + /@next/swc-linux-arm64-musl@13.5.6: + resolution: {integrity: sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -10110,8 +9514,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@13.5.4: - resolution: {integrity: sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==} + /@next/swc-linux-x64-gnu@13.5.6: + resolution: {integrity: sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -10119,8 +9523,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@13.5.4: - resolution: {integrity: sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==} + /@next/swc-linux-x64-musl@13.5.6: + resolution: {integrity: sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -10128,8 +9532,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@13.5.4: - resolution: {integrity: sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==} + /@next/swc-win32-arm64-msvc@13.5.6: + resolution: {integrity: sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -10137,8 +9541,8 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@13.5.4: - resolution: {integrity: sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==} + /@next/swc-win32-ia32-msvc@13.5.6: + resolution: {integrity: sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -10146,8 +9550,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@13.5.4: - resolution: {integrity: sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==} + /@next/swc-win32-x64-msvc@13.5.6: + resolution: {integrity: sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -10190,6 +9594,7 @@ packages: /@noble/hashes@1.3.2: resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} engines: {node: '>= 16'} + dev: false /@noble/secp256k1@1.7.1: resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} @@ -10369,7 +9774,7 @@ packages: dependencies: '@ethersproject/abi': 5.7.0 '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.13.1) - '@types/chai-as-promised': 7.1.6 + '@types/chai-as-promised': 7.1.7 chai: 4.3.10 chai-as-promised: 7.1.1(chai@4.3.10) deep-eql: 4.1.3 @@ -10387,7 +9792,7 @@ packages: hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) dev: true - /@nomicfoundation/hardhat-toolbox@2.0.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-chai-matchers@1.0.6)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(@typechain/ethers-v5@11.1.2)(@typechain/hardhat@9.1.0)(@types/chai@4.3.7)(@types/mocha@9.1.0)(@types/node@18.15.13)(chai@4.3.10)(ethers@5.7.2)(hardhat-gas-reporter@1.0.9)(hardhat@2.13.1)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.1)(typescript@4.9.5): + /@nomicfoundation/hardhat-toolbox@2.0.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-chai-matchers@1.0.6)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(@typechain/ethers-v5@11.1.2)(@typechain/hardhat@9.1.0)(@types/chai@4.3.9)(@types/mocha@9.1.0)(@types/node@18.18.6)(chai@4.3.10)(ethers@5.7.2)(hardhat-gas-reporter@1.0.9)(hardhat@2.13.1)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.2)(typescript@4.9.5): resolution: {integrity: sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg==} peerDependencies: '@ethersproject/abi': ^5.4.7 @@ -10416,18 +9821,18 @@ packages: '@nomicfoundation/hardhat-network-helpers': 1.0.9(hardhat@2.13.1) '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.13.1) '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.13.1) - '@typechain/ethers-v5': 11.1.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@4.9.5) - '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.1) - '@types/chai': 4.3.7 + '@typechain/ethers-v5': 11.1.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) + '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2) + '@types/chai': 4.3.9 '@types/mocha': 9.1.0 - '@types/node': 18.15.13 + '@types/node': 18.18.6 chai: 4.3.10 ethers: 5.7.2 hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) hardhat-gas-reporter: 1.0.9(hardhat@2.13.1) solidity-coverage: 0.8.5(hardhat@2.13.1) - ts-node: 10.9.1(@types/node@18.15.13)(typescript@4.9.5) - typechain: 8.3.1(typescript@4.9.5) + ts-node: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + typechain: 8.3.2(typescript@4.9.5) typescript: 4.9.5 dev: true @@ -10536,47 +9941,155 @@ packages: hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) dev: true - /@nomiclabs/hardhat-etherscan@3.1.7(hardhat@2.13.1): - resolution: {integrity: sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==} - peerDependencies: - hardhat: ^2.0.4 + /@nomiclabs/hardhat-etherscan@3.1.7(hardhat@2.13.1): + resolution: {integrity: sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==} + peerDependencies: + hardhat: ^2.0.4 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/address': 5.7.0 + cbor: 8.1.0 + chalk: 2.4.2 + debug: 4.3.4(supports-color@8.1.1) + fs-extra: 7.0.1 + hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + lodash: 4.17.21 + semver: 6.3.1 + table: 6.8.1 + undici: 5.26.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@observablehq/inspector@5.0.0: + resolution: {integrity: sha512-Vvg/TQdsZTUaeYbH0IKxYEz37FbRO6kdowoz2PrHLQif54NC1CjEihEjg+ZMSBn587GQxTFABu0CGkFZgtR1UQ==} + dependencies: + isoformat: 0.2.1 + dev: false + + /@observablehq/runtime@5.9.4: + resolution: {integrity: sha512-r+2TjUH4oZlTkmZnk0tj4kgAe1C2O+KVPjWqxH/6G5fF38UAYlUf/+ONFmLotsXs0BkqHKXIui5U8dMdeMkncw==} + dependencies: + '@observablehq/inspector': 5.0.0 + '@observablehq/stdlib': 5.8.3 + dev: false + + /@observablehq/stdlib@5.8.3: + resolution: {integrity: sha512-XmuwqzAMZ8H0ICJfzd5wV3WD6nLlC2XwhMIdu2QDZppTSxGafATMSbgZ2JaiNPCejenkpERGmoC3W83FUGuNeg==} + engines: {node: '>=14.5.0'} + dependencies: + d3-array: 3.2.4 + d3-dsv: 3.0.1 + d3-require: 1.3.0 + dev: false + + /@oclif/core@2.15.0(@types/node@18.18.6)(typescript@4.9.5): + resolution: {integrity: sha512-fNEMG5DzJHhYmI3MgpByTvltBOMyFcnRIUMxbiz2ai8rhaYgaTHMG3Q38HcosfIvtw9nCjxpcQtC8MN8QtVCcA==} + engines: {node: '>=14.0.0'} + dependencies: + '@types/cli-progress': 3.11.4 + ansi-escapes: 4.3.2 + ansi-styles: 4.3.0 + cardinal: 2.1.1 + chalk: 4.1.2 + clean-stack: 3.0.1 + cli-progress: 3.12.0 + debug: 4.3.4(supports-color@8.1.1) + ejs: 3.1.9 + get-package-type: 0.1.0 + globby: 11.1.0 + hyperlinker: 1.0.0 + indent-string: 4.0.0 + is-wsl: 2.2.0 + js-yaml: 3.14.1 + natural-orderby: 2.0.3 + object-treeify: 1.1.33 + password-prompt: 1.1.3 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + supports-color: 8.1.1 + supports-hyperlinks: 2.3.0 + ts-node: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + tslib: 2.6.2 + widest-line: 3.1.0 + wordwrap: 1.0.0 + wrap-ansi: 7.0.0 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - typescript + dev: true + + /@oclif/core@2.8.6(@types/node@18.18.6)(typescript@4.9.5): + resolution: {integrity: sha512-1QlPaHMhOORySCXkQyzjsIsy2GYTilOw3LkjeHkCgsPJQjAT4IclVytJusWktPbYNys9O+O4V23J44yomQvnBQ==} + engines: {node: '>=14.0.0'} dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/address': 5.7.0 - cbor: 8.1.0 - chalk: 2.4.2 + '@types/cli-progress': 3.11.4 + ansi-escapes: 4.3.2 + ansi-styles: 4.3.0 + cardinal: 2.1.1 + chalk: 4.1.2 + clean-stack: 3.0.1 + cli-progress: 3.12.0 debug: 4.3.4(supports-color@8.1.1) - fs-extra: 7.0.1 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) - lodash: 4.17.21 - semver: 6.3.1 - table: 6.8.1 - undici: 5.26.0 + ejs: 3.1.9 + fs-extra: 9.1.0 + get-package-type: 0.1.0 + globby: 11.1.0 + hyperlinker: 1.0.0 + indent-string: 4.0.0 + is-wsl: 2.2.0 + js-yaml: 3.14.1 + natural-orderby: 2.0.3 + object-treeify: 1.1.33 + password-prompt: 1.1.3 + semver: 7.5.4 + string-width: 4.2.3 + strip-ansi: 6.0.1 + supports-color: 8.1.1 + supports-hyperlinks: 2.3.0 + ts-node: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + tslib: 2.6.2 + widest-line: 3.1.0 + wordwrap: 1.0.0 + wrap-ansi: 7.0.0 transitivePeerDependencies: - - supports-color + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - typescript dev: true - /@observablehq/inspector@5.0.0: - resolution: {integrity: sha512-Vvg/TQdsZTUaeYbH0IKxYEz37FbRO6kdowoz2PrHLQif54NC1CjEihEjg+ZMSBn587GQxTFABu0CGkFZgtR1UQ==} - dependencies: - isoformat: 0.2.1 - dev: false - - /@observablehq/runtime@5.9.3: - resolution: {integrity: sha512-dRgqbClP4QiOSlInp6NaBXRPK7fJ2LtyPY/xppR8p9COTgwAPlP0/wHL8d1OD4f6AgwWXMqotiZqmduXsZgkSQ==} + /@oclif/plugin-autocomplete@2.3.10(@types/node@18.18.6)(typescript@4.9.5): + resolution: {integrity: sha512-Ow1AR8WtjzlyCtiWWPgzMyT8SbcDJFr47009riLioHa+MHX2BCDtVn2DVnN/E6b9JlPV5ptQpjefoRSNWBesmg==} + engines: {node: '>=12.0.0'} dependencies: - '@observablehq/inspector': 5.0.0 - '@observablehq/stdlib': 5.8.3 - dev: false + '@oclif/core': 2.15.0(@types/node@18.18.6)(typescript@4.9.5) + chalk: 4.1.2 + debug: 4.3.4(supports-color@8.1.1) + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - supports-color + - typescript + dev: true - /@observablehq/stdlib@5.8.3: - resolution: {integrity: sha512-XmuwqzAMZ8H0ICJfzd5wV3WD6nLlC2XwhMIdu2QDZppTSxGafATMSbgZ2JaiNPCejenkpERGmoC3W83FUGuNeg==} - engines: {node: '>=14.5.0'} + /@oclif/plugin-not-found@2.4.3(@types/node@18.18.6)(typescript@4.9.5): + resolution: {integrity: sha512-nIyaR4y692frwh7wIHZ3fb+2L6XEecQwRDIb4zbEam0TvaVmBQWZoColQyWA84ljFBPZ8XWiQyTz+ixSwdRkqg==} + engines: {node: '>=12.0.0'} dependencies: - d3-array: 3.2.4 - d3-dsv: 3.0.1 - d3-require: 1.3.0 - dev: false + '@oclif/core': 2.15.0(@types/node@18.18.6)(typescript@4.9.5) + chalk: 4.1.2 + fast-levenshtein: 3.0.0 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - typescript + dev: true /@open-draft/until@1.0.3: resolution: {integrity: sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==} @@ -10680,7 +10193,7 @@ packages: '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.13.1) '@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4) '@openzeppelin/platform-deploy-client': 0.8.0(debug@4.3.4) - '@openzeppelin/upgrades-core': 1.30.1 + '@openzeppelin/upgrades-core': 1.31.0 chalk: 4.1.2 debug: 4.3.4(supports-color@8.1.1) ethers: 5.7.2 @@ -10712,8 +10225,8 @@ packages: - encoding dev: true - /@openzeppelin/upgrades-core@1.30.1: - resolution: {integrity: sha512-mFUsZibpiWJv1DR2K89cjbFIseTc2CUV4D2kvPPK5xYke6m7+M87qcr/Xk24mMrdCmG7RWNxQohhVnzESI6Eeg==} + /@openzeppelin/upgrades-core@1.31.0: + resolution: {integrity: sha512-E1Cz8lVpo2mnBeFWxiGDLWtuTYMFNTEWwbnhle4dZ+5UHX6xTRO+Q/CaWBHm33HHhuuiUbRwgGNnAR9zOu+fyQ==} hasBin: true dependencies: cbor: 9.0.1 @@ -10728,8 +10241,8 @@ packages: - supports-color dev: true - /@peculiar/asn1-schema@2.3.6: - resolution: {integrity: sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA==} + /@peculiar/asn1-schema@2.3.8: + resolution: {integrity: sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==} dependencies: asn1js: 3.0.5 pvtsutils: 1.3.5 @@ -10745,7 +10258,7 @@ packages: resolution: {integrity: sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==} engines: {node: '>=10.12.0'} dependencies: - '@peculiar/asn1-schema': 2.3.6 + '@peculiar/asn1-schema': 2.3.8 '@peculiar/json-schema': 1.1.12 pvtsutils: 1.3.5 tslib: 2.6.2 @@ -10757,22 +10270,22 @@ packages: requiresBuild: true optional: true - /@plasmicapp/data-sources-context@0.1.15(react@18.2.0): - resolution: {integrity: sha512-y5JFBR490+oNrpwEo4fWTcgqB3dipEhS8khOLqHmy+ZSmp5OAp4Qh7v65XlQ4IoRitoqQoJuJ90QHfDrx4m0Og==} + /@plasmicapp/data-sources-context@0.1.17(react@18.2.0): + resolution: {integrity: sha512-vCAcgcxT6+MOn+rGlVszGDHPqBTGszzNZ4FuwXkX5RjN4W7VG8Vep6qpZC2KUZI0KpjGmGq3uLkeK4BcvciRzA==} engines: {node: '>=10'} peerDependencies: - react: '>=16' + react: '>=16.8.0' dependencies: react: 18.2.0 dev: false - /@plasmicapp/host@1.0.171(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-yMkUq+MakBij6WfJEVR0s72KUXUoodY2GhX3WPEj1rpNlb6k03IbkkLiJM1hYN6dFvP7TKI4Pq6fR0mm0X6x8g==} + /@plasmicapp/host@1.0.177(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-TqipEiPaTZyz8wqQe/XJrdDAs0SIB99QINxZwtgvGjil47biFO0dhCk8Mv1JsrKyRTxRu5MCBToND8xpatXsBQ==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: - '@plasmicapp/query': 0.1.72(react@18.2.0) + '@plasmicapp/query': 0.1.74(react@18.2.0) csstype: 3.1.2 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -10785,42 +10298,41 @@ packages: unfetch: 4.2.0 dev: false - /@plasmicapp/loader-core@1.0.112: - resolution: {integrity: sha512-hS8oKhzA73JEW59UQBWNGpATs84GQSBj+ANSOxmbvfEPh+v9HYn9627y3tKsMTaGHdAtp5iDH8cOQGIFxYF2hA==} + /@plasmicapp/loader-core@1.0.115: + resolution: {integrity: sha512-Ip/I4kuBFnsOB7DrCTrkhOCfSCGYknDTH83qiWpbQdYwCxWCHUsCtY3P3j9K8U4NYjFgy3OL4d0EkAtOvoBCTw==} engines: {node: '>=10'} dependencies: '@plasmicapp/isomorphic-unfetch': 1.0.3 - '@plasmicapp/loader-fetcher': 1.0.35 + '@plasmicapp/loader-fetcher': 1.0.37 dev: false - /@plasmicapp/loader-edge@1.0.41: - resolution: {integrity: sha512-Kw3et94sLUSMhhwp+907q0PY/FcjY1hErkEp4QKaw4wgyDfcg5RNtGimjac+xAu59JiGvX+D6sCvqzB6MuGlYw==} + /@plasmicapp/loader-edge@1.0.46: + resolution: {integrity: sha512-r3PA6ARF3EDWma5kwHOgPu/meed7hkKnkDp2aUWiHQKe7X0eRDWXpId/+2uYVzh8p1sjIxiINK6P9Bv1jVuXrQ==} engines: {node: '>=10'} dependencies: - '@plasmicapp/loader-fetcher': 1.0.35 - '@plasmicapp/loader-splits': 1.0.40 + '@plasmicapp/loader-splits': 1.0.43 dev: false - /@plasmicapp/loader-fetcher@1.0.35: - resolution: {integrity: sha512-QHpgxMi+Nl9lgEs3uIjRPcYt/KW2txXNsPKMoh6+KtebktOsH0n1bbl65cY7PbivYMEgVBJ3aSGMWeJaHLKYCg==} + /@plasmicapp/loader-fetcher@1.0.37: + resolution: {integrity: sha512-yLrOGklV8FNeyNteumzuE99zvPVGvNTT7TuLQISMvCkisY+pg4NY6gDxSUvDut65waBH0ie/ZdG6jUtkqb0kBg==} engines: {node: '>=10'} dependencies: '@plasmicapp/isomorphic-unfetch': 1.0.3 dev: false - /@plasmicapp/loader-nextjs@1.0.321(next@13.5.4)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-myXKOPHciWT+FL8PyetXmH1ST4yH74AQqvPXBl4KLBE1fQSxc5EVJOcdqnLfOm8M0NkigMUtjIR+kktf2NkzQg==} + /@plasmicapp/loader-nextjs@1.0.333(next@13.5.6)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Uhkeeig9UhZQqLgH5QPuV3bd1jE4Z5ZsJgvoxmsL96XrGEuxEO2wUPLq02HQ+EgJtXuNTgbb5bSPZsVCJ/nCKQ==} engines: {node: '>=10'} peerDependencies: next: '>=10.1.0' react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: - '@plasmicapp/loader-core': 1.0.112 - '@plasmicapp/loader-edge': 1.0.41 - '@plasmicapp/loader-react': 1.0.302(react-dom@18.2.0)(react@18.2.0) - '@plasmicapp/watcher': 1.0.76 - next: 13.5.4(@babel/core@7.23.2)(react-dom@18.2.0)(react@18.2.0) + '@plasmicapp/loader-core': 1.0.115 + '@plasmicapp/loader-edge': 1.0.46 + '@plasmicapp/loader-react': 1.0.312(react-dom@18.2.0)(react@18.2.0) + '@plasmicapp/watcher': 1.0.78 + next: 13.5.6(@babel/core@7.23.2)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) server-only: 0.0.1 @@ -10830,51 +10342,50 @@ packages: - utf-8-validate dev: false - /@plasmicapp/loader-react@1.0.302(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-Gm+iZknV+16ELdUKKnvTSrkjRtmkQ5bphUgOkQO/jGoIV7PqZzG0kDELYYleEsorStOPg9kelQ4Lyi3LZg8OCg==} + /@plasmicapp/loader-react@1.0.312(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-nUu9TJrlu5/innWFTz1rvJx4NQgm/yLNZwK27cbLufQCYzec4FBdGEr4Ywr7IMHb4OHTzJOJG3ZsEDmFjTeJ3Q==} engines: {node: '>=12'} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: - '@plasmicapp/data-sources-context': 0.1.15(react@18.2.0) - '@plasmicapp/host': 1.0.171(react-dom@18.2.0)(react@18.2.0) - '@plasmicapp/loader-core': 1.0.112 - '@plasmicapp/loader-splits': 1.0.40 - '@plasmicapp/prepass': 1.0.7(react-dom@18.2.0)(react@18.2.0) - '@plasmicapp/query': 0.1.72(react@18.2.0) + '@plasmicapp/data-sources-context': 0.1.17(react@18.2.0) + '@plasmicapp/host': 1.0.177(react-dom@18.2.0)(react@18.2.0) + '@plasmicapp/loader-core': 1.0.115 + '@plasmicapp/loader-splits': 1.0.43 + '@plasmicapp/prepass': 1.0.9(react-dom@18.2.0)(react@18.2.0) + '@plasmicapp/query': 0.1.74(react@18.2.0) pascalcase: 1.0.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) server-only: 0.0.1 dev: false - /@plasmicapp/loader-splits@1.0.40: - resolution: {integrity: sha512-rjMjPhjtYE0LTexANQ6RIlz2rNSms9A0p1BH4m/OnvF7p9u1vxsNQ2vqDfkKxyfZkfG0+/hbQF2ODggs4Qvjgg==} + /@plasmicapp/loader-splits@1.0.43: + resolution: {integrity: sha512-XdSiD/N9ddD/HTjsk6EUhU0SSLFzQl0G4vlapdcHIBI9vBZRLAJQLGPIS98OJJnEK3DsE7j4kMYzKevoE/bycQ==} engines: {node: '>=10'} dependencies: - '@plasmicapp/loader-fetcher': 1.0.35 json-logic-js: 2.0.2 dev: false - /@plasmicapp/prepass@1.0.7(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-wBCbiGvirExoDXhkWryblNcx6nQ4D95HkME9IiRDT+IdKOH/7o2yAKBAqBCxbAzQznxX1R8GnTNWvVtCG+qJ0w==} + /@plasmicapp/prepass@1.0.9(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-0iG7iCD/Kf0I1Qaxw/steVPm3p2ciBPeA8Xa4i/E34gEat5qRsGl6cMi4V2EaPLWOF4cL6B+PEdtHCmZBscOGw==} engines: {node: '>=12'} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: - '@plasmicapp/query': 0.1.72(react@18.2.0) + '@plasmicapp/query': 0.1.74(react@18.2.0) '@plasmicapp/react-ssr-prepass': 2.0.3(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /@plasmicapp/query@0.1.72(react@18.2.0): - resolution: {integrity: sha512-7kR7t4IKdXwrGCRnwQQbWDaJy8AqiujYZFvRaF1cQUSL6TcgNCXOWeIdCcnwsP3BpjdNfu+HEgvR5y+GuyN5Hw==} + /@plasmicapp/query@0.1.74(react@18.2.0): + resolution: {integrity: sha512-5ZwplvH/ObqBFTgB3hG2nA72F5DqV8bCsDnxM/O+Z8o1IsFRI4xkdj1pMQY/bkrLshMFA6uu6jZJTPU/dRnxJA==} engines: {node: '>=10'} peerDependencies: - react: '>=16' + react: '>=16.8.0' dependencies: react: 18.2.0 swr: 1.3.0(react@18.2.0) @@ -10888,8 +10399,8 @@ packages: react: 18.2.0 dev: false - /@plasmicapp/watcher@1.0.76: - resolution: {integrity: sha512-wYMto8wa38OQ9fynVmVUD77KZJBbbGKl07lpIFOM94HKKTCTFVCvMdyt7/b1/Y9AelYZ6R2y9vOP3SoC5jFzVg==} + /@plasmicapp/watcher@1.0.78: + resolution: {integrity: sha512-YvBtGMkI6pvqgagwP72Rr5btZ3iJsIOyInH7XsT3vDopWaQfrEm2oB4sVwxUxnsxnUZPniH/LHCwn4QJsPmdfQ==} engines: {node: '>=10'} dependencies: socket.io-client: 4.7.2 @@ -10899,12 +10410,12 @@ packages: - utf-8-validate dev: false - /@playwright/test@1.38.1: - resolution: {integrity: sha512-NqRp8XMwj3AK+zKLbZShl0r/9wKgzqI/527bkptKXomtuo+dOjU9NdMASQ8DNC9z9zLOMbG53T4eihYr3XR+BQ==} + /@playwright/test@1.39.0: + resolution: {integrity: sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ==} engines: {node: '>=16'} hasBin: true dependencies: - playwright: 1.38.1 + playwright: 1.39.0 dev: true /@polka/url@1.0.0-next.23: @@ -10927,48 +10438,38 @@ packages: /@protobufjs/aspromise@1.1.2: resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} - dev: false /@protobufjs/base64@1.1.2: resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - dev: false /@protobufjs/codegen@2.0.4: resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} - dev: false /@protobufjs/eventemitter@1.1.0: resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} - dev: false /@protobufjs/fetch@1.1.0: resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/inquire': 1.1.0 - dev: false /@protobufjs/float@1.0.2: resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - dev: false /@protobufjs/inquire@1.1.0: resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} - dev: false /@protobufjs/path@1.1.2: resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} - dev: false /@protobufjs/pool@1.1.0: resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - dev: false /@protobufjs/utf8@1.1.0: resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - dev: false - /@rainbow-me/rainbowkit@1.0.8(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9): + /@rainbow-me/rainbowkit@1.0.8(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9): resolution: {integrity: sha512-m1B9/X3p8MLmj4fDfs2NpJlFRmKz7vOR0jmcdBw2SMFzXqP1FQFQc4pjvtLEeyfEUGSNNceGrecFZRVS0Qk//A==} engines: {node: '>=12.4'} peerDependencies: @@ -10984,9 +10485,9 @@ packages: qrcode: 1.5.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.4(@types/react@18.2.28)(react@18.2.0) + react-remove-scroll: 2.5.4(@types/react@18.2.31)(react@18.2.0) viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) - wagmi: 1.3.9(@types/react@18.2.28)(react-dom@18.2.0)(react-native@0.72.5)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + wagmi: 1.3.9(@types/react@18.2.31)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) transitivePeerDependencies: - '@types/react' dev: false @@ -11040,7 +10541,7 @@ packages: strip-ansi: 5.2.0 sudo-prompt: 9.2.1 wcwidth: 1.0.1 - yaml: 2.3.1 + yaml: 2.3.3 transitivePeerDependencies: - encoding @@ -11191,18 +10692,22 @@ packages: /@react-native/normalize-colors@0.72.0: resolution: {integrity: sha512-285lfdqSXaqKuBbbtP9qL2tDrfxdOFtIMvkKadtleRQkdOxx+uzGvFr82KHmc/sSiMtfXGp7JnFYWVh4sFl7Yw==} - /@react-native/virtualized-lists@0.72.8(react-native@0.72.5): + /@react-native/virtualized-lists@0.72.8(react-native@0.72.6): resolution: {integrity: sha512-J3Q4Bkuo99k7mu+jPS9gSUSgq+lLRSI/+ahXNwV92XgJ/8UgOTxu2LPwhJnBk/sQKxq7E8WkZBnBiozukQMqrw==} peerDependencies: react-native: '*' dependencies: invariant: 2.2.4 nullthrows: 1.1.1 - react-native: 0.72.5(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(react@18.2.0) + react-native: 0.72.6(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(react@18.2.0) /@repeaterjs/repeater@3.0.4: resolution: {integrity: sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==} + /@rescript/std@9.0.0: + resolution: {integrity: sha512-zGzFsgtZ44mgL4Xef2gOy1hrRVdrs9mcxCOOKZrIPsmbZW14yTkaF591GXxpQvjXiHtgZ/iA9qLyWH6oSReIxQ==} + dev: true + /@resolver-engine/core@0.3.3: resolution: {integrity: sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ==} dependencies: @@ -11369,7 +10874,7 @@ packages: rollup: optional: true dependencies: - '@types/estree': 1.0.2 + '@types/estree': 1.0.3 estree-walker: 2.0.2 picomatch: 2.3.1 rollup: 2.78.0 @@ -11384,7 +10889,7 @@ packages: rollup: optional: true dependencies: - '@types/estree': 1.0.2 + '@types/estree': 1.0.3 estree-walker: 2.0.2 picomatch: 2.3.1 rollup: 3.29.4 @@ -11399,7 +10904,7 @@ packages: rollup: optional: true dependencies: - '@types/estree': 1.0.2 + '@types/estree': 1.0.3 estree-walker: 2.0.2 picomatch: 2.3.1 rollup: 4.1.4 @@ -11560,14 +11065,14 @@ packages: resolution: {integrity: sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==} dependencies: '@noble/curves': 1.0.0 - '@noble/hashes': 1.3.2 + '@noble/hashes': 1.3.0 '@scure/base': 1.1.3 /@scure/bip32@1.3.1: resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==} dependencies: '@noble/curves': 1.1.0 - '@noble/hashes': 1.3.2 + '@noble/hashes': 1.3.1 '@scure/base': 1.1.3 dev: true @@ -11580,35 +11085,35 @@ packages: /@scure/bip39@1.2.0: resolution: {integrity: sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==} dependencies: - '@noble/hashes': 1.3.2 + '@noble/hashes': 1.3.0 '@scure/base': 1.1.3 /@scure/bip39@1.2.1: resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} dependencies: - '@noble/hashes': 1.3.2 + '@noble/hashes': 1.3.1 '@scure/base': 1.1.3 dev: true - /@sentry-internal/tracing@7.73.0: - resolution: {integrity: sha512-ig3WL/Nqp8nRQ52P205NaypGKNfIl/G+cIqge9xPW6zfRb5kJdM1YParw9GSJ1SPjEZBkBORGAML0on5H2FILw==} + /@sentry-internal/tracing@7.74.1: + resolution: {integrity: sha512-nNaiZreQxCitG2PzYPaC7XtyA9OMsETGYMKAtiK4p62/uTmeYbsBva9BoNx1XeiHRwbrVQYRMKQ9nV5e2jS4/A==} engines: {node: '>=8'} dependencies: - '@sentry/core': 7.73.0 - '@sentry/types': 7.73.0 - '@sentry/utils': 7.73.0 + '@sentry/core': 7.74.1 + '@sentry/types': 7.74.1 + '@sentry/utils': 7.74.1 tslib: 2.6.2 dev: false - /@sentry/browser@7.73.0: - resolution: {integrity: sha512-e301hUixcJ5+HNKCJwajFF5smF4opXEFSclyWsJuFNufv5J/1C1SDhbwG2JjBt5zzdSoKWJKT1ewR6vpICyoDw==} + /@sentry/browser@7.74.1: + resolution: {integrity: sha512-OYWNne/KO60lOvkIpIlJUyiJt/9j8DGI57thSDFEYSmmbNqMitczUTBOaEStouvHKyfchqLZm1CZfWKt+z0VOA==} engines: {node: '>=8'} dependencies: - '@sentry-internal/tracing': 7.73.0 - '@sentry/core': 7.73.0 - '@sentry/replay': 7.73.0 - '@sentry/types': 7.73.0 - '@sentry/utils': 7.73.0 + '@sentry-internal/tracing': 7.74.1 + '@sentry/core': 7.74.1 + '@sentry/replay': 7.74.1 + '@sentry/types': 7.74.1 + '@sentry/utils': 7.74.1 tslib: 2.6.2 dev: false @@ -11655,12 +11160,12 @@ packages: '@sentry/utils': 5.30.0 tslib: 1.14.1 - /@sentry/core@7.73.0: - resolution: {integrity: sha512-9FEz4Gq848LOgVN2OxJGYuQqxv7cIVw69VlAzWHEm3njt8mjvlTq+7UiFsGRo84+59V2FQuHxzA7vVjl90WfSg==} + /@sentry/core@7.74.1: + resolution: {integrity: sha512-LvEhOSfdIvwkr+PdlrT/aA/iOLhkXrSkvjqAQyogE4ddCWeYfS0NoirxNt1EaxMBAWKhYZRqzkA7WA4LDLbzlA==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.73.0 - '@sentry/utils': 7.73.0 + '@sentry/types': 7.74.1 + '@sentry/utils': 7.74.1 tslib: 2.6.2 dev: false @@ -11672,13 +11177,13 @@ packages: '@sentry/utils': 5.30.0 tslib: 1.14.1 - /@sentry/integrations@7.73.0: - resolution: {integrity: sha512-IjVpn4d+aSL9L1Ntu/oAdRwujz4BzzavDsZf96Xgc/AjBnjAEUT+wT1dAwluThfuKDXmWOJHhZ2cHHMfqI+7vw==} + /@sentry/integrations@7.74.1: + resolution: {integrity: sha512-Q7chPehHpHB4WOQ1J/X6NiN2ptiqJMmxtL+6wHumzIAyrjup3c9XekR83qEs8zpqYJAlb/4MUlwd9fPbkhGXnQ==} engines: {node: '>=8'} dependencies: - '@sentry/core': 7.73.0 - '@sentry/types': 7.73.0 - '@sentry/utils': 7.73.0 + '@sentry/core': 7.74.1 + '@sentry/types': 7.74.1 + '@sentry/utils': 7.74.1 localforage: 1.10.0 tslib: 2.6.2 dev: false @@ -11691,8 +11196,8 @@ packages: '@sentry/types': 5.30.0 tslib: 1.14.1 - /@sentry/nextjs@7.73.0(next@13.5.4)(react@18.2.0)(webpack@5.88.2): - resolution: {integrity: sha512-WTTxb3xFFpQ9u8jLx2jXa5oJIlgQs3kQ7wjHoTVOuuk51kB3wtMvq546tA5Kmsgu5uInjznBe4f2qUFYdqiO9Q==} + /@sentry/nextjs@7.74.1(next@13.5.6)(react@18.2.0)(webpack@5.89.0): + resolution: {integrity: sha512-1RySEs3WBEqlpQCAFQ/XwV+oW4wEAtpYglvAyDBwPen/s6KnkkZ0za0l3Ug0O6S9HvMiNll1rPhvnkH5nM37Tg==} engines: {node: '>=8'} peerDependencies: next: ^10.0.8 || ^11.0 || ^12.0 || ^13.0 @@ -11703,21 +11208,22 @@ packages: optional: true dependencies: '@rollup/plugin-commonjs': 24.0.0(rollup@2.78.0) - '@sentry/core': 7.73.0 - '@sentry/integrations': 7.73.0 - '@sentry/node': 7.73.0 - '@sentry/react': 7.73.0(react@18.2.0) - '@sentry/types': 7.73.0 - '@sentry/utils': 7.73.0 - '@sentry/vercel-edge': 7.73.0 + '@sentry/core': 7.74.1 + '@sentry/integrations': 7.74.1 + '@sentry/node': 7.74.1 + '@sentry/react': 7.74.1(react@18.2.0) + '@sentry/types': 7.74.1 + '@sentry/utils': 7.74.1 + '@sentry/vercel-edge': 7.74.1 '@sentry/webpack-plugin': 1.20.0 chalk: 3.0.0 - next: 13.5.4(@babel/core@7.23.2)(react-dom@18.2.0)(react@18.2.0) + next: 13.5.6(@babel/core@7.23.2)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 + resolve: 1.22.8 rollup: 2.78.0 stacktrace-parser: 0.1.10 tslib: 2.6.2 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - encoding - supports-color @@ -11739,14 +11245,14 @@ packages: transitivePeerDependencies: - supports-color - /@sentry/node@7.73.0: - resolution: {integrity: sha512-i50bRfmgkRRx0XXUbg9jGD/RuznDJxJXc4rBILhoJuhl+BjRIaoXA3ayplfJn8JLZxsNh75uJaCq4IUK70SORw==} + /@sentry/node@7.74.1: + resolution: {integrity: sha512-aMUQ2LFZF64FBr+cgjAqjT4OkpYBIC9lyWI8QqjEHqNho5+LGu18/iVrJPD4fgs4UhGdCuAiQjpC36MbmnIDZA==} engines: {node: '>=8'} dependencies: - '@sentry-internal/tracing': 7.73.0 - '@sentry/core': 7.73.0 - '@sentry/types': 7.73.0 - '@sentry/utils': 7.73.0 + '@sentry-internal/tracing': 7.74.1 + '@sentry/core': 7.74.1 + '@sentry/types': 7.74.1 + '@sentry/utils': 7.74.1 cookie: 0.5.0 https-proxy-agent: 5.0.1 lru_map: 0.3.3 @@ -11755,27 +11261,27 @@ packages: - supports-color dev: false - /@sentry/react@7.73.0(react@18.2.0): - resolution: {integrity: sha512-RCGlxW0Xp5vsC38LGxUO0Xf11LBzfg75VN+KS3D2FS5GXl0R0JwgUyPNVlod7YMCfwytsKGhfP+YpQvHGQAVwg==} + /@sentry/react@7.74.1(react@18.2.0): + resolution: {integrity: sha512-16oTsNi2hl/S5AL/e5bo9DQZDwXPkX0nC8ajrpU0z2pH4cwjQZUZt/9Xq1+MKqDIEZkqDcMwpTmBptOvy1Pvkw==} engines: {node: '>=8'} peerDependencies: react: 15.x || 16.x || 17.x || 18.x dependencies: - '@sentry/browser': 7.73.0 - '@sentry/types': 7.73.0 - '@sentry/utils': 7.73.0 + '@sentry/browser': 7.74.1 + '@sentry/types': 7.74.1 + '@sentry/utils': 7.74.1 hoist-non-react-statics: 3.3.2 react: 18.2.0 tslib: 2.6.2 dev: false - /@sentry/replay@7.73.0: - resolution: {integrity: sha512-a8IC9SowBisLYD2IdLkXzx7gN4iVwHDJhQvLp2B8ARs1PyPjJ7gCxSMHeGrYp94V0gOXtorNYkrxvuX8ayPROA==} + /@sentry/replay@7.74.1: + resolution: {integrity: sha512-qmbOl+jYdyhoHFbPp9WemKx8UojID5hVmuVLxNIP0ANqAwmE9OQEK9YFg2cf7L/TpKb1tqz0qLgi5MYIdcdpgQ==} engines: {node: '>=12'} dependencies: - '@sentry/core': 7.73.0 - '@sentry/types': 7.73.0 - '@sentry/utils': 7.73.0 + '@sentry/core': 7.74.1 + '@sentry/types': 7.74.1 + '@sentry/utils': 7.74.1 dev: false /@sentry/tracing@5.30.0: @@ -11792,8 +11298,8 @@ packages: resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} engines: {node: '>=6'} - /@sentry/types@7.73.0: - resolution: {integrity: sha512-/v8++bly8jW7r4cP2wswYiiVpn7eLLcqwnfPUMeCQze4zj3F3nTRIKc9BGHzU0V+fhHa3RwRC2ksqTGq1oJMDg==} + /@sentry/types@7.74.1: + resolution: {integrity: sha512-2jIuPc+YKvXqZETwr2E8VYnsH1zsSUR/wkIvg1uTVeVNyoowJv+YsOtCdeGyL2AwiotUBSPKu7O1Lz0kq5rMOQ==} engines: {node: '>=8'} dev: false @@ -11804,21 +11310,21 @@ packages: '@sentry/types': 5.30.0 tslib: 1.14.1 - /@sentry/utils@7.73.0: - resolution: {integrity: sha512-h3ZK/qpf4k76FhJV9uiSbvMz3V/0Ovy94C+5/9UgPMVCJXFmVsdw8n/dwANJ7LupVPfYP23xFGgebDMFlK1/2w==} + /@sentry/utils@7.74.1: + resolution: {integrity: sha512-qUsqufuHYcy5gFhLZslLxA5kcEOkkODITXW3c7D+x+8iP/AJqa8v8CeUCVNS7RetHCuIeWAbbTClC4c411EwQg==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.73.0 + '@sentry/types': 7.74.1 tslib: 2.6.2 dev: false - /@sentry/vercel-edge@7.73.0: - resolution: {integrity: sha512-5EIJAuHG9w2OBrG76uH51Zlh4SMg3N8n29YiZgOtsBL0FU7AvBpxsIknECmmQOKPFrfCa0ycu2WSWgFXILCYGQ==} + /@sentry/vercel-edge@7.74.1: + resolution: {integrity: sha512-E2lTfEtDFSh57EkjVe4EcgcdjOM8UvfZVsmANBqG4bnwRKrNX9GouClzKU2Ckd5vQnOiCH9r8x2aJ/dTqyBswQ==} engines: {node: '>=8'} dependencies: - '@sentry/core': 7.73.0 - '@sentry/types': 7.73.0 - '@sentry/utils': 7.73.0 + '@sentry/core': 7.74.1 + '@sentry/types': 7.74.1 + '@sentry/utils': 7.74.1 tslib: 2.6.2 dev: false @@ -11894,8 +11400,8 @@ packages: webpack-sources: 3.2.3 dev: false - /@smithy/types@2.3.5: - resolution: {integrity: sha512-ehyDt8M9hehyxrLQGoA1BGPou8Js1Ocoh5M0ngDhJMqbFmNK5N6Xhr9/ZExWkyIW8XcGkiMPq3ZUEE0ScrhbuQ==} + /@smithy/types@2.4.0: + resolution: {integrity: sha512-iH1Xz68FWlmBJ9vvYeHifVMWJf82ONx+OybPW8ZGf5wnEv2S0UXcU4zwlwJkRXuLKpcSLHrraHbn2ucdVXLb4g==} engines: {node: '>=14.0.0'} dependencies: tslib: 2.6.2 @@ -11911,10 +11417,10 @@ packages: buffer: 6.0.3 dev: false - /@solana/web3.js@1.87.1: - resolution: {integrity: sha512-E8Y9bNlZ8TQlhOvCx1b7jG+TjA4SJLVwufmIk1+tcQctUhK5HiB1Q8ljd4yQDkFlk6OOeAlAeqvW0YntWJU94Q==} + /@solana/web3.js@1.87.2: + resolution: {integrity: sha512-TZNhS+tvJbYjm0LAvIkUy/3Aqgt2l6/3X6XsVUpvj5MGOl2Q6Ch8hYSxcUUtMbAFNN3sUXmV8NhhMLNJEvI6TA==} dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@noble/curves': 1.2.0 '@noble/hashes': 1.3.2 '@solana/buffer-layout': 4.0.1 @@ -11927,7 +11433,7 @@ packages: fast-stable-stringify: 1.0.0 jayson: 4.1.0 node-fetch: 2.7.0 - rpc-websockets: 7.6.0 + rpc-websockets: 7.6.1 superstruct: 0.14.2 transitivePeerDependencies: - bufferutil @@ -12069,8 +11575,8 @@ packages: '@supabase/node-fetch': 2.6.14 dev: false - /@supabase/gotrue-js@2.55.0: - resolution: {integrity: sha512-wZAP66Lo68iROKo33m8seY30rCeGiR34leMEZ80j9fPm+/ar6h3y43Hb7f9F2STVMwT3Sv+aM+w0yCon5bih4g==} + /@supabase/gotrue-js@2.57.0: + resolution: {integrity: sha512-/CcAW40aPKgp9/w9WgXVUQFg1AOdvFR687ONOMjASPBuC6FsNbKlcXp4pc+rwKNtxyxDkBbR+x7zj/8g00r/Og==} dependencies: '@supabase/node-fetch': 2.6.14 dev: false @@ -12082,18 +11588,18 @@ packages: whatwg-url: 5.0.0 dev: false - /@supabase/postgrest-js@1.8.4: - resolution: {integrity: sha512-ELjpvhb04wILUiJz9zIsTSwaz9LQNlX+Ig5/LgXQ7k68qQI6NqHVn+ISRNt53DngUIyOnLHjeqqIRHBZ7zpgGA==} + /@supabase/postgrest-js@1.8.5: + resolution: {integrity: sha512-XvoqN5e5Z4TsQOYWLQYLW0HIlZtFSzwAcwiuToaSBSTpLOGCg4NaZ7au5GfBzCQJZdZPY5vk5FvwthfDsQK/Jw==} dependencies: '@supabase/node-fetch': 2.6.14 dev: false - /@supabase/realtime-js@2.8.0: - resolution: {integrity: sha512-j1OP2nRJhqLNEoYSMkIl1+cHK/Ow9fektemazkF2CvrIrmwgfJJGaFGiWGVgwoKtwVcrdknSsYWpxs90hys1EQ==} + /@supabase/realtime-js@2.8.1: + resolution: {integrity: sha512-bka5U4OeoKMdorGMPjdF30cl8n8nbhn+I9H4iySKzbN45W6AGxi7xoODnxdq/QwaDGtVyTMVbU+GVWre0QCdtw==} dependencies: '@supabase/node-fetch': 2.6.14 - '@types/phoenix': 1.6.2 - '@types/websocket': 1.0.7 + '@types/phoenix': 1.6.3 + '@types/websocket': 1.0.8 websocket: 1.0.34 transitivePeerDependencies: - supports-color @@ -12105,114 +11611,114 @@ packages: '@supabase/node-fetch': 2.6.14 dev: false - /@supabase/supabase-js@2.38.0: - resolution: {integrity: sha512-FSkIcz+/+TTBqNqhR8AdtblxEqCF72//CCkmZFIRCa3Xh/aiI0F4cBdL7AB3aIQn2DhE4aGxZ4mGiGR593096Q==} + /@supabase/supabase-js@2.38.2: + resolution: {integrity: sha512-yOCi94oO5WVUBhQ890BvtT7J3p8spP47PMhn22YldIcDLEQWE6N6X2JzfWCLHktXw+oCYUJfQBuqYhyLHAKb0w==} dependencies: '@supabase/functions-js': 2.1.5 - '@supabase/gotrue-js': 2.55.0 + '@supabase/gotrue-js': 2.57.0 '@supabase/node-fetch': 2.6.14 - '@supabase/postgrest-js': 1.8.4 - '@supabase/realtime-js': 2.8.0 + '@supabase/postgrest-js': 1.8.5 + '@supabase/realtime-js': 2.8.1 '@supabase/storage-js': 2.5.4 transitivePeerDependencies: - supports-color dev: false - /@svgr/babel-plugin-add-jsx-attribute@6.5.1(@babel/core@7.23.0): + /@svgr/babel-plugin-add-jsx-attribute@6.5.1(@babel/core@7.23.2): resolution: {integrity: sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==} engines: {node: '>=10'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 dev: false - /@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.23.0): + /@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.23.2): resolution: {integrity: sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==} engines: {node: '>=14'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 dev: false - /@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.23.0): + /@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.23.2): resolution: {integrity: sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==} engines: {node: '>=14'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 dev: false - /@svgr/babel-plugin-replace-jsx-attribute-value@6.5.1(@babel/core@7.23.0): + /@svgr/babel-plugin-replace-jsx-attribute-value@6.5.1(@babel/core@7.23.2): resolution: {integrity: sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==} engines: {node: '>=10'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 dev: false - /@svgr/babel-plugin-svg-dynamic-title@6.5.1(@babel/core@7.23.0): + /@svgr/babel-plugin-svg-dynamic-title@6.5.1(@babel/core@7.23.2): resolution: {integrity: sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==} engines: {node: '>=10'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 dev: false - /@svgr/babel-plugin-svg-em-dimensions@6.5.1(@babel/core@7.23.0): + /@svgr/babel-plugin-svg-em-dimensions@6.5.1(@babel/core@7.23.2): resolution: {integrity: sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==} engines: {node: '>=10'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 dev: false - /@svgr/babel-plugin-transform-react-native-svg@6.5.1(@babel/core@7.23.0): + /@svgr/babel-plugin-transform-react-native-svg@6.5.1(@babel/core@7.23.2): resolution: {integrity: sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==} engines: {node: '>=10'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 dev: false - /@svgr/babel-plugin-transform-svg-component@6.5.1(@babel/core@7.23.0): + /@svgr/babel-plugin-transform-svg-component@6.5.1(@babel/core@7.23.2): resolution: {integrity: sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==} engines: {node: '>=12'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 dev: false - /@svgr/babel-preset@6.5.1(@babel/core@7.23.0): + /@svgr/babel-preset@6.5.1(@babel/core@7.23.2): resolution: {integrity: sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==} engines: {node: '>=10'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.23.0 - '@svgr/babel-plugin-add-jsx-attribute': 6.5.1(@babel/core@7.23.0) - '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.23.0) - '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.23.0) - '@svgr/babel-plugin-replace-jsx-attribute-value': 6.5.1(@babel/core@7.23.0) - '@svgr/babel-plugin-svg-dynamic-title': 6.5.1(@babel/core@7.23.0) - '@svgr/babel-plugin-svg-em-dimensions': 6.5.1(@babel/core@7.23.0) - '@svgr/babel-plugin-transform-react-native-svg': 6.5.1(@babel/core@7.23.0) - '@svgr/babel-plugin-transform-svg-component': 6.5.1(@babel/core@7.23.0) + '@babel/core': 7.23.2 + '@svgr/babel-plugin-add-jsx-attribute': 6.5.1(@babel/core@7.23.2) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.23.2) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.23.2) + '@svgr/babel-plugin-replace-jsx-attribute-value': 6.5.1(@babel/core@7.23.2) + '@svgr/babel-plugin-svg-dynamic-title': 6.5.1(@babel/core@7.23.2) + '@svgr/babel-plugin-svg-em-dimensions': 6.5.1(@babel/core@7.23.2) + '@svgr/babel-plugin-transform-react-native-svg': 6.5.1(@babel/core@7.23.2) + '@svgr/babel-plugin-transform-svg-component': 6.5.1(@babel/core@7.23.2) dev: false /@svgr/core@6.5.1: resolution: {integrity: sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==} engines: {node: '>=10'} dependencies: - '@babel/core': 7.23.0 - '@svgr/babel-preset': 6.5.1(@babel/core@7.23.0) + '@babel/core': 7.23.2 + '@svgr/babel-preset': 6.5.1(@babel/core@7.23.2) '@svgr/plugin-jsx': 6.5.1(@svgr/core@6.5.1) camelcase: 6.3.0 cosmiconfig: 7.1.0 @@ -12234,8 +11740,8 @@ packages: peerDependencies: '@svgr/core': ^6.0.0 dependencies: - '@babel/core': 7.23.0 - '@svgr/babel-preset': 6.5.1(@babel/core@7.23.0) + '@babel/core': 7.23.2 + '@svgr/babel-preset': 6.5.1(@babel/core@7.23.2) '@svgr/core': 6.5.1 '@svgr/hast-util-to-babel-ast': 6.5.1 svg-parser: 2.0.4 @@ -12259,11 +11765,11 @@ packages: resolution: {integrity: sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA==} engines: {node: '>=10'} dependencies: - '@babel/core': 7.23.0 - '@babel/plugin-transform-react-constant-elements': 7.22.5(@babel/core@7.23.0) - '@babel/preset-env': 7.22.20(@babel/core@7.23.0) - '@babel/preset-react': 7.22.15(@babel/core@7.23.0) - '@babel/preset-typescript': 7.23.0(@babel/core@7.23.0) + '@babel/core': 7.23.2 + '@babel/plugin-transform-react-constant-elements': 7.22.5(@babel/core@7.23.2) + '@babel/preset-env': 7.23.2(@babel/core@7.23.2) + '@babel/preset-react': 7.22.15(@babel/core@7.23.2) + '@babel/preset-typescript': 7.23.2(@babel/core@7.23.2) '@svgr/core': 6.5.1 '@svgr/plugin-jsx': 6.5.1(@svgr/core@6.5.1) '@svgr/plugin-svgo': 6.5.1(@svgr/core@6.5.1) @@ -12277,19 +11783,19 @@ packages: tslib: 2.6.2 dev: false - /@synthetixio/synpress@3.7.1(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.6)(webpack@5.88.2): + /@synthetixio/synpress@3.7.1(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.6)(webpack@5.89.0): resolution: {integrity: sha512-fU2+niaDgDvR/7NJwTvMA5WPbAt4fu8c4EMhQH1Lgk8OKSmaovL9xXgOscd90KZyHu6FbW8DNnocJKyiZmELEA==} engines: {node: '>=14'} hasBin: true dependencies: - '@cypress/code-coverage': 3.12.1(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(cypress@12.17.4)(webpack@5.88.2) - '@cypress/webpack-dev-server': 3.6.1(debug@4.3.4)(webpack@5.88.2) + '@cypress/code-coverage': 3.12.5(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(cypress@12.17.4)(webpack@5.89.0) + '@cypress/webpack-dev-server': 3.6.1(debug@4.3.4)(webpack@5.89.0) '@drptbl/gremlins.js': 2.2.1 '@foundry-rs/easy-foundryup': 0.1.3 - '@playwright/test': 1.38.1 + '@playwright/test': 1.39.0 '@testing-library/cypress': 9.0.0(cypress@12.17.4) '@testing-library/react': 14.0.0(react-dom@18.2.0)(react@18.2.0) - '@types/testing-library__cypress': 5.0.11 + '@types/testing-library__cypress': 5.0.12 '@viem/anvil': 0.0.5(debug@4.3.4) app-root-path: 3.1.0 axios: 1.5.1(debug@4.3.4) @@ -12368,7 +11874,7 @@ packages: react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: '@tanstack/match-sorter-utils': 8.8.4 - '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react-native@0.72.5)(react@18.2.0) + '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) superjson: 1.13.3 @@ -12381,10 +11887,10 @@ packages: '@tanstack/react-query': ^4.36.1 dependencies: '@tanstack/query-persist-client-core': 4.36.1 - '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react-native@0.72.5)(react@18.2.0) + '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0) dev: false - /@tanstack/react-query@4.36.1(react-dom@18.2.0)(react-native@0.72.5)(react@18.2.0): + /@tanstack/react-query@4.36.1(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0): resolution: {integrity: sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -12399,7 +11905,7 @@ packages: '@tanstack/query-core': 4.36.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-native: 0.72.5(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(react@18.2.0) + react-native: 0.72.6(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(react@18.2.0) use-sync-external-store: 1.2.0(react@18.2.0) dev: false @@ -12409,7 +11915,7 @@ packages: peerDependencies: cypress: ^12.0.0 dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@testing-library/dom': 8.20.1 cypress: 12.17.4 dev: true @@ -12419,7 +11925,7 @@ packages: engines: {node: '>=10'} dependencies: '@babel/code-frame': 7.22.13 - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@types/aria-query': 4.2.2 aria-query: 4.2.2 chalk: 4.1.2 @@ -12433,8 +11939,8 @@ packages: engines: {node: '>=12'} dependencies: '@babel/code-frame': 7.22.13 - '@babel/runtime': 7.23.1 - '@types/aria-query': 5.0.2 + '@babel/runtime': 7.23.2 + '@types/aria-query': 5.0.3 aria-query: 5.1.3 chalk: 4.1.2 dom-accessibility-api: 0.5.16 @@ -12447,8 +11953,8 @@ packages: engines: {node: '>=14'} dependencies: '@babel/code-frame': 7.22.13 - '@babel/runtime': 7.23.1 - '@types/aria-query': 5.0.2 + '@babel/runtime': 7.23.2 + '@types/aria-query': 5.0.3 aria-query: 5.1.3 chalk: 4.1.2 dom-accessibility-api: 0.5.16 @@ -12461,9 +11967,9 @@ packages: engines: {node: '>=8', npm: '>=6', yarn: '>=1'} dependencies: '@adobe/css-tools': 4.3.1 - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@types/testing-library__jest-dom': 5.14.9 - aria-query: 5.1.3 + aria-query: 5.3.0 chalk: 3.0.0 css.escape: 1.5.1 dom-accessibility-api: 0.5.16 @@ -12478,9 +11984,9 @@ packages: react: ^18.0.0 react-dom: ^18.0.0 dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 '@testing-library/dom': 9.3.3 - '@types/react-dom': 18.2.13 + '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true @@ -12509,7 +12015,7 @@ packages: '@babel/parser': 7.18.9 '@babel/traverse': 7.17.3 '@babel/types': 7.17.0 - '@vue/compiler-sfc': 3.3.4 + '@vue/compiler-sfc': 3.3.6 javascript-natural-sort: 0.7.1 lodash: 4.17.21 prettier: 2.8.8 @@ -12555,7 +12061,7 @@ packages: /@tsconfig/node16@1.0.4: resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - /@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@4.9.5): + /@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5): resolution: {integrity: sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==} peerDependencies: '@ethersproject/abi': ^5.0.0 @@ -12569,10 +12075,10 @@ packages: ethers: 5.7.2 lodash: 4.17.21 ts-essentials: 7.0.3(typescript@4.9.5) - typechain: 8.3.1(typescript@4.9.5) + typechain: 8.3.2(typescript@4.9.5) typescript: 4.9.5 - /@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@5.1.6): + /@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.1.6): resolution: {integrity: sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==} peerDependencies: '@ethersproject/abi': ^5.0.0 @@ -12586,11 +12092,11 @@ packages: ethers: 5.7.2 lodash: 4.17.21 ts-essentials: 7.0.3(typescript@5.1.6) - typechain: 8.3.1(typescript@5.1.6) + typechain: 8.3.2(typescript@5.1.6) typescript: 5.1.6 dev: false - /@typechain/ethers-v5@11.1.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@4.9.5): + /@typechain/ethers-v5@11.1.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5): resolution: {integrity: sha512-ID6pqWkao54EuUQa0P5RgjvfA3MYqxUQKpbGKERbsjBW5Ra7EIXvbMlPp2pcP5IAdUkyMCFYsP2SN5q7mPdLDQ==} peerDependencies: '@ethersproject/abi': ^5.0.0 @@ -12604,11 +12110,11 @@ packages: ethers: 5.7.2 lodash: 4.17.21 ts-essentials: 7.0.3(typescript@4.9.5) - typechain: 8.3.1(typescript@4.9.5) + typechain: 8.3.2(typescript@4.9.5) typescript: 4.9.5 dev: true - /@typechain/ethers-v6@0.5.1(ethers@5.7.2)(typechain@8.3.1)(typescript@4.9.5): + /@typechain/ethers-v6@0.5.1(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5): resolution: {integrity: sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==} peerDependencies: ethers: ^5.7.2 @@ -12618,11 +12124,11 @@ packages: ethers: 5.7.2 lodash: 4.17.21 ts-essentials: 7.0.3(typescript@4.9.5) - typechain: 8.3.1(typescript@4.9.5) + typechain: 8.3.2(typescript@4.9.5) typescript: 4.9.5 dev: true - /@typechain/hardhat@6.1.6(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@10.2.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.1): + /@typechain/hardhat@6.1.6(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@10.2.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2): resolution: {integrity: sha512-BiVnegSs+ZHVymyidtK472syodx1sXYlYJJixZfRstHVGYTi8V1O7QG4nsjyb0PC/LORcq7sfBUcHto1y6UgJA==} peerDependencies: '@ethersproject/abi': ^5.4.7 @@ -12634,14 +12140,14 @@ packages: dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/providers': 5.7.2 - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@4.9.5) + '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) ethers: 5.7.2 fs-extra: 9.1.0 hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) - typechain: 8.3.1(typescript@4.9.5) + typechain: 8.3.2(typescript@4.9.5) dev: false - /@typechain/hardhat@9.1.0(@typechain/ethers-v6@0.5.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.1): + /@typechain/hardhat@9.1.0(@typechain/ethers-v6@0.5.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2): resolution: {integrity: sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==} peerDependencies: '@typechain/ethers-v6': ^0.5.1 @@ -12649,187 +12155,193 @@ packages: hardhat: ^2.9.9 typechain: ^8.3.2 dependencies: - '@typechain/ethers-v6': 0.5.1(ethers@5.7.2)(typechain@8.3.1)(typescript@4.9.5) + '@typechain/ethers-v6': 0.5.1(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) ethers: 5.7.2 fs-extra: 9.1.0 hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) - typechain: 8.3.1(typescript@4.9.5) + typechain: 8.3.2(typescript@4.9.5) dev: true - /@types/abstract-leveldown@7.2.3: - resolution: {integrity: sha512-YAdL8tIYbiKoFjAf/0Ir3mvRJ/iFvBP/FK0I8Xa5rGWgVcq0xWOEInzlJfs6TIPWFweEOTKgNSBdxneUcHRvaw==} + /@types/abstract-leveldown@7.2.4: + resolution: {integrity: sha512-ygy0hYyHdKnAtvCGUFEFvr3YV7Y6Q4akyRkZpM3RSUMYGSr35ZGRCT9Div+la4DpRUiwYUhJ6l75JBz6EORmpg==} dev: true /@types/aria-query@4.2.2: resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==} dev: true - /@types/aria-query@5.0.2: - resolution: {integrity: sha512-PHKZuMN+K5qgKIWhBodXzQslTo5P+K/6LqeKXS6O/4liIDdZqaX5RXrCK++LAw+y/nptN48YmUMFiQHRSWYwtQ==} + /@types/aria-query@5.0.3: + resolution: {integrity: sha512-0Z6Tr7wjKJIk4OUEjVUQMtyunLDy339vcMaj38Kpj6jM2OE1p3S4kXExKZ7a3uXQAPCoy3sbrP1wibDKaf39oA==} dev: true - /@types/babel__core@7.20.2: - resolution: {integrity: sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==} + /@types/babel__core@7.20.3: + resolution: {integrity: sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==} dependencies: '@babel/parser': 7.23.0 '@babel/types': 7.23.0 - '@types/babel__generator': 7.6.5 - '@types/babel__template': 7.4.2 - '@types/babel__traverse': 7.20.2 + '@types/babel__generator': 7.6.6 + '@types/babel__template': 7.4.3 + '@types/babel__traverse': 7.20.3 - /@types/babel__generator@7.6.5: - resolution: {integrity: sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==} + /@types/babel__generator@7.6.6: + resolution: {integrity: sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==} dependencies: '@babel/types': 7.23.0 - /@types/babel__template@7.4.2: - resolution: {integrity: sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==} + /@types/babel__template@7.4.3: + resolution: {integrity: sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==} dependencies: '@babel/parser': 7.23.0 '@babel/types': 7.23.0 - /@types/babel__traverse@7.20.2: - resolution: {integrity: sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==} + /@types/babel__traverse@7.20.3: + resolution: {integrity: sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==} dependencies: '@babel/types': 7.23.0 - /@types/better-sqlite3@7.6.5: - resolution: {integrity: sha512-H3ZUx89KiPhYa9nalUXVVStSUFHuzYxt4yoazufpTTYW9rVUCzhh02V8CH2C8nE4libnK0UgFq5DFIe0DOhqow==} + /@types/better-sqlite3@7.6.6: + resolution: {integrity: sha512-nuFAptzt0hZYBvyLzKQCbuCCK+RN9PHH4ezar5EJLIg2qpVhwQ/uLvLO/K8A9O7N8DafawgFupiyXQSs0U48Ng==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 dev: true /@types/bn.js@4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 - /@types/bn.js@5.1.2: - resolution: {integrity: sha512-dkpZu0szUtn9UXTmw+e0AJFd4D2XAxDnsCLdc05SfqpqzPEBft8eQr8uaFitfo/dUUOZERaLec2hHMG87A4Dxg==} + /@types/bn.js@5.1.3: + resolution: {integrity: sha512-wT1B4iIO82ecXkdN6waCK8Ou7E71WU+mP1osDA5Q8c6Ur+ozU2vIKUIhSpUr6uE5L2YHocKS1Z2jG2fBC1YVeg==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 - /@types/body-parser@1.19.3: - resolution: {integrity: sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==} + /@types/body-parser@1.19.4: + resolution: {integrity: sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==} dependencies: - '@types/connect': 3.4.36 - '@types/node': 18.15.13 + '@types/connect': 3.4.37 + '@types/node': 18.18.6 - /@types/bonjour@3.5.11: - resolution: {integrity: sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg==} + /@types/bonjour@3.5.12: + resolution: {integrity: sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 - /@types/chai-as-promised@7.1.6: - resolution: {integrity: sha512-cQLhk8fFarRVZAXUQV1xEnZgMoPxqKojBvRkqPCKPQCzEhpbbSKl1Uu75kDng7k5Ln6LQLUmNBjLlFthCgm1NA==} + /@types/chai-as-promised@7.1.7: + resolution: {integrity: sha512-APucaP5rlmTRYKtRA6FE5QPP87x76ejw5t5guRJ4y5OgMnwtsvigw7HHhKZlx2MGXLeZd6R/GNZR/IqDHcbtQw==} dependencies: - '@types/chai': 4.3.7 + '@types/chai': 4.3.9 dev: true - /@types/chai-subset@1.3.3: - resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} + /@types/chai-subset@1.3.4: + resolution: {integrity: sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==} dependencies: - '@types/chai': 4.3.7 + '@types/chai': 4.3.9 + dev: true + + /@types/chai@4.3.9: + resolution: {integrity: sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==} dev: true - /@types/chai@4.3.7: - resolution: {integrity: sha512-/k+vesl92vMvMygmQrFe9Aimxi6oQXFUX9mA5HanTrKUSAMoLauSi6PNFOdRw0oeqilaW600GNx2vSaT2f8aIQ==} + /@types/cli-progress@3.11.4: + resolution: {integrity: sha512-yufTxeeNCZuEIxx2uebK8lpSAsJM4lvzakm/VxzYhDtqhXCzwH9jpn7nPCxzrROuEbLATqhFq4MIPoG0tlrsvw==} + dependencies: + '@types/node': 18.18.6 dev: true /@types/concat-stream@1.6.1: resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 dev: true - /@types/connect-history-api-fallback@1.5.1: - resolution: {integrity: sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==} + /@types/connect-history-api-fallback@1.5.2: + resolution: {integrity: sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==} dependencies: - '@types/express-serve-static-core': 4.17.37 - '@types/node': 18.15.13 + '@types/express-serve-static-core': 4.17.39 + '@types/node': 18.18.6 - /@types/connect@3.4.36: - resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} + /@types/connect@3.4.37: + resolution: {integrity: sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 /@types/cookie@0.4.1: resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} dev: true - /@types/debug@4.1.9: - resolution: {integrity: sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==} + /@types/debug@4.1.10: + resolution: {integrity: sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==} dependencies: - '@types/ms': 0.7.32 + '@types/ms': 0.7.33 - /@types/dns-packet@5.6.1: - resolution: {integrity: sha512-F8X3srlDYXQSVGfjAWl0lxd9mGfYtkneMA0QFQ3BFBw/BUmBlhlAbpRjmvE7LbW3wIxf01KHi20/bPstYK6ssA==} + /@types/dns-packet@5.6.2: + resolution: {integrity: sha512-vgUZ0ilYvpnTDx7tBmmAUn1HsyzK3huAtulHaDbBBCW5UdaDrEei5XJjWHnD4s8r9/MSL1hJ8s+nvJdcvNKgMA==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 dev: false - /@types/eslint-scope@3.7.5: - resolution: {integrity: sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==} + /@types/eslint-scope@3.7.6: + resolution: {integrity: sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==} dependencies: - '@types/eslint': 8.44.4 - '@types/estree': 1.0.2 + '@types/eslint': 8.44.6 + '@types/estree': 1.0.3 - /@types/eslint@8.44.4: - resolution: {integrity: sha512-lOzjyfY/D9QR4hY9oblZ76B90MYTB3RrQ4z2vBIJKj9ROCRqdkYl2gSUx1x1a4IWPjKJZLL4Aw1Zfay7eMnmnA==} + /@types/eslint@8.44.6: + resolution: {integrity: sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==} dependencies: - '@types/estree': 1.0.2 - '@types/json-schema': 7.0.13 + '@types/estree': 1.0.3 + '@types/json-schema': 7.0.14 - /@types/estree@1.0.2: - resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==} + /@types/estree@1.0.3: + resolution: {integrity: sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==} - /@types/express-serve-static-core@4.17.37: - resolution: {integrity: sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==} + /@types/express-serve-static-core@4.17.39: + resolution: {integrity: sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==} dependencies: - '@types/node': 18.15.13 - '@types/qs': 6.9.8 - '@types/range-parser': 1.2.5 - '@types/send': 0.17.2 + '@types/node': 18.18.6 + '@types/qs': 6.9.9 + '@types/range-parser': 1.2.6 + '@types/send': 0.17.3 - /@types/express@4.17.19: - resolution: {integrity: sha512-UtOfBtzN9OvpZPPbnnYunfjM7XCI4jyk1NvnFhTVz5krYAnW4o5DCoIekvms+8ApqhB4+9wSge1kBijdfTSmfg==} + /@types/express@4.17.20: + resolution: {integrity: sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==} dependencies: - '@types/body-parser': 1.19.3 - '@types/express-serve-static-core': 4.17.37 - '@types/qs': 6.9.8 - '@types/serve-static': 1.15.3 + '@types/body-parser': 1.19.4 + '@types/express-serve-static-core': 4.17.39 + '@types/qs': 6.9.9 + '@types/serve-static': 1.15.4 /@types/form-data@0.0.33: resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 dev: true /@types/glob@7.2.0: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: - '@types/minimatch': 3.0.5 - '@types/node': 18.15.13 + '@types/minimatch': 5.1.2 + '@types/node': 18.18.6 dev: true - /@types/graceful-fs@4.1.7: - resolution: {integrity: sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==} + /@types/graceful-fs@4.1.8: + resolution: {integrity: sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 - /@types/hast@2.3.6: - resolution: {integrity: sha512-47rJE80oqPmFdVDCD7IheXBrVdwuBgsYwoczFvKmwfo2Mzsnt+V9OONsYauFmICb6lQPpCuXYJWejBNs4pDJRg==} + /@types/hast@2.3.7: + resolution: {integrity: sha512-EVLigw5zInURhzfXUM65eixfadfsHKomGKUakToXo84t8gGIJuTcD2xooM2See7GyQ7DRtYjhCHnSUQez8JaLw==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 dev: false /@types/history@4.7.11: resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==} - /@types/hoist-non-react-statics@3.3.3: - resolution: {integrity: sha512-Wny3a2UXn5FEA1l7gc6BbpoV5mD1XijZqgkp4TRgDCDL5r3B5ieOFGUX5h3n78Tr1MEG7BfvoM8qeztdvNU0fw==} + /@types/hoist-non-react-statics@3.3.4: + resolution: {integrity: sha512-ZchYkbieA+7tnxwX/SCBySx9WwvWR8TaP5tb2jRAzwvLb/rWchGw3v0w3pqUbUvj0GCwW2Xz/AVPSk6kUGctXQ==} dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 hoist-non-react-statics: 3.3.2 dev: false @@ -12840,29 +12352,29 @@ packages: /@types/html-minifier-terser@6.1.0: resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} - /@types/http-errors@2.0.2: - resolution: {integrity: sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==} + /@types/http-errors@2.0.3: + resolution: {integrity: sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==} - /@types/http-proxy@1.17.12: - resolution: {integrity: sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw==} + /@types/http-proxy@1.17.13: + resolution: {integrity: sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 - /@types/istanbul-lib-coverage@2.0.4: - resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + /@types/istanbul-lib-coverage@2.0.5: + resolution: {integrity: sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==} - /@types/istanbul-lib-report@3.0.1: - resolution: {integrity: sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==} + /@types/istanbul-lib-report@3.0.2: + resolution: {integrity: sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==} dependencies: - '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-lib-coverage': 2.0.5 - /@types/istanbul-reports@3.0.2: - resolution: {integrity: sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==} + /@types/istanbul-reports@3.0.3: + resolution: {integrity: sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==} dependencies: - '@types/istanbul-lib-report': 3.0.1 + '@types/istanbul-lib-report': 3.0.2 - /@types/jest@29.5.5: - resolution: {integrity: sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==} + /@types/jest@29.5.6: + resolution: {integrity: sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==} dependencies: expect: 29.7.0 pretty-format: 29.7.0 @@ -12872,20 +12384,20 @@ packages: resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} dev: false - /@types/js-levenshtein@1.1.1: - resolution: {integrity: sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==} + /@types/js-levenshtein@1.1.2: + resolution: {integrity: sha512-/NCbMABw2uacuyE16Iwka1EzREDD50/W2ggRBad0y1WHBvAkvR9OEINxModVY7D428gXBe0igeVX7bUc9GaslQ==} dev: true /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: - '@types/node': 18.15.13 - '@types/tough-cookie': 4.0.3 + '@types/node': 18.18.6 + '@types/tough-cookie': 4.0.4 parse5: 7.1.2 dev: true - /@types/json-schema@7.0.13: - resolution: {integrity: sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==} + /@types/json-schema@7.0.14: + resolution: {integrity: sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==} /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} @@ -12895,72 +12407,75 @@ packages: /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 - /@types/level-errors@3.0.0: - resolution: {integrity: sha512-/lMtoq/Cf/2DVOm6zE6ORyOM+3ZVm/BvzEZVxUhf6bgh8ZHglXlBqxbxSlJeVp8FCbD3IVvk/VbsaNmDjrQvqQ==} + /@types/level-errors@3.0.1: + resolution: {integrity: sha512-eFJZWaOUhgjSqgEsPKJZrqXS9aEDUQh/5F9saFhhkR5uEVKlYb4GSG8XyoVC7APklcQKPGDVenTointTZBGIQg==} dev: true /@types/levelup@4.3.3: resolution: {integrity: sha512-K+OTIjJcZHVlZQN1HmU64VtrC0jC3dXWQozuEIR9zVvltIk90zaGPM2AgT+fIkChpzHhFE3YnvFLCbLtzAmexA==} dependencies: - '@types/abstract-leveldown': 7.2.3 - '@types/level-errors': 3.0.0 - '@types/node': 18.15.13 + '@types/abstract-leveldown': 7.2.4 + '@types/level-errors': 3.0.1 + '@types/node': 18.18.6 dev: true - /@types/lodash@4.14.199: - resolution: {integrity: sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==} + /@types/lodash@4.14.200: + resolution: {integrity: sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==} /@types/long@4.0.2: resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} - dev: false /@types/lru-cache@5.1.1: resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} - /@types/mdast@3.0.13: - resolution: {integrity: sha512-HjiGiWedR0DVFkeNljpa6Lv4/IZU1+30VY5d747K7lBudFc3R0Ibr6yJ9lN3BE28VnZyDfLF/VB1Ql1ZIbKrmg==} + /@types/mdast@3.0.14: + resolution: {integrity: sha512-gVZ04PGgw1qLZKsnWnyFv4ORnaJ+DXLdHTVSFbU8yX6xZ34Bjg4Q32yPkmveUP1yItXReKfB0Aknlh/3zxTKAw==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 dev: false - /@types/mime@1.3.3: - resolution: {integrity: sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==} + /@types/mime@1.3.4: + resolution: {integrity: sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==} - /@types/mime@3.0.2: - resolution: {integrity: sha512-Wj+fqpTLtTbG7c0tH47dkahefpLKEbB+xAZuLq7b4/IDHPl/n6VoXcyUQ2bypFlbSwvCr0y+bD4euTTqTJsPxQ==} + /@types/mime@3.0.3: + resolution: {integrity: sha512-i8MBln35l856k5iOhKk2XJ4SeAWg75mLIpZB4v6imOagKL6twsukBZGDMNhdOVk7yRFTMPpfILocMos59Q1otQ==} /@types/minimatch@3.0.5: resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} - /@types/minimist@1.2.3: - resolution: {integrity: sha512-ZYFzrvyWUNhaPomn80dsMNgMeXxNWZBdkuG/hWlUvXvbdUH8ZERNBGXnU87McuGcWDsyzX2aChCv/SVN348k3A==} + /@types/minimatch@5.1.2: + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + dev: true + + /@types/minimist@1.2.4: + resolution: {integrity: sha512-Kfe/D3hxHTusnPNRbycJE1N77WHDsdS4AjUYIzlDzhDrS47NrwuL3YW4VITxwR7KCVpzwgy4Rbj829KSSQmwXQ==} /@types/mkdirp@0.5.2: resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 dev: true /@types/mocha@9.1.0: resolution: {integrity: sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg==} dev: true - /@types/ms@0.7.32: - resolution: {integrity: sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==} + /@types/ms@0.7.33: + resolution: {integrity: sha512-AuHIyzR5Hea7ij0P9q7vx7xu4z0C28ucwjAZC0ja7JhINyCnOw8/DnvAPQQ9TfOlCtZAmCERKQX9+o1mgQhuOQ==} - /@types/multicast-dns@7.2.2: - resolution: {integrity: sha512-re0wpYJU2SdKkBbmCh7f5zYMLFA/FCbX46DI0rRMLlkkDqhk+0bTHbYsUVZumk/43GfJehPImK9e202eSuxPKA==} + /@types/multicast-dns@7.2.3: + resolution: {integrity: sha512-2SZ079yRhuhDn5BssqkQGp07vErjm3PD8S/JAlduWXacZ8SVHF0q6R2m0PwjjgTDU1vE3kibNPlmnr1iKbP/Sw==} dependencies: - '@types/dns-packet': 5.6.1 - '@types/node': 18.15.13 + '@types/dns-packet': 5.6.2 + '@types/node': 18.18.6 dev: false - /@types/node-fetch@2.6.6: - resolution: {integrity: sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==} + /@types/node-fetch@2.6.7: + resolution: {integrity: sha512-lX17GZVpJ/fuCjguZ5b3TjEbSENxmEk1B2z02yoXSK9WMEWRivhdSY73wWMn6bpcCDAOh6qAdktpKHIlkDk2lg==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 form-data: 4.0.0 dev: true @@ -12974,119 +12489,116 @@ packages: /@types/node@12.20.55: resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - dev: false - /@types/node@16.18.58: - resolution: {integrity: sha512-YGncyA25/MaVtQkjWW9r0EFBukZ+JulsLcVZBlGUfIb96OBMjkoRWwQo5IEWJ8Fj06Go3GHw+bjYDitv6BaGsA==} + /@types/node@16.18.59: + resolution: {integrity: sha512-PJ1w2cNeKUEdey4LiPra0ZuxZFOGvetswE8qHRriV/sUkL5Al4tTmPV9D2+Y/TPIxTHHgxTfRjZVKWhPw/ORhQ==} dev: true /@types/node@17.0.45: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} dev: false - /@types/node@18.15.13: - resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} + /@types/node@18.18.6: + resolution: {integrity: sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==} /@types/node@20.5.1: resolution: {integrity: sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==} - requiresBuild: true dev: true /@types/node@8.10.66: resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} dev: true - /@types/normalize-package-data@2.4.2: - resolution: {integrity: sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==} + /@types/normalize-package-data@2.4.3: + resolution: {integrity: sha512-ehPtgRgaULsFG8x0NeYJvmyH1hmlfsNLujHe9dQEia/7MAJYdzMSi19JtchUHjmBA6XC/75dK55mzZH+RyieSg==} - /@types/papaparse@5.3.9: - resolution: {integrity: sha512-sZcrKD63qA4/6GyBcVvX6AIp0AkpfyYk00CUQHMBvb4+OVXTZWyXUvidUZaai1wyKUVyJoxO7mgREam/pMRrDw==} + /@types/papaparse@5.3.10: + resolution: {integrity: sha512-mS1Fta/xJ9EDYmAvpeWzcV9Gr0cOl1ClpW7di9+wSUNDIDO55tBtyXg97O7K+Syrd9rDEmuejM2iqmJIJ1SO5g==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 dev: true - /@types/parse-json@4.0.0: - resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} - dev: false + /@types/parse-json@4.0.1: + resolution: {integrity: sha512-3YmXzzPAdOTVljVMkTMBdBEvlOLg2cDQaDhnnhT3nT9uDbnJzjWhKlzb+desT12Y7tGqaN6d+AbozcKzyL36Ng==} /@types/parse5@5.0.3: resolution: {integrity: sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==} dev: false - /@types/pbkdf2@3.1.0: - resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} + /@types/pbkdf2@3.1.1: + resolution: {integrity: sha512-4HCoGwR3221nOc7G0Z/6KgTNGgaaFGkbGrtUJsB+zlKX2LBVjFHHIUkieMBgHHXgBH5Gq6dZHJKdBYdtlhBQvw==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 - /@types/phoenix@1.6.2: - resolution: {integrity: sha512-I3mm7x5XIi+5NsIY3nfreY+H4PmQdyBwJ84SiUSOxSg1axwEPNmkKWYVm56y+emDpPPUL3cPzrLcgRWSd9gI7g==} + /@types/phoenix@1.6.3: + resolution: {integrity: sha512-D8TtchWVnU2ZdPVDY6tBJuz8MUDmCNVduilZTrf0Gn/u5I/uZEXOsaL4Gs4F0j43cysHsU/4h7eqAKc+SF2boQ==} dev: false /@types/prettier@2.7.3: resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} - /@types/prop-types@15.7.8: - resolution: {integrity: sha512-kMpQpfZKSCBqltAJwskgePRaYRFukDkm1oItcAbC3gNELR20XIBcN9VRgg4+m8DKsTfkWeA4m4Imp4DDuWy7FQ==} + /@types/prop-types@15.7.9: + resolution: {integrity: sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==} - /@types/qs@6.9.8: - resolution: {integrity: sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==} + /@types/qs@6.9.9: + resolution: {integrity: sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==} - /@types/range-parser@1.2.5: - resolution: {integrity: sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==} + /@types/range-parser@1.2.6: + resolution: {integrity: sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==} - /@types/react-dom@18.2.13: - resolution: {integrity: sha512-eJIUv7rPP+EC45uNYp/ThhSpE16k22VJUknt5OLoH9tbXoi8bMhwLf5xRuWMywamNbWzhrSmU7IBJfPup1+3fw==} + /@types/react-dom@18.2.14: + resolution: {integrity: sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==} dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 dev: true - /@types/react-router-config@5.0.8: - resolution: {integrity: sha512-zBzYZsr05V9xRG96oQ/xBXHy5+fDCX5wL7bboM0FFoOYQp9Gxmz8uvuKSkLesNWHlICl+W1l64F7fmp/KsOkuw==} + /@types/react-router-config@5.0.9: + resolution: {integrity: sha512-a7zOj9yVUtM3Ns5stoseQAAsmppNxZpXDv6tZiFV5qlRmV4W96u53on1vApBX1eRSc8mrFOiB54Hc0Pk1J8GFg==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.28 + '@types/react': 18.2.31 '@types/react-router': 5.1.20 /@types/react-router-dom@5.3.3: resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.28 + '@types/react': 18.2.31 '@types/react-router': 5.1.20 /@types/react-router@5.1.20: resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.28 + '@types/react': 18.2.31 - /@types/react-transition-group@4.4.7: - resolution: {integrity: sha512-ICCyBl5mvyqYp8Qeq9B5G/fyBSRC0zx3XM3sCC6KkcMsNeAHqXBKkmat4GqdJET5jtYUpZXrxI5flve5qhi2Eg==} + /@types/react-transition-group@4.4.8: + resolution: {integrity: sha512-QmQ22q+Pb+HQSn04NL3HtrqHwYMf4h3QKArOy5F8U5nEVMaihBs3SR10WiOM1iwPz5jIo8x/u11al+iEGZZrvg==} dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 dev: false - /@types/react@18.2.28: - resolution: {integrity: sha512-ad4aa/RaaJS3hyGz0BGegdnSRXQBkd1CCYDCdNjBPg90UUpLgo+WlJqb9fMYUxtehmzF3PJaTWqRZjko6BRzBg==} + /@types/react@18.2.31: + resolution: {integrity: sha512-c2UnPv548q+5DFh03y8lEDeMfDwBn9G3dRwfkrxQMo/dOtRHUUO57k6pHvBIfH/VF4Nh+98mZ5aaSe+2echD5g==} dependencies: - '@types/prop-types': 15.7.8 - '@types/scheduler': 0.16.4 + '@types/prop-types': 15.7.9 + '@types/scheduler': 0.16.5 csstype: 3.1.2 /@types/readable-stream@2.3.15: resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 safe-buffer: 5.1.2 /@types/resolve@1.20.2: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} dev: true - /@types/responselike@1.0.1: - resolution: {integrity: sha512-TiGnitEDxj2X0j+98Eqk5lv/Cij8oHd32bU4D/Yw6AOq7vvTk0gSD2GPj0G/HkvhMoVsdlhYF4yqqlyPBTM6Sg==} + /@types/responselike@1.0.2: + resolution: {integrity: sha512-/4YQT5Kp6HxUDb4yhRkm0bJ7TbjvTddqX7PZ5hz6qV3pxSo72f/6YPRo+Mu2DU307tm9IioO69l7uAwn5XNcFA==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 /@types/retry@0.12.0: resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} @@ -13095,88 +12607,92 @@ packages: resolution: {integrity: sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==} dev: false - /@types/sax@1.2.5: - resolution: {integrity: sha512-9jWta97bBVC027/MShr3gLab8gPhKy4l6qpb+UJLF5pDm3501NvA7uvqVCW+REFtx00oTi6Cq9JzLwgq6evVgw==} + /@types/sax@1.2.6: + resolution: {integrity: sha512-A1mpYCYu1aHFayy8XKN57ebXeAbh9oQIZ1wXcno6b1ESUAfMBDMx7mf/QGlYwcMRaFryh9YBuH03i/3FlPGDkQ==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 dev: false - /@types/scheduler@0.16.4: - resolution: {integrity: sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==} + /@types/scheduler@0.16.5: + resolution: {integrity: sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==} - /@types/secp256k1@4.0.4: - resolution: {integrity: sha512-oN0PFsYxDZnX/qSJ5S5OwaEDTYfekhvaM5vqui2bu1AA39pKofmgL104Q29KiOXizXS2yLjSzc5YdTyMKdcy4A==} + /@types/secp256k1@4.0.5: + resolution: {integrity: sha512-aIonTBMErtE3T9MxDvTZRzcrT/mCqpEZBw3CCY/i+oG9n57N/+7obBkhFgavUAIrX21bU0LHg1XRgtaLdelBhA==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 /@types/seedrandom@3.0.1: resolution: {integrity: sha512-giB9gzDeiCeloIXDgzFBCgjj1k4WxcDrZtGl6h1IqmUPlxF+Nx8Ve+96QCyDZ/HseB/uvDsKbpib9hU5cU53pw==} dev: true - /@types/semver@7.5.3: - resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==} + /@types/semver@7.5.4: + resolution: {integrity: sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==} dev: true - /@types/send@0.17.2: - resolution: {integrity: sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==} + /@types/send@0.17.3: + resolution: {integrity: sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==} dependencies: - '@types/mime': 1.3.3 - '@types/node': 18.15.13 + '@types/mime': 1.3.4 + '@types/node': 18.18.6 - /@types/serve-index@1.9.2: - resolution: {integrity: sha512-asaEIoc6J+DbBKXtO7p2shWUpKacZOoMBEGBgPG91P8xhO53ohzHWGCs4ScZo5pQMf5ukQzVT9fhX1WzpHihig==} + /@types/serve-index@1.9.3: + resolution: {integrity: sha512-4KG+yMEuvDPRrYq5fyVm/I2uqAJSAwZK9VSa+Zf+zUq9/oxSSvy3kkIqyL+jjStv6UCVi8/Aho0NHtB1Fwosrg==} dependencies: - '@types/express': 4.17.19 + '@types/express': 4.17.20 - /@types/serve-static@1.15.3: - resolution: {integrity: sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==} + /@types/serve-static@1.15.4: + resolution: {integrity: sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==} dependencies: - '@types/http-errors': 2.0.2 - '@types/mime': 3.0.2 - '@types/node': 18.15.13 + '@types/http-errors': 2.0.3 + '@types/mime': 3.0.3 + '@types/node': 18.18.6 - /@types/set-cookie-parser@2.4.4: - resolution: {integrity: sha512-xCfTC/eL/GmvMC24b42qJpYSTdCIBwWcfskDF80ztXtnU6pKXyvuZP2EConb2K9ps0s7gMhCa0P1foy7wiItMA==} + /@types/set-cookie-parser@2.4.5: + resolution: {integrity: sha512-ZPmztaAQ4rbnW/WTUnT1dwSENQo4bjGqxCSeyK+gZxmd+zJl/QAeF6dpEXcS5UEJX22HwiggFSaY8nE1nRmkbg==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 dev: true - /@types/sinon@10.0.19: - resolution: {integrity: sha512-MWZNGPSchIdDfb5FL+VFi4zHsHbNOTQEgjqFQk7HazXSXwUU9PAX3z9XBqb3AJGYr9YwrtCtaSMsT3brYsN/jQ==} + /@types/sinon@10.0.20: + resolution: {integrity: sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg==} dependencies: - '@types/sinonjs__fake-timers': 8.1.1 + '@types/sinonjs__fake-timers': 8.1.4 dev: true /@types/sinonjs__fake-timers@8.1.1: resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} dev: true - /@types/sizzle@2.3.4: - resolution: {integrity: sha512-jA2llq2zNkg8HrALI7DtWzhALcVH0l7i89yhY3iBdOz6cBPeACoFq+fkQrjHA39t1hnSFOboZ7A/AY5MMZSlag==} + /@types/sinonjs__fake-timers@8.1.4: + resolution: {integrity: sha512-GDV68H0mBSN449sa5HEj51E0wfpVQb8xNSMzxf/PrypMFcLTMwJMOM/cgXiv71Mq5drkOQmUGvL1okOZcu6RrQ==} + dev: true + + /@types/sizzle@2.3.5: + resolution: {integrity: sha512-tAe4Q+OLFOA/AMD+0lq8ovp8t3ysxAOeaScnfNdZpUxaGl51ZMDEITxkvFl1STudQ58mz6gzVGl9VhMKhwRnZQ==} dev: true - /@types/sockjs@0.3.34: - resolution: {integrity: sha512-R+n7qBFnm/6jinlteC9DBL5dGiDGjWAvjo4viUanpnc/dG1y7uDoacXPIQ/PQEg1fI912SMHIa014ZjRpvDw4g==} + /@types/sockjs@0.3.35: + resolution: {integrity: sha512-tIF57KB+ZvOBpAQwSaACfEu7htponHXaFzP7RfKYgsOS0NoYnn+9+jzp7bbq4fWerizI3dTB4NfAZoyeQKWJLw==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 - /@types/source-list-map@0.1.3: - resolution: {integrity: sha512-I9R/7fUjzUOyDy6AFkehCK711wWoAXEaBi80AfjZt1lIkbe6AcXKd3ckQc3liMvQExWvfOeh/8CtKzrfUFN5gA==} + /@types/source-list-map@0.1.4: + resolution: {integrity: sha512-Kdfm7Sk5VX8dFW7Vbp18+fmAatBewzBILa1raHYxrGEFXT0jNl9x3LWfuW7bTbjEKFNey9Dfkj/UzT6z/NvRlg==} dev: true /@types/stack-trace@0.0.29: resolution: {integrity: sha512-TgfOX+mGY/NyNxJLIbDWrO9DjGoVSW9+aB8H2yy1fy32jsvxijhmyJI9fDFgvz3YP4lvJaq9DzdR/M1bOgVc9g==} dev: true - /@types/stack-utils@2.0.1: - resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} + /@types/stack-utils@2.0.2: + resolution: {integrity: sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==} - /@types/tapable@1.0.9: - resolution: {integrity: sha512-fOHIwZua0sRltqWzODGUM6b4ffZrf/vzGUmNXdR+4DzuJP42PMbM5dLKcdzlYvv8bMJ3GALOzkk1q7cDm2zPyA==} + /@types/tapable@1.0.10: + resolution: {integrity: sha512-q8F20SdXG5fdVJQ5yxsVlH+f+oekP42QeHv4s5KlrxTMT0eopXn7ol1rhxMcksf8ph7XNv811iVDE2hOpUvEPg==} dev: true - /@types/testing-library__cypress@5.0.11: - resolution: {integrity: sha512-SNKUJWfxJKG7ZAmkRCFYWfqxBk3nxD60QKUJYXpU7wxX85EikDEjHxIGmQQfZ6TLSyItMrkgt9MHlX0rG7JF/Q==} + /@types/testing-library__cypress@5.0.12: + resolution: {integrity: sha512-MxX257KJIDnakpfCOzpT3tIwrWd3bpGWHCMIpJO3Ye1sCxtzluRyYIKWt6+XDr9ZzJeHlsR9i5ggZEgNB71cfQ==} dependencies: '@testing-library/dom': 7.31.2 cypress: 12.17.4 @@ -13185,86 +12701,85 @@ packages: /@types/testing-library__jest-dom@5.14.9: resolution: {integrity: sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==} dependencies: - '@types/jest': 29.5.5 + '@types/jest': 29.5.6 dev: true - /@types/tough-cookie@4.0.3: - resolution: {integrity: sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg==} + /@types/tough-cookie@4.0.4: + resolution: {integrity: sha512-95Sfz4nvMAb0Nl9DTxN3j64adfwfbBPEYq14VN7zT5J5O2M9V6iZMIIQU1U+pJyl9agHYHNCqhCXgyEtIRRa5A==} dev: true - /@types/trusted-types@2.0.4: - resolution: {integrity: sha512-IDaobHimLQhjwsQ/NMwRVfa/yL7L/wriQPMhw1ZJall0KX6E1oxk29XMDeilW5qTIg5aoiqf5Udy8U/51aNoQQ==} + /@types/trusted-types@2.0.5: + resolution: {integrity: sha512-I3pkr8j/6tmQtKV/ZzHtuaqYSQvyjGRKH4go60Rr0IDLlFxuRT5V32uvB1mecM5G1EVAUyF/4r4QZ1GHgz+mxA==} dev: false - /@types/uglify-js@3.17.2: - resolution: {integrity: sha512-9SjrHO54LINgC/6Ehr81NjAxAYvwEZqjUHLjJYvC4Nmr9jbLQCIZbWSvl4vXQkkmR1UAuaKDycau3O1kWGFyXQ==} + /@types/uglify-js@3.17.3: + resolution: {integrity: sha512-ToldSfJ6wxO21cakcz63oFD1GjqQbKzhZCD57eH7zWuYT5UEZvfUoqvrjX5d+jB9g4a/sFO0n6QSVzzn5sMsjg==} dependencies: source-map: 0.6.1 dev: true - /@types/unist@2.0.8: - resolution: {integrity: sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==} + /@types/unist@2.0.9: + resolution: {integrity: sha512-zC0iXxAv1C1ERURduJueYzkzZ2zaGyc+P2c95hgkikHPr3z8EdUZOlgEQ5X0DRmwDZn+hekycQnoeiiRVrmilQ==} dev: false - /@types/webpack-sources@3.2.1: - resolution: {integrity: sha512-iLC3Fsx62ejm3ST3PQ8vBMC54Rb3EoCprZjeJGI5q+9QjfDLGt9jeg/k245qz1G9AQnORGk0vqPicJFPT1QODQ==} + /@types/webpack-sources@3.2.2: + resolution: {integrity: sha512-acCzhuVe+UJy8abiSFQWXELhhNMZjQjQKpLNEi1pKGgKXZj0ul614ATcx4kkhunPost6Xw+aCq8y8cn1/WwAiA==} dependencies: - '@types/node': 18.15.13 - '@types/source-list-map': 0.1.3 + '@types/node': 18.18.6 + '@types/source-list-map': 0.1.4 source-map: 0.7.4 dev: true - /@types/webpack@4.41.34: - resolution: {integrity: sha512-CN2aOGrR3zbMc2v+cKqzaClYP1ldkpPOgtdNvgX+RmlWCSWxHxpzz6WSCVQZRkF8D60ROlkRzAoEpgjWQ+bd2g==} + /@types/webpack@4.41.35: + resolution: {integrity: sha512-XRC6HLGHtNfN8/xWeu1YUQV1GSE+28q8lSqvcJ+0xt/zW9Wmn4j9pCSvaXPyRlCKrl5OuqECQNEJUy2vo8oWqg==} dependencies: - '@types/node': 18.15.13 - '@types/tapable': 1.0.9 - '@types/uglify-js': 3.17.2 - '@types/webpack-sources': 3.2.1 + '@types/node': 18.18.6 + '@types/tapable': 1.0.10 + '@types/uglify-js': 3.17.3 + '@types/webpack-sources': 3.2.2 anymatch: 3.1.3 source-map: 0.6.1 dev: true - /@types/websocket@1.0.7: - resolution: {integrity: sha512-62Omr8U0PO+hgjLCpPnMsmjh2/FRwIGOktZHyYAUzooEJotwkXHMp7vCacdYi8haxBNOiw9bc2HIHI+b/MPNjA==} + /@types/websocket@1.0.8: + resolution: {integrity: sha512-wvkOpWApbuxVfHhSQ1XrjVN4363vsfLJwEo4AboIZk0g1vJA5nmLp8GXUHuIdf4/Fe7+/V0Efe2HvWiLqHtlqw==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 dev: false /@types/ws@7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: - '@types/node': 18.15.13 - dev: false + '@types/node': 18.18.6 - /@types/ws@8.5.7: - resolution: {integrity: sha512-6UrLjiDUvn40CMrAubXuIVtj2PEfKDffJS7ychvnPU44j+KVeXmdHHTgqcM/dxLUTHxlXHiFM8Skmb8ozGdTnQ==} + /@types/ws@8.5.8: + resolution: {integrity: sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg==} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 - /@types/yargs-parser@21.0.1: - resolution: {integrity: sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==} + /@types/yargs-parser@21.0.2: + resolution: {integrity: sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==} - /@types/yargs@15.0.16: - resolution: {integrity: sha512-2FeD5qezW3FvLpZ0JpfuaEWepgNLl9b2gQYiz/ce0NhoB1W/D+VZu98phITXkADYerfr/jb7JcDcVhITsc9bwg==} + /@types/yargs@15.0.17: + resolution: {integrity: sha512-cj53I8GUcWJIgWVTSVe2L7NJAB5XWGdsoMosVvUgv1jEnMbAcsbaCzt1coUcyi8Sda5PgTWAooG8jNyDTD+CWA==} dependencies: - '@types/yargs-parser': 21.0.1 + '@types/yargs-parser': 21.0.2 - /@types/yargs@16.0.6: - resolution: {integrity: sha512-oTP7/Q13GSPrgcwEwdlnkoZSQ1Hg9THe644qq8PG6hhJzjZ3qj1JjEFPIwWV/IXVs5XGIVqtkNOS9kh63WIJ+A==} + /@types/yargs@16.0.7: + resolution: {integrity: sha512-lQcYmxWuOfJq4IncK88/nwud9rwr1F04CFc5xzk0k4oKVyz/AI35TfsXmhjf6t8zp8mpCOi17BfvuNWx+zrYkg==} dependencies: - '@types/yargs-parser': 21.0.1 + '@types/yargs-parser': 21.0.2 - /@types/yargs@17.0.28: - resolution: {integrity: sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==} + /@types/yargs@17.0.29: + resolution: {integrity: sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==} dependencies: - '@types/yargs-parser': 21.0.1 + '@types/yargs-parser': 21.0.2 - /@types/yauzl@2.10.1: - resolution: {integrity: sha512-CHzgNU3qYBnp/O4S3yv2tXPlvMTq0YWSTVg2/JYLqWZGHwwgJGAwd00poay/11asPq8wLFwHzubyInqHIFmmiw==} + /@types/yauzl@2.10.2: + resolution: {integrity: sha512-Km7XAtUIduROw7QPgvcft0lIupeG8a8rdKL8RiSyKvlE7dYY31fEn41HVuQsRFDuROA8tA4K2UVL+WdfFmErBA==} requiresBuild: true dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 dev: true optional: true @@ -13296,7 +12811,7 @@ packages: - supports-color dev: true - /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.51.0)(typescript@4.9.5): + /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.52.0)(typescript@4.9.5): resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -13308,12 +12823,12 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.9.1 - '@typescript-eslint/parser': 5.62.0(eslint@8.51.0)(typescript@4.9.5) + '@typescript-eslint/parser': 5.62.0(eslint@8.52.0)(typescript@4.9.5) '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/type-utils': 5.62.0(eslint@8.51.0)(typescript@4.9.5) - '@typescript-eslint/utils': 5.62.0(eslint@8.51.0)(typescript@4.9.5) + '@typescript-eslint/type-utils': 5.62.0(eslint@8.52.0)(typescript@4.9.5) + '@typescript-eslint/utils': 5.62.0(eslint@8.52.0)(typescript@4.9.5) debug: 4.3.4(supports-color@8.1.1) - eslint: 8.51.0 + eslint: 8.52.0 graphemer: 1.4.0 ignore: 5.2.4 natural-compare-lite: 1.4.0 @@ -13344,7 +12859,7 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@5.62.0(eslint@8.51.0)(typescript@4.9.5): + /@typescript-eslint/parser@5.62.0(eslint@8.52.0)(typescript@4.9.5): resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -13358,7 +12873,7 @@ packages: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5) debug: 4.3.4(supports-color@8.1.1) - eslint: 8.51.0 + eslint: 8.52.0 typescript: 4.9.5 transitivePeerDependencies: - supports-color @@ -13392,7 +12907,7 @@ packages: - supports-color dev: true - /@typescript-eslint/type-utils@5.62.0(eslint@8.51.0)(typescript@4.9.5): + /@typescript-eslint/type-utils@5.62.0(eslint@8.52.0)(typescript@4.9.5): resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -13403,9 +12918,9 @@ packages: optional: true dependencies: '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5) - '@typescript-eslint/utils': 5.62.0(eslint@8.51.0)(typescript@4.9.5) + '@typescript-eslint/utils': 5.62.0(eslint@8.52.0)(typescript@4.9.5) debug: 4.3.4(supports-color@8.1.1) - eslint: 8.51.0 + eslint: 8.52.0 tsutils: 3.21.0(typescript@4.9.5) typescript: 4.9.5 transitivePeerDependencies: @@ -13466,8 +12981,8 @@ packages: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.19.0) - '@types/json-schema': 7.0.13 - '@types/semver': 7.5.3 + '@types/json-schema': 7.0.14 + '@types/semver': 7.5.4 '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) @@ -13479,19 +12994,19 @@ packages: - typescript dev: true - /@typescript-eslint/utils@5.62.0(eslint@8.51.0)(typescript@4.9.5): + /@typescript-eslint/utils@5.62.0(eslint@8.52.0)(typescript@4.9.5): resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.51.0) - '@types/json-schema': 7.0.13 - '@types/semver': 7.5.3 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) + '@types/json-schema': 7.0.14 + '@types/semver': 7.5.4 '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5) - eslint: 8.51.0 + eslint: 8.52.0 eslint-scope: 5.1.1 semver: 7.5.4 transitivePeerDependencies: @@ -13507,6 +13022,10 @@ packages: eslint-visitor-keys: 3.4.3 dev: true + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + /@vanilla-extract/css@1.9.1: resolution: {integrity: sha512-pu2SFiff5jRhPwvGoj8cM5l/qIyLvigOmy22ss5DGjwV5pJYezRjDLxWumi2luIwioMWvh9EozCjyfH8nq+7fQ==} dependencies: @@ -13551,7 +13070,7 @@ packages: execa: 7.2.0 get-port: 6.1.2 http-proxy: 1.18.1(debug@4.3.4) - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - debug @@ -13585,61 +13104,61 @@ packages: dependencies: cli-truncate: 3.1.0 diff: 5.1.0 - loupe: 2.3.6 + loupe: 2.3.7 picocolors: 1.0.0 pretty-format: 27.5.1 dev: true - /@vue/compiler-core@3.3.4: - resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} + /@vue/compiler-core@3.3.6: + resolution: {integrity: sha512-2JNjemwaNwf+MkkatATVZi7oAH1Hx0B04DdPH3ZoZ8vKC1xZVP7nl4HIsk8XYd3r+/52sqqoz9TWzYc3yE9dqA==} dependencies: '@babel/parser': 7.23.0 - '@vue/shared': 3.3.4 + '@vue/shared': 3.3.6 estree-walker: 2.0.2 source-map-js: 1.0.2 dev: true - /@vue/compiler-dom@3.3.4: - resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} + /@vue/compiler-dom@3.3.6: + resolution: {integrity: sha512-1MxXcJYMHiTPexjLAJUkNs/Tw2eDf2tY3a0rL+LfuWyiKN2s6jvSwywH3PWD8bKICjfebX3GWx2Os8jkRDq3Ng==} dependencies: - '@vue/compiler-core': 3.3.4 - '@vue/shared': 3.3.4 + '@vue/compiler-core': 3.3.6 + '@vue/shared': 3.3.6 dev: true - /@vue/compiler-sfc@3.3.4: - resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} + /@vue/compiler-sfc@3.3.6: + resolution: {integrity: sha512-/Kms6du2h1VrXFreuZmlvQej8B1zenBqIohP0690IUBkJjsFvJxY0crcvVRJ0UhMgSR9dewB+khdR1DfbpArJA==} dependencies: '@babel/parser': 7.23.0 - '@vue/compiler-core': 3.3.4 - '@vue/compiler-dom': 3.3.4 - '@vue/compiler-ssr': 3.3.4 - '@vue/reactivity-transform': 3.3.4 - '@vue/shared': 3.3.4 + '@vue/compiler-core': 3.3.6 + '@vue/compiler-dom': 3.3.6 + '@vue/compiler-ssr': 3.3.6 + '@vue/reactivity-transform': 3.3.6 + '@vue/shared': 3.3.6 estree-walker: 2.0.2 magic-string: 0.30.5 postcss: 8.4.31 source-map-js: 1.0.2 dev: true - /@vue/compiler-ssr@3.3.4: - resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} + /@vue/compiler-ssr@3.3.6: + resolution: {integrity: sha512-QTIHAfDCHhjXlYGkUg5KH7YwYtdUM1vcFl/FxFDlD6d0nXAmnjizka3HITp8DGudzHndv2PjKVS44vqqy0vP4w==} dependencies: - '@vue/compiler-dom': 3.3.4 - '@vue/shared': 3.3.4 + '@vue/compiler-dom': 3.3.6 + '@vue/shared': 3.3.6 dev: true - /@vue/reactivity-transform@3.3.4: - resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} + /@vue/reactivity-transform@3.3.6: + resolution: {integrity: sha512-RlJl4dHfeO7EuzU1iJOsrlqWyJfHTkJbvYz/IOJWqu8dlCNWtxWX377WI0VsbAgBizjwD+3ZjdnvSyyFW1YVng==} dependencies: '@babel/parser': 7.23.0 - '@vue/compiler-core': 3.3.4 - '@vue/shared': 3.3.4 + '@vue/compiler-core': 3.3.6 + '@vue/shared': 3.3.6 estree-walker: 2.0.2 magic-string: 0.30.5 dev: true - /@vue/shared@3.3.4: - resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} + /@vue/shared@3.3.6: + resolution: {integrity: sha512-Xno5pEqg8SVhomD0kTSmfh30ZEmV/+jZtyh39q6QflrjdJCXah5lrnOLi9KB6a5k5aAHXMXjoMnxlzUkCNfWLQ==} dev: true /@wagmi/chains@1.0.0(typescript@5.1.6): @@ -13700,7 +13219,7 @@ packages: - zod dev: false - /@wagmi/core@1.3.8(@types/react@18.2.28)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): + /@wagmi/core@1.3.8(@types/react@18.2.31)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): resolution: {integrity: sha512-OYSxikoMizqVnpSkFTwGE7PwFaz2k0PXteSiI0W2Mtk4j4sZzRFdP+9AWeDB6AYm0yU3WvgN1IATx0EEBKUe3w==} peerDependencies: typescript: '>=5.0.4' @@ -13715,7 +13234,7 @@ packages: eventemitter3: 4.0.7 typescript: 5.1.6 viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) - zustand: 4.4.3(@types/react@18.2.28)(react@18.2.0) + zustand: 4.4.4(@types/react@18.2.31)(react@18.2.0) transitivePeerDependencies: - '@react-native-async-storage/async-storage' - '@types/react' @@ -14247,27 +13766,27 @@ packages: '@webassemblyjs/ast': 1.11.6 '@xtuc/long': 4.2.2 - /@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.88.2): + /@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.89.0): resolution: {integrity: sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==} engines: {node: '>=14.15.0'} peerDependencies: webpack: 5.x.x webpack-cli: 5.x.x dependencies: - webpack: 5.88.2(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.88.2) + webpack: 5.89.0(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack@5.89.0) - /@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.88.2): + /@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.89.0): resolution: {integrity: sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==} engines: {node: '>=14.15.0'} peerDependencies: webpack: 5.x.x webpack-cli: 5.x.x dependencies: - webpack: 5.88.2(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.88.2) + webpack: 5.89.0(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack@5.89.0) - /@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.88.2): + /@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.89.0): resolution: {integrity: sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==} engines: {node: '>=14.15.0'} peerDependencies: @@ -14278,8 +13797,8 @@ packages: webpack-dev-server: optional: true dependencies: - webpack: 5.88.2(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.88.2) + webpack: 5.89.0(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack@5.89.0) /@whatwg-node/cookie-store@0.0.1: resolution: {integrity: sha512-uoti8QU5xd+X+9PULOGpPpOqPDdwkz+ukMc4kyQG1GwXeKVGktr4FSllr6dBotjOjNVPSBPpmj5V6zrUdDcLaw==} @@ -14391,6 +13910,14 @@ packages: requiresBuild: true optional: true + /JSONStream@1.3.2: + resolution: {integrity: sha512-mn0KSip7N4e0UDPZHnqDsHECo5uGQrixQKnAskOM1BIB8hd7QKbd6il8IPRPudPHOeHiECoCFqhyMaRO9+nWyA==} + hasBin: true + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + dev: true + /JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true @@ -14763,6 +14290,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + /ansicolors@0.3.2: + resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} + dev: true + /antlr4@4.13.1: resolution: {integrity: sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==} engines: {node: '>=16'} @@ -14781,11 +14312,9 @@ packages: dependencies: abort-controller: 3.0.0 native-abort-controller: 1.0.4(abort-controller@3.0.0) - dev: false /any-signal@3.0.1: resolution: {integrity: sha512-xgZgJtKEa9YmDqXodIgl7Fl1C8yNXr8w6gXjqK3LW4GcEiYT+6AQfJSE/8SPsEpLLmcvbv8YU+qet94UewHxqg==} - dev: false /any-signal@4.1.1: resolution: {integrity: sha512-iADenERppdC+A2YKbOXXB2WUeABLaM6qnpZ70kZbPZ1cZMMJ7eF+3CaYm+/PhBizgkzlvssC7QuHS30oOiQYWA==} @@ -14799,6 +14328,18 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 + /apisauce@2.1.6(debug@4.3.4): + resolution: {integrity: sha512-MdxR391op/FucS2YQRfB/NMRyCnHEPDd4h17LRIuVYi0BpGmMhpxc0shbOpfs5ahABuBEffNCGal5EcsydbBWg==} + dependencies: + axios: 0.21.4(debug@4.3.4) + transitivePeerDependencies: + - debug + dev: true + + /app-module-path@2.2.0: + resolution: {integrity: sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ==} + dev: true + /app-root-path@3.1.0: resolution: {integrity: sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==} engines: {node: '>= 6.0.0'} @@ -14847,8 +14388,8 @@ packages: resolution: {integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==} engines: {node: '>=6.0'} dependencies: - '@babel/runtime': 7.23.1 - '@babel/runtime-corejs3': 7.23.1 + '@babel/runtime': 7.23.2 + '@babel/runtime-corejs3': 7.23.2 dev: true /aria-query@5.1.3: @@ -14857,6 +14398,12 @@ packages: deep-equal: 2.2.2 dev: true + /aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + dependencies: + dequal: 2.0.3 + dev: true + /array-back@3.1.0: resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} engines: {node: '>=6'} @@ -14868,7 +14415,7 @@ packages: /array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 is-array-buffer: 3.0.2 dev: true @@ -14886,10 +14433,10 @@ packages: resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - get-intrinsic: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 is-string: 1.0.7 dev: true @@ -14918,51 +14465,51 @@ packages: resolution: {integrity: sha512-kcBubumjciBg4JKp5KTKtI7ec7tRefPk88yjkWJwaVKYd9QfTaxcsOxoMNKd7iBr447zCfDV0z1kOF47umv42g==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - es-shim-unscopables: 1.0.0 - get-intrinsic: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + get-intrinsic: 1.2.2 dev: true /array.prototype.findlastindex@1.2.3: resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - es-shim-unscopables: 1.0.0 - get-intrinsic: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + get-intrinsic: 1.2.2 dev: true /array.prototype.flat@1.3.2: resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - es-shim-unscopables: 1.0.0 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 dev: true /array.prototype.flatmap@1.3.2: resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - es-shim-unscopables: 1.0.0 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 dev: true /array.prototype.reduce@1.0.6: resolution: {integrity: sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 + es-abstract: 1.22.3 es-array-method-boxes-properly: 1.0.0 is-string: 1.0.7 dev: true @@ -14970,11 +14517,11 @@ packages: /array.prototype.tosorted@1.1.2: resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - es-shim-unscopables: 1.0.0 - get-intrinsic: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + get-intrinsic: 1.2.2 dev: true /arraybuffer.prototype.slice@1.0.2: @@ -14982,10 +14529,10 @@ packages: engines: {node: '>= 0.4'} dependencies: array-buffer-byte-length: 1.0.0 - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - get-intrinsic: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 is-array-buffer: 3.0.2 is-shared-array-buffer: 1.0.2 dev: true @@ -15011,6 +14558,23 @@ packages: pvutils: 1.1.3 tslib: 2.6.2 + /assemblyscript@0.19.10: + resolution: {integrity: sha512-HavcUBXB3mBTRGJcpvaQjmnmaqKHBGREjSPNsIvnAk2f9dj78y4BkMaSSdvBQYWcDDzsHQjyUC8stICFkD1Odg==} + hasBin: true + dependencies: + binaryen: 101.0.0-nightly.20210723 + long: 4.0.0 + dev: true + + /assemblyscript@0.19.23: + resolution: {integrity: sha512-fwOQNZVTMga5KRsfY80g7cpOl4PsFQczMwHzdtgoqLXaYhkhavufKb0sB0l3T1DUxpAufA0KNhlbpuuhZUwxMA==} + hasBin: true + dependencies: + binaryen: 102.0.0-nightly.20211028 + long: 5.2.3 + source-map-support: 0.5.21 + dev: true + /assert-plus@1.0.0: resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} engines: {node: '>=0.8'} @@ -15111,8 +14675,8 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.22.1 - caniuse-lite: 1.0.30001547 - fraction.js: 4.3.6 + caniuse-lite: 1.0.30001553 + fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.0 postcss: 8.4.31 @@ -15209,7 +14773,7 @@ packages: dependencies: '@babel/core': 7.23.2 '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.2 + '@types/babel__core': 7.20.3 babel-plugin-istanbul: 6.1.1 babel-preset-jest: 29.6.3(@babel/core@7.23.2) chalk: 4.1.2 @@ -15218,22 +14782,22 @@ packages: transitivePeerDependencies: - supports-color - /babel-loader@8.3.0(@babel/core@7.23.0)(webpack@5.88.2): + /babel-loader@8.3.0(@babel/core@7.23.2)(webpack@5.89.0): resolution: {integrity: sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==} engines: {node: '>= 8.9'} peerDependencies: '@babel/core': ^7.0.0 webpack: '>=2' dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.23.2 find-cache-dir: 3.3.2 loader-utils: 2.0.4 make-dir: 3.1.0 schema-utils: 2.7.1 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: false - /babel-loader@9.1.3(@babel/core@7.23.2)(webpack@5.88.2): + /babel-loader@9.1.3(@babel/core@7.23.2)(webpack@5.89.0): resolution: {integrity: sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -15243,7 +14807,7 @@ packages: '@babel/core': 7.23.2 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: true /babel-plugin-apply-mdx-type-prop@1.6.22(@babel/core@7.12.9): @@ -15286,31 +14850,18 @@ packages: dependencies: '@babel/template': 7.22.15 '@babel/types': 7.23.0 - '@types/babel__core': 7.20.2 - '@types/babel__traverse': 7.20.2 + '@types/babel__core': 7.20.3 + '@types/babel__traverse': 7.20.3 /babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 cosmiconfig: 7.1.0 resolve: 1.22.8 dev: false - /babel-plugin-polyfill-corejs2@0.4.6(@babel/core@7.23.0): - resolution: {integrity: sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/compat-data': 7.23.2 - '@babel/core': 7.23.0 - '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.23.0) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: false - /babel-plugin-polyfill-corejs2@0.4.6(@babel/core@7.23.2): resolution: {integrity: sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==} peerDependencies: @@ -15323,39 +14874,16 @@ packages: transitivePeerDependencies: - supports-color - /babel-plugin-polyfill-corejs3@0.8.5(@babel/core@7.23.0): - resolution: {integrity: sha512-Q6CdATeAvbScWPNLB8lzSO7fgUVBkQt6zLgNlfyeCr/EQaEQR+bWiBYYPYAFyE528BMjRhL+1QBMOI4jc/c5TA==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.23.0) - core-js-compat: 3.33.0 - transitivePeerDependencies: - - supports-color - dev: false - - /babel-plugin-polyfill-corejs3@0.8.5(@babel/core@7.23.2): - resolution: {integrity: sha512-Q6CdATeAvbScWPNLB8lzSO7fgUVBkQt6zLgNlfyeCr/EQaEQR+bWiBYYPYAFyE528BMjRhL+1QBMOI4jc/c5TA==} + /babel-plugin-polyfill-corejs3@0.8.6(@babel/core@7.23.2): + resolution: {integrity: sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 dependencies: '@babel/core': 7.23.2 '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.23.2) - core-js-compat: 3.33.0 - transitivePeerDependencies: - - supports-color - - /babel-plugin-polyfill-regenerator@0.5.3(@babel/core@7.23.0): - resolution: {integrity: sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.23.0 - '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.23.0) + core-js-compat: 3.33.1 transitivePeerDependencies: - supports-color - dev: false /babel-plugin-polyfill-regenerator@0.5.3(@babel/core@7.23.2): resolution: {integrity: sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==} @@ -15558,6 +15086,27 @@ packages: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} + /binary-install-raw@0.0.13(debug@4.3.4): + resolution: {integrity: sha512-v7ms6N/H7iciuk6QInon3/n2mu7oRX+6knJ9xFPsJ3rQePgAqcR3CRTwUheFd8SLbiq4LL7Z4G/44L9zscdt9A==} + engines: {node: '>=10'} + dependencies: + axios: 0.21.4(debug@4.3.4) + rimraf: 3.0.2 + tar: 6.2.0 + transitivePeerDependencies: + - debug + dev: true + + /binaryen@101.0.0-nightly.20210723: + resolution: {integrity: sha512-eioJNqhHlkguVSbblHOtLqlhtC882SOEPKmNFZaDuz1hzQjolxZ+eu3/kaS10n3sGPONsIZsO7R9fR00UyhEUA==} + hasBin: true + dev: true + + /binaryen@102.0.0-nightly.20211028: + resolution: {integrity: sha512-GCJBVB5exbxzzvyt8MGDv/MeUjs6gkXDvf4xOIItRBptYl0Tz5sm1o/uG95YK0L0VeG5ajDu3hRtkBP2kzqC5w==} + hasBin: true + dev: true + /bind-decorator@1.0.11: resolution: {integrity: sha512-yzkH0uog6Vv/vQ9+rhSKxecnqGUZHYncg7qS7voz3Q76+TAi1SGiOKk2mlOvusQnFz9Dc4BC/NMkeXu11YgjJg==} dev: false @@ -15610,7 +15159,6 @@ packages: resolution: {integrity: sha512-iCmk0W4NdbrWgRRuxOriU8aM5ijeVLI61Zulsmg/lUHNr7pYjoj+U77opLefNagevtrrbMt3JQ5Qip7ar178kA==} dependencies: browser-readablestream-to-it: 1.0.3 - dev: false /blob-to-it@2.0.4: resolution: {integrity: sha512-1z2a98yY7v855TreA3HzwJs/j7ecMzes6U1ty8fJ93S1XbiETsup+h5DA/XBMwK3tBu+CWx4WJjR3b8S13TKeQ==} @@ -15758,7 +15306,7 @@ packages: dependencies: ansi-align: 3.0.1 camelcase: 7.0.1 - chalk: 5.3.0 + chalk: 5.0.1 cli-boxes: 3.0.0 string-width: 5.1.2 type-fest: 2.19.0 @@ -15796,7 +15344,6 @@ packages: /browser-readablestream-to-it@1.0.3: resolution: {integrity: sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw==} - dev: false /browser-readablestream-to-it@2.0.4: resolution: {integrity: sha512-EOjEEA+tJInvKg/Pml6QYxVY6gD8lka/ceLmkUbEeuWlzZx/a5k5ugupVFUUKSfI/88+v0VFs7JSFi5iYpp3IA==} @@ -15820,8 +15367,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001547 - electron-to-chromium: 1.4.549 + caniuse-lite: 1.0.30001553 + electron-to-chromium: 1.4.564 node-releases: 2.0.13 update-browserslist-db: 1.0.13(browserslist@4.22.1) @@ -15908,8 +15455,8 @@ packages: dev: true optional: true - /bufferutil@4.0.7: - resolution: {integrity: sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==} + /bufferutil@4.0.8: + resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} engines: {node: '>=6.14.2'} requiresBuild: true dependencies: @@ -15979,10 +15526,10 @@ packages: resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==} engines: {node: '>=8'} dependencies: - clone-response: 1.0.2 + clone-response: 1.0.3 get-stream: 5.2.0 http-cache-semantics: 4.1.1 - keyv: 3.0.0 + keyv: 3.1.0 lowercase-keys: 2.0.0 normalize-url: 4.5.1 responselike: 1.0.2 @@ -16008,11 +15555,12 @@ packages: write-file-atomic: 3.0.3 dev: true - /call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.2.1 + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.1.1 /call-me-maybe@1.0.2: resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} @@ -16079,13 +15627,13 @@ packages: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} dependencies: browserslist: 4.22.1 - caniuse-lite: 1.0.30001547 + caniuse-lite: 1.0.30001553 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 dev: false - /caniuse-lite@1.0.30001547: - resolution: {integrity: sha512-W7CrtIModMAxobGhz8iXmDfuJiiKg1WADMO/9x7/CLNin5cpSbuBjooyoIUVB5eyCc36QuTVlkVa1iB2S5+/eA==} + /caniuse-lite@1.0.30001553: + resolution: {integrity: sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==} /capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} @@ -16103,6 +15651,14 @@ packages: multiformats: 9.9.0 dev: false + /cardinal@2.1.1: + resolution: {integrity: sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==} + hasBin: true + dependencies: + ansicolors: 0.3.2 + redeyed: 2.1.1 + dev: true + /case@1.6.3: resolution: {integrity: sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==} engines: {node: '>= 0.8.0'} @@ -16132,10 +15688,9 @@ packages: /cborg@1.10.2: resolution: {integrity: sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==} hasBin: true - dev: false - /cborg@4.0.3: - resolution: {integrity: sha512-poLvpK30KT5KI8gzDx3J/IuVCbsLqMT2fEbOrOuX0H7Hyj8yg5LezeWhRh9aLa5Z6MfPC5sriW3HVJF328M8LQ==} + /cborg@4.0.4: + resolution: {integrity: sha512-nu+JXYskYqWN/tFWQVjL2ZYlUwK+dapqkTpruAtJkwmDv7XaTgg8PStUbO+sXfhqSWaeQ9LPSPCTrO2WZ2Bxfg==} hasBin: true dev: false @@ -16173,7 +15728,7 @@ packages: check-error: 1.0.3 deep-eql: 4.1.3 get-func-name: 2.0.2 - loupe: 2.3.6 + loupe: 2.3.7 pathval: 1.1.1 type-detect: 4.0.8 dev: true @@ -16215,6 +15770,7 @@ packages: /chalk@5.3.0: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true /chance@1.1.11: resolution: {integrity: sha512-kqTg3WWywappJPqtgrdvbA380VoXO2eu9VCV895JgbyHsaErXdyHK9LOZ911OvAk6L0obK7kDk9CGs8+oBawVA==} @@ -16341,6 +15897,15 @@ packages: optionalDependencies: fsevents: 2.3.3 + /chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + dev: true + + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: true + /chrome-trace-event@1.0.3: resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} engines: {node: '>=6.0'} @@ -16393,6 +15958,13 @@ packages: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} + /clean-stack@3.0.1: + resolution: {integrity: sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 4.0.0 + dev: true + /cli-boxes@2.2.1: resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} engines: {node: '>=6'} @@ -16427,6 +15999,13 @@ packages: restore-cursor: 4.0.0 dev: true + /cli-progress@3.12.0: + resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==} + engines: {node: '>=4'} + dependencies: + string-width: 4.2.3 + dev: true + /cli-spinners@2.9.1: resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} engines: {node: '>=6'} @@ -16441,6 +16020,16 @@ packages: colors: 1.4.0 dev: true + /cli-table3@0.6.0: + resolution: {integrity: sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==} + engines: {node: 10.* || >= 12.*} + dependencies: + object-assign: 4.1.1 + string-width: 4.2.3 + optionalDependencies: + colors: 1.4.0 + dev: true + /cli-table3@0.6.3: resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} engines: {node: 10.* || >= 12.*} @@ -16525,6 +16114,13 @@ packages: resolution: {integrity: sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==} dependencies: mimic-response: 1.0.1 + dev: true + + /clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + dependencies: + mimic-response: 1.0.1 + dev: false /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} @@ -16563,7 +16159,6 @@ packages: /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - requiresBuild: true dependencies: color-name: 1.1.3 @@ -16575,7 +16170,6 @@ packages: /color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - requiresBuild: true /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} @@ -16876,7 +16470,7 @@ packages: toggle-selection: 1.0.6 dev: false - /copy-webpack-plugin@11.0.0(webpack@5.88.2): + /copy-webpack-plugin@11.0.0(webpack@5.89.0): resolution: {integrity: sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -16888,7 +16482,7 @@ packages: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.1 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: false /copyfiles@2.4.1: @@ -16904,13 +16498,13 @@ packages: yargs: 16.2.0 dev: true - /core-js-compat@3.33.0: - resolution: {integrity: sha512-0w4LcLXsVEuNkIqwjjf9rjCoPhK8uqA4tMRh4Ge26vfLtUutshn+aRJU21I9LCJlh2QQHfisNToLjw1XEJLTWw==} + /core-js-compat@3.33.1: + resolution: {integrity: sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==} dependencies: browserslist: 4.22.1 - /core-js-pure@3.33.0: - resolution: {integrity: sha512-FKSIDtJnds/YFIEaZ4HszRX7hkxGpNKM7FC9aJ9WLJbSd3lD4vOltFuVIBLR8asSx9frkTSqL0dw90SKQxgKrg==} + /core-js-pure@3.33.1: + resolution: {integrity: sha512-wCXGbLjnsP10PlK/thHSQlOLlLKNEkaWbTzVvHHZ79fZNeN1gUmw2gBlpItxPv/pvqldevEXFh/d5stdNvl6EQ==} requiresBuild: true /core-js@2.6.12: @@ -16919,8 +16513,8 @@ packages: requiresBuild: true dev: true - /core-js@3.33.0: - resolution: {integrity: sha512-HoZr92+ZjFEKar5HS6MC776gYslNOKHt75mEBKWKnPeFDpZ6nH5OeF3S6HFT1mUAUZKrzkez05VboaX8myjSuw==} + /core-js@3.33.1: + resolution: {integrity: sha512-qVSq3s+d4+GsqN0teRCJtM6tdEEXyWxjzbhVrCHmBS5ZTM0FS2MOS0D13dUXAWDUN6a+lHI/N1hF9Ytz6iLl9Q==} requiresBuild: true /core-util-is@1.0.2: @@ -16942,10 +16536,25 @@ packages: layout-base: 2.0.1 dev: false + /cosmiconfig-typescript-loader@4.4.0(@types/node@18.18.6)(cosmiconfig@8.3.6)(ts-node@10.9.1)(typescript@5.2.2): + resolution: {integrity: sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==} + engines: {node: '>=v14.21.3'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=7' + ts-node: '>=10' + typescript: '>=4' + dependencies: + '@types/node': 18.18.6 + cosmiconfig: 8.3.6(typescript@5.2.2) + ts-node: 10.9.1(@types/node@18.18.6)(typescript@5.2.2) + typescript: 5.2.2 + dev: true + optional: true + /cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6)(ts-node@10.9.1)(typescript@4.9.5): resolution: {integrity: sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==} engines: {node: '>=v14.21.3'} - requiresBuild: true peerDependencies: '@types/node': '*' cosmiconfig: '>=7' @@ -16971,18 +16580,29 @@ packages: resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==} engines: {node: '>=8'} dependencies: - '@types/parse-json': 4.0.0 + '@types/parse-json': 4.0.1 import-fresh: 3.3.0 parse-json: 5.2.0 path-type: 4.0.0 yaml: 1.10.2 dev: false + /cosmiconfig@7.0.1: + resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.1 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: true + /cosmiconfig@7.1.0: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} dependencies: - '@types/parse-json': 4.0.0 + '@types/parse-json': 4.0.1 import-fresh: 3.3.0 parse-json: 5.2.0 path-type: 4.0.0 @@ -17019,6 +16639,23 @@ packages: path-type: 4.0.0 typescript: 5.1.6 + /cosmiconfig@8.3.6(typescript@5.2.2): + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + typescript: 5.2.2 + dev: true + optional: true + /crc-32@1.2.2: resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} engines: {node: '>=0.8'} @@ -17043,7 +16680,7 @@ packages: safe-buffer: 5.2.1 sha.js: 2.4.11 - /create-jest@29.7.0(@types/node@18.15.13)(ts-node@10.9.1): + /create-jest@29.7.0(@types/node@18.18.6)(ts-node@10.9.1): resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -17052,7 +16689,7 @@ packages: chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@18.15.13)(ts-node@10.9.1) + jest-config: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -17121,7 +16758,7 @@ packages: utrie: 1.0.2 dev: false - /css-loader@6.8.1(webpack@5.88.2): + /css-loader@6.8.1(webpack@5.89.0): resolution: {integrity: sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -17135,10 +16772,10 @@ packages: postcss-modules-values: 4.0.0(postcss@8.4.31) postcss-value-parser: 4.2.0 semver: 7.5.4 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: false - /css-minimizer-webpack-plugin@4.2.2(clean-css@5.3.2)(webpack@5.88.2): + /css-minimizer-webpack-plugin@4.2.2(clean-css@5.3.2)(webpack@5.89.0): resolution: {integrity: sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -17170,7 +16807,7 @@ packages: schema-utils: 4.2.0 serialize-javascript: 6.0.1 source-map: 0.6.1 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: false /css-select@4.3.0: @@ -17330,9 +16967,9 @@ packages: dependencies: '@cypress/request': 2.88.12 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) - '@types/node': 16.18.58 + '@types/node': 16.18.59 '@types/sinonjs__fake-timers': 8.1.1 - '@types/sizzle': 2.3.4 + '@types/sizzle': 2.3.5 arch: 2.2.0 blob-util: 2.0.2 bluebird: 3.7.2 @@ -17410,7 +17047,7 @@ packages: longest: 2.0.1 word-wrap: 1.2.5 optionalDependencies: - '@commitlint/load': 17.8.0 + '@commitlint/load': 18.0.0 transitivePeerDependencies: - '@swc/core' - '@swc/wasm' @@ -17712,7 +17349,6 @@ packages: /data-uri-to-buffer@4.0.1: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} - dev: false /data-urls@3.0.2: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} @@ -17800,10 +17436,6 @@ packages: /dayjs@1.11.7: resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==} - /dayjs@1.11.9: - resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==} - dev: true - /death@1.1.0: resolution: {integrity: sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==} dev: true @@ -17953,9 +17585,9 @@ packages: resolution: {integrity: sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==} dependencies: array-buffer-byte-length: 1.0.0 - call-bind: 1.0.2 + call-bind: 1.0.5 es-get-iterator: 1.1.3 - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 is-arguments: 1.1.1 is-array-buffer: 3.0.2 is-date-object: 1.0.5 @@ -17969,7 +17601,7 @@ packages: side-channel: 1.0.4 which-boxed-primitive: 1.0.2 which-collection: 1.0.1 - which-typed-array: 1.1.11 + which-typed-array: 1.1.13 dev: true /deep-extend@0.6.0: @@ -18030,13 +17662,13 @@ packages: inherits: 2.0.4 dev: true - /define-data-property@1.1.0: - resolution: {integrity: sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==} + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} engines: {node: '>= 0.4'} dependencies: - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 gopd: 1.0.1 - has-property-descriptors: 1.0.0 + has-property-descriptors: 1.0.1 /define-lazy-prop@2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} @@ -18046,15 +17678,15 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} dependencies: - define-data-property: 1.1.0 - has-property-descriptors: 1.0.0 + define-data-property: 1.1.1 + has-property-descriptors: 1.0.1 object-keys: 1.1.1 /del@6.1.1: resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} engines: {node: '>=10'} dependencies: - globby: 11.0.4 + globby: 11.1.0 graceful-fs: 4.2.11 is-glob: 4.0.3 is-path-cwd: 2.2.0 @@ -18073,7 +17705,6 @@ packages: /delay@5.0.0: resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} engines: {node: '>=10'} - dev: false /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} @@ -18229,16 +17860,15 @@ packages: transitivePeerDependencies: - node-fetch - supports-color - dev: false /dns-over-http-resolver@2.1.2: resolution: {integrity: sha512-Bjbf6aZjr3HMnwGslZnoW3MJVqgbTsh39EZWpikx2yLl9xEjw4eZhlOHCFhkOu89zoWaS4rqe2Go53TXW4Byiw==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} dependencies: debug: 4.3.4(supports-color@8.1.1) - native-fetch: 4.0.2(undici@5.26.0) + native-fetch: 4.0.2(undici@5.26.5) receptacle: 1.3.2 - undici: 5.26.0 + undici: 5.26.5 transitivePeerDependencies: - supports-color dev: false @@ -18255,6 +17885,36 @@ packages: asap: 2.0.6 lodash.clone: 4.5.0 + /docker-compose@0.23.19: + resolution: {integrity: sha512-v5vNLIdUqwj4my80wxFDkNH+4S85zsRuH29SO7dCWVWPCMt/ohZBsGN6g6KXWifT0pzQ7uOxqEKCYCDPJ8Vz4g==} + engines: {node: '>= 6.0.0'} + dependencies: + yaml: 1.10.2 + dev: true + + /docker-modem@1.0.9: + resolution: {integrity: sha512-lVjqCSCIAUDZPAZIeyM125HXfNvOmYYInciphNrLrylUtKyW66meAjSPXWchKVzoIYZx69TPnAepVSSkeawoIw==} + engines: {node: '>= 0.8'} + dependencies: + JSONStream: 1.3.2 + debug: 3.2.7(supports-color@8.1.1) + readable-stream: 1.0.34 + split-ca: 1.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /dockerode@2.5.8: + resolution: {integrity: sha512-+7iOUYBeDTScmOmQqpUYQaE7F4vvIt6+gIZNHWhqAQEI887tiPFB9OvXI/HzQYqfUNvukMK+9myLW63oTJPZpw==} + engines: {node: '>= 0.8'} + dependencies: + concat-stream: 1.6.2 + docker-modem: 1.0.9 + tar-fs: 1.16.3 + transitivePeerDependencies: + - supports-color + dev: true + /doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -18296,7 +17956,7 @@ packages: /dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 csstype: 3.1.2 dev: false @@ -18437,15 +18097,30 @@ packages: /ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + /ejs@3.1.6: + resolution: {integrity: sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + jake: 10.8.7 + dev: true + + /ejs@3.1.9: + resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + jake: 10.8.7 + dev: true + /electron-fetch@1.9.1: resolution: {integrity: sha512-M9qw6oUILGVrcENMSRRefE1MbHPIz0h79EKIeJWK9v563aT9Qkh8aEHPO1H5vi970wPirNY+jO9OpFoLiMsMGA==} engines: {node: '>=6'} dependencies: encoding: 0.1.13 - dev: false - /electron-to-chromium@1.4.549: - resolution: {integrity: sha512-gpXfJslSi4hYDkA0mTLEpYKRv9siAgSUgZ+UWyk+J5Cttpd1ThCVwdclzIwQSclz3hYn049+M2fgrP1WpvF8xg==} + /electron-to-chromium@1.4.564: + resolution: {integrity: sha512-bGAx9+teIzL5I4esQwCMtiXtb78Ysc8xOKTPOvmafbJZ4SQ40kDO1ym3yRcGSkfaBtV81fGgHOgPoe6DsmpmkA==} /elkjs@0.8.2: resolution: {integrity: sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==} @@ -18510,7 +18185,6 @@ packages: resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} dependencies: iconv-lite: 0.6.3 - dev: false /end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} @@ -18543,6 +18217,13 @@ packages: graceful-fs: 4.2.11 tapable: 2.2.1 + /enquirer@2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + dev: true + /enquirer@2.4.1: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} @@ -18568,7 +18249,6 @@ packages: /err-code@3.0.1: resolution: {integrity: sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==} - dev: false /errno@0.1.8: resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} @@ -18594,26 +18274,26 @@ packages: accepts: 1.3.8 escape-html: 1.0.3 - /es-abstract@1.22.2: - resolution: {integrity: sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==} + /es-abstract@1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} engines: {node: '>= 0.4'} dependencies: array-buffer-byte-length: 1.0.0 arraybuffer.prototype.slice: 1.0.2 available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - es-set-tostringtag: 2.0.1 + call-bind: 1.0.5 + es-set-tostringtag: 2.0.2 es-to-primitive: 1.2.1 function.prototype.name: 1.1.6 - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 get-symbol-description: 1.0.0 globalthis: 1.0.3 gopd: 1.0.1 - has: 1.0.4 - has-property-descriptors: 1.0.0 + has-property-descriptors: 1.0.1 has-proto: 1.0.1 has-symbols: 1.0.3 - internal-slot: 1.0.5 + hasown: 2.0.0 + internal-slot: 1.0.6 is-array-buffer: 3.0.2 is-callable: 1.2.7 is-negative-zero: 2.0.2 @@ -18622,7 +18302,7 @@ packages: is-string: 1.0.7 is-typed-array: 1.1.12 is-weakref: 1.0.2 - object-inspect: 1.12.3 + object-inspect: 1.13.1 object-keys: 1.1.1 object.assign: 4.1.4 regexp.prototype.flags: 1.5.1 @@ -18636,7 +18316,7 @@ packages: typed-array-byte-offset: 1.0.0 typed-array-length: 1.0.4 unbox-primitive: 1.0.2 - which-typed-array: 1.1.11 + which-typed-array: 1.1.13 dev: true /es-array-method-boxes-properly@1.0.0: @@ -18646,8 +18326,8 @@ packages: /es-get-iterator@1.1.3: resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 has-symbols: 1.0.3 is-arguments: 1.1.1 is-map: 2.0.2 @@ -18661,17 +18341,17 @@ packages: resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} dependencies: asynciterator.prototype: 1.0.0 - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - es-set-tostringtag: 2.0.1 - function-bind: 1.1.1 - get-intrinsic: 1.2.1 + es-abstract: 1.22.3 + es-set-tostringtag: 2.0.2 + function-bind: 1.1.2 + get-intrinsic: 1.2.2 globalthis: 1.0.3 - has-property-descriptors: 1.0.0 + has-property-descriptors: 1.0.1 has-proto: 1.0.1 has-symbols: 1.0.3 - internal-slot: 1.0.5 + internal-slot: 1.0.6 iterator.prototype: 1.1.2 safe-array-concat: 1.0.1 dev: true @@ -18679,19 +18359,19 @@ packages: /es-module-lexer@1.3.1: resolution: {integrity: sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==} - /es-set-tostringtag@2.0.1: - resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + /es-set-tostringtag@2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} engines: {node: '>= 0.4'} dependencies: - get-intrinsic: 1.2.1 - has: 1.0.4 + get-intrinsic: 1.2.2 has-tostringtag: 1.0.0 + hasown: 2.0.0 dev: true - /es-shim-unscopables@1.0.0: - resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + /es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} dependencies: - has: 1.0.4 + hasown: 2.0.0 dev: true /es-to-primitive@1.2.1: @@ -18725,13 +18405,11 @@ packages: /es6-promise@4.2.8: resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} - dev: false /es6-promisify@5.0.0: resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} dependencies: es6-promise: 4.2.8 - dev: false /es6-symbol@3.1.3: resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} @@ -18838,6 +18516,36 @@ packages: '@esbuild/win32-x64': 0.18.20 dev: true + /esbuild@0.19.5: + resolution: {integrity: sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.19.5 + '@esbuild/android-arm64': 0.19.5 + '@esbuild/android-x64': 0.19.5 + '@esbuild/darwin-arm64': 0.19.5 + '@esbuild/darwin-x64': 0.19.5 + '@esbuild/freebsd-arm64': 0.19.5 + '@esbuild/freebsd-x64': 0.19.5 + '@esbuild/linux-arm': 0.19.5 + '@esbuild/linux-arm64': 0.19.5 + '@esbuild/linux-ia32': 0.19.5 + '@esbuild/linux-loong64': 0.19.5 + '@esbuild/linux-mips64el': 0.19.5 + '@esbuild/linux-ppc64': 0.19.5 + '@esbuild/linux-riscv64': 0.19.5 + '@esbuild/linux-s390x': 0.19.5 + '@esbuild/linux-x64': 0.19.5 + '@esbuild/netbsd-x64': 0.19.5 + '@esbuild/openbsd-x64': 0.19.5 + '@esbuild/sunos-x64': 0.19.5 + '@esbuild/win32-arm64': 0.19.5 + '@esbuild/win32-ia32': 0.19.5 + '@esbuild/win32-x64': 0.19.5 + dev: true + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -18901,8 +18609,8 @@ packages: '@typescript-eslint/parser': 5.62.0(eslint@8.19.0)(typescript@5.1.6) eslint: 8.19.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.28.1)(eslint@8.19.0) - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@2.7.1)(eslint@8.19.0) + eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.29.0)(eslint@8.19.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@2.7.1)(eslint@8.19.0) eslint-plugin-jsx-a11y: 6.7.1(eslint@8.19.0) eslint-plugin-react: 7.33.2(eslint@8.19.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.19.0) @@ -18921,13 +18629,13 @@ packages: eslint: 8.19.0 dev: true - /eslint-config-prettier@8.10.0(eslint@8.51.0): + /eslint-config-prettier@8.10.0(eslint@8.52.0): resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.51.0 + eslint: 8.52.0 dev: true /eslint-config-react@1.1.7: @@ -18938,13 +18646,13 @@ packages: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} dependencies: debug: 3.2.7(supports-color@8.1.1) - is-core-module: 2.13.0 + is-core-module: 2.13.1 resolve: 1.22.8 transitivePeerDependencies: - supports-color dev: true - /eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.28.1)(eslint@8.19.0): + /eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.29.0)(eslint@8.19.0): resolution: {integrity: sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==} engines: {node: '>=4'} peerDependencies: @@ -18953,7 +18661,7 @@ packages: dependencies: debug: 4.3.4(supports-color@8.1.1) eslint: 8.19.0 - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@2.7.1)(eslint@8.19.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@2.7.1)(eslint@8.19.0) glob: 7.2.3 is-glob: 4.0.3 resolve: 1.22.8 @@ -18987,13 +18695,13 @@ packages: debug: 3.2.7(supports-color@8.1.1) eslint: 8.19.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.28.1)(eslint@8.19.0) + eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.29.0)(eslint@8.19.0) transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-import@2.28.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@2.7.1)(eslint@8.19.0): - resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==} + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@2.7.1)(eslint@8.19.0): + resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -19012,8 +18720,8 @@ packages: eslint: 8.19.0 eslint-import-resolver-node: 0.3.9 eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@2.7.1)(eslint@8.19.0) - has: 1.0.4 - is-core-module: 2.13.0 + hasown: 2.0.0 + is-core-module: 2.13.1 is-glob: 4.0.3 minimatch: 3.1.2 object.fromentries: 2.0.7 @@ -19033,8 +18741,8 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 dependencies: - '@babel/runtime': 7.23.1 - aria-query: 5.1.3 + '@babel/runtime': 7.23.2 + aria-query: 5.3.0 array-includes: 3.1.7 array.prototype.flatmap: 1.3.2 ast-types-flow: 0.0.7 @@ -19165,18 +18873,19 @@ packages: - supports-color dev: true - /eslint@8.51.0: - resolution: {integrity: sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==} + /eslint@8.52.0: + resolution: {integrity: sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.51.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) '@eslint-community/regexpp': 4.9.1 '@eslint/eslintrc': 2.1.2 - '@eslint/js': 8.51.0 - '@humanwhocodes/config-array': 0.11.11 + '@eslint/js': 8.52.0 + '@humanwhocodes/config-array': 0.11.13 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 @@ -19356,8 +19065,8 @@ packages: /ethereum-cryptography@0.1.3: resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} dependencies: - '@types/pbkdf2': 3.1.0 - '@types/secp256k1': 4.0.4 + '@types/pbkdf2': 3.1.1 + '@types/secp256k1': 4.0.5 blakejs: 1.2.1 browserify-aes: 1.2.0 bs58check: 2.1.2 @@ -19397,12 +19106,12 @@ packages: ethers: ^5.7.2 dependencies: '@ethereum-waffle/chai': 4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(ethers@5.7.2) - '@ethereum-waffle/compiler': 4.0.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(solc@0.8.15)(typechain@8.3.1)(typescript@4.9.5) + '@ethereum-waffle/compiler': 4.0.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(solc@0.8.15)(typechain@8.3.2)(typescript@4.9.5) '@ethereum-waffle/mock-contract': 4.0.4(ethers@5.7.2) '@ethereum-waffle/provider': 4.0.5(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(ethers@5.7.2) ethers: 5.7.2 solc: 0.8.15 - typechain: 8.3.1(typescript@4.9.5) + typechain: 8.3.2(typescript@4.9.5) transitivePeerDependencies: - '@ensdomains/ens' - '@ensdomains/resolver' @@ -19435,7 +19144,7 @@ packages: resolution: {integrity: sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw==} engines: {node: '>=10.0.0'} dependencies: - '@types/bn.js': 5.1.2 + '@types/bn.js': 5.1.3 bn.js: 5.2.1 create-hash: 1.2.0 ethereum-cryptography: 0.1.3 @@ -19446,7 +19155,7 @@ packages: resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} engines: {node: '>=10.0.0'} dependencies: - '@types/bn.js': 5.1.2 + '@types/bn.js': 5.1.3 bn.js: 5.2.1 create-hash: 1.2.0 ethereum-cryptography: 0.1.3 @@ -19519,7 +19228,7 @@ packages: resolution: {integrity: sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==} engines: {node: '>= 0.8'} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 require-like: 0.1.2 dev: false @@ -19712,6 +19421,13 @@ packages: /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + /extension-port-stream@2.1.1: + resolution: {integrity: sha512-qknp5o5rj2J9CRKfVB8KJr+uXQlrojNZzdESUPhKYLXf97TPcGf6qWWKmpsNNtUyOdzFhab1ON0jzouNxHHvow==} + engines: {node: '>=12.0.0'} + dependencies: + webextension-polyfill: 0.10.0 + dev: false + /external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} @@ -19734,7 +19450,7 @@ packages: get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: - '@types/yauzl': 2.10.1 + '@types/yauzl': 2.10.2 transitivePeerDependencies: - supports-color dev: true @@ -19747,7 +19463,6 @@ packages: /eyes@0.1.8: resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} engines: {node: '> 0.1.90'} - dev: false /fast-base64-decode@1.0.0: resolution: {integrity: sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==} @@ -19764,7 +19479,6 @@ packages: /fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - dev: false /fast-glob@3.3.1: resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} @@ -19791,6 +19505,12 @@ packages: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true + /fast-levenshtein@3.0.0: + resolution: {integrity: sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==} + dependencies: + fastest-levenshtein: 1.0.16 + dev: true + /fast-loops@1.1.3: resolution: {integrity: sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==} dev: false @@ -19899,7 +19619,6 @@ packages: dependencies: node-domexception: 1.0.0 web-streams-polyfill: 3.2.1 - dev: false /fets@0.1.5: resolution: {integrity: sha512-mL/ya591WOgCP1yBBPbp8E37nynj8QQF6iQCUVl0aHDL80BZ9SOL4BcKBy0dnKdC+clnnAkMm05KB9hsj4m4jQ==} @@ -19931,7 +19650,7 @@ packages: flat-cache: 3.1.1 dev: true - /file-loader@6.2.0(webpack@5.88.2): + /file-loader@6.2.0(webpack@5.89.0): resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -19939,7 +19658,7 @@ packages: dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: false /file-selector@0.6.0: @@ -19978,6 +19697,12 @@ packages: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} dev: false + /filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + dependencies: + minimatch: 5.1.6 + dev: true + /filename-reserved-regex@2.0.0: resolution: {integrity: sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==} engines: {node: '>=4'} @@ -20237,7 +19962,7 @@ packages: resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} dev: true - /fork-ts-checker-webpack-plugin@6.5.3(typescript@4.9.5)(webpack@5.88.2): + /fork-ts-checker-webpack-plugin@6.5.3(typescript@4.9.5)(webpack@5.89.0): resolution: {integrity: sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==} engines: {node: '>=10', yarn: '>=1.0.0'} peerDependencies: @@ -20252,7 +19977,7 @@ packages: optional: true dependencies: '@babel/code-frame': 7.22.13 - '@types/json-schema': 7.0.13 + '@types/json-schema': 7.0.14 chalk: 4.1.2 chokidar: 3.5.3 cosmiconfig: 6.0.0 @@ -20265,7 +19990,7 @@ packages: semver: 7.5.4 tapable: 1.1.3 typescript: 4.9.5 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: false /form-data@2.3.3: @@ -20277,6 +20002,15 @@ packages: mime-types: 2.1.35 dev: true + /form-data@2.5.1: + resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -20290,9 +20024,8 @@ packages: engines: {node: '>=12.20.0'} dependencies: fetch-blob: 3.2.0 - dev: false - /formik-mui-x-date-pickers@0.0.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.13)(@mui/system@5.14.13)(@mui/x-date-pickers@5.0.20)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3): + /formik-mui-x-date-pickers@0.0.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(@mui/system@5.14.14)(@mui/x-date-pickers@5.0.20)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3): resolution: {integrity: sha512-IxZsY6er+g0eNsucIDHcNs6DLaPDdG14IYx/lS2HSuKnTgV4vGEWpXyGMpkY/vGyh+W3N5U4TrBVu+7eRb5rLA==} peerDependencies: '@emotion/react': '>=11.5.0' @@ -20304,17 +20037,17 @@ packages: react: '>=17.0.2' tiny-warning: '>=1.0.3' dependencies: - '@emotion/react': 11.11.1(@types/react@18.2.28)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.28)(react@18.2.0) - '@mui/material': 5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0) - '@mui/system': 5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.28)(react@18.2.0) - '@mui/x-date-pickers': 5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.13)(@mui/system@5.14.13)(@types/react@18.2.28)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) + '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) + '@mui/material': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) + '@mui/system': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react@18.2.0) + '@mui/x-date-pickers': 5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(@mui/system@5.14.14)(@types/react@18.2.31)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) formik: 2.4.5(react@18.2.0) react: 18.2.0 tiny-warning: 1.0.3 dev: false - /formik-mui@5.0.0-alpha.0(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.13)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3): + /formik-mui@5.0.0-alpha.0(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3): resolution: {integrity: sha512-tcY8B4I3N2UK9ghgVpeBWsXGMDe1y4LVKwI8GiUbLKGB86fI/CN9UMr4FuNo6kzNXvO42LFNmCxdEVzovNCyYQ==} peerDependencies: '@emotion/react': '>=11.5.0' @@ -20324,9 +20057,9 @@ packages: react: '>=17.0.2' tiny-warning: '>=1.0.3' dependencies: - '@emotion/react': 11.11.1(@types/react@18.2.28)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.28)(react@18.2.0) - '@mui/material': 5.14.13(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0) + '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) + '@mui/material': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) formik: 2.4.5(react@18.2.0) react: 18.2.0 tiny-warning: 1.0.3 @@ -20337,7 +20070,7 @@ packages: peerDependencies: react: '>=16.8.0' dependencies: - '@types/hoist-non-react-statics': 3.3.3 + '@types/hoist-non-react-statics': 3.3.4 deepmerge: 2.2.1 hoist-non-react-statics: 3.3.2 lodash: 4.17.21 @@ -20355,8 +20088,8 @@ packages: /fp-ts@1.19.3: resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} - /fraction.js@4.3.6: - resolution: {integrity: sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==} + /fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} dev: false /freeport-promise@2.0.0: @@ -20435,6 +20168,20 @@ packages: jsonfile: 6.1.0 universalify: 2.0.0 + /fs-jetpack@4.3.1: + resolution: {integrity: sha512-dbeOK84F6BiQzk2yqqCVwCPWTxAvVGJ3fMQc6E2wuEohS28mR6yHngbrKuVCK1KHRx/ccByDylqu4H5PCP2urQ==} + dependencies: + minimatch: 3.1.2 + rimraf: 2.7.1 + dev: true + + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: true + /fs-monkey@1.0.5: resolution: {integrity: sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==} @@ -20460,16 +20207,16 @@ packages: requiresBuild: true optional: true - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} /function.prototype.name@1.1.6: resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 + es-abstract: 1.22.3 functions-have-names: 1.2.3 dev: true @@ -20485,7 +20232,7 @@ packages: hasBin: true dependencies: '@trufflesuite/bigint-buffer': 1.1.10 - '@types/bn.js': 5.1.2 + '@types/bn.js': 5.1.3 '@types/lru-cache': 5.1.1 '@types/seedrandom': 3.0.1 emittery: 0.10.0 @@ -20528,17 +20275,16 @@ packages: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} dev: true - /get-intrinsic@1.2.1: - resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} dependencies: - function-bind: 1.1.1 - has: 1.0.4 + function-bind: 1.1.2 has-proto: 1.0.1 has-symbols: 1.0.3 + hasown: 2.0.0 /get-iterator@1.0.2: resolution: {integrity: sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==} - dev: false /get-iterator@2.0.1: resolution: {integrity: sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg==} @@ -20605,8 +20351,8 @@ packages: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 dev: true /get-tsconfig@4.7.2: @@ -20751,6 +20497,16 @@ packages: minimatch: 5.1.6 once: 1.4.0 + /glob@9.3.5: + resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + fs.realpath: 1.0.0 + minimatch: 8.0.4 + minipass: 4.2.8 + path-scurry: 1.10.1 + dev: true + /global-dirs@0.1.1: resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} engines: {node: '>=4'} @@ -20840,6 +20596,7 @@ packages: ignore: 5.2.4 merge2: 1.4.1 slash: 3.0.0 + dev: true /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -20874,10 +20631,48 @@ packages: pinkie-promise: 2.0.1 dev: true + /gluegun@5.1.2(debug@4.3.4): + resolution: {integrity: sha512-Cwx/8S8Z4YQg07a6AFsaGnnnmd8mN17414NcPS3OoDtZRwxgsvwRNJNg69niD6fDa8oNwslCG0xH7rEpRNNE/g==} + hasBin: true + dependencies: + apisauce: 2.1.6(debug@4.3.4) + app-module-path: 2.2.0 + cli-table3: 0.6.0 + colors: 1.4.0 + cosmiconfig: 7.0.1 + cross-spawn: 7.0.3 + ejs: 3.1.6 + enquirer: 2.3.6 + execa: 5.1.1 + fs-jetpack: 4.3.1 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.lowercase: 4.3.0 + lodash.lowerfirst: 4.3.1 + lodash.pad: 4.5.1 + lodash.padend: 4.6.1 + lodash.padstart: 4.6.1 + lodash.repeat: 4.1.0 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.trim: 4.5.1 + lodash.trimend: 4.5.1 + lodash.trimstart: 4.5.1 + lodash.uppercase: 4.3.0 + lodash.upperfirst: 4.3.1 + ora: 4.0.2 + pluralize: 8.0.0 + semver: 7.3.5 + which: 2.0.2 + yargs-parser: 21.1.1 + transitivePeerDependencies: + - debug + dev: true + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 /got@8.3.2: resolution: {integrity: sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==} @@ -20885,7 +20680,7 @@ packages: dependencies: '@sindresorhus/is': 0.7.0 '@types/keyv': 3.1.4 - '@types/responselike': 1.0.1 + '@types/responselike': 1.0.2 cacheable-request: 2.1.4 decompress-response: 3.3.0 duplexer3: 0.1.5 @@ -20911,7 +20706,7 @@ packages: '@sindresorhus/is': 0.14.0 '@szmarczak/http-timer': 1.1.2 '@types/keyv': 3.1.4 - '@types/responselike': 1.0.1 + '@types/responselike': 1.0.2 cacheable-request: 6.1.0 decompress-response: 3.3.0 duplexer3: 0.1.5 @@ -20969,8 +20764,8 @@ packages: dependencies: graphql: 16.8.1 - /graphql-ws@5.14.1(graphql@16.8.1): - resolution: {integrity: sha512-aqkls1espsygP1PfkAuuLIV96IbztQ6EaADse97pw8wRIMT3+AL/OYfS8V2iCRkc0gzckitoDRGCQEdnySggiA==} + /graphql-ws@5.14.2(graphql@16.8.1): + resolution: {integrity: sha512-LycmCwhZ+Op2GlHz4BZDsUYHKRiiUz+3r9wbhBATMETNlORQJAaFlAgTFoeRh6xQoQegwYwIylVD1Qns9/DA3w==} engines: {node: '>=10'} peerDependencies: graphql: ^16.6.0 @@ -21150,7 +20945,7 @@ packages: '@nomicfoundation/ethereumjs-vm': 7.0.0 '@nomicfoundation/solidity-analyzer': 0.1.1 '@sentry/node': 5.30.0 - '@types/bn.js': 5.1.2 + '@types/bn.js': 5.1.3 '@types/lru-cache': 5.1.1 abort-controller: 3.0.0 adm-zip: 0.4.16 @@ -21176,16 +20971,16 @@ packages: mocha: 10.2.0 p-map: 4.0.0 qs: 6.11.2 - raw-body: 2.5.1 + raw-body: 2.5.2 resolve: 1.17.0 semver: 6.3.1 solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 - ts-node: 10.9.1(@types/node@18.15.13)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) tsort: 0.0.1 typescript: 4.9.5 - undici: 5.26.0 + undici: 5.26.5 uuid: 8.3.2 ws: 7.5.9 transitivePeerDependencies: @@ -21220,7 +21015,7 @@ packages: '@nomicfoundation/ethereumjs-vm': 7.0.0 '@nomicfoundation/solidity-analyzer': 0.1.1 '@sentry/node': 5.30.0 - '@types/bn.js': 5.1.2 + '@types/bn.js': 5.1.3 '@types/lru-cache': 5.1.1 abort-controller: 3.0.0 adm-zip: 0.4.16 @@ -21246,7 +21041,7 @@ packages: mocha: 10.2.0 p-map: 4.0.0 qs: 6.11.2 - raw-body: 2.5.1 + raw-body: 2.5.2 resolve: 1.17.0 semver: 6.3.1 solc: 0.7.3(debug@4.3.4) @@ -21254,7 +21049,7 @@ packages: stacktrace-parser: 0.1.10 tsort: 0.0.1 typescript: 5.1.6 - undici: 5.26.0 + undici: 5.26.5 uuid: 8.3.2 ws: 7.5.9 transitivePeerDependencies: @@ -21275,16 +21070,15 @@ packages: /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} - requiresBuild: true /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - /has-property-descriptors@1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + /has-property-descriptors@1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} dependencies: - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 /has-proto@1.0.1: resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} @@ -21318,6 +21112,7 @@ packages: /has@1.0.4: resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} engines: {node: '>= 0.4.0'} + dev: true /hash-base@3.1.0: resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} @@ -21348,10 +21143,16 @@ packages: resolution: {integrity: sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==} dev: false + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + /hast-to-hyperscript@9.0.1: resolution: {integrity: sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 comma-separated-tokens: 1.0.8 property-information: 5.6.0 space-separated-tokens: 1.1.5 @@ -21378,7 +21179,7 @@ packages: /hast-util-raw@6.0.1: resolution: {integrity: sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==} dependencies: - '@types/hast': 2.3.6 + '@types/hast': 2.3.7 hast-util-from-parse5: 6.0.1 hast-util-to-parse5: 6.0.0 html-void-elements: 1.0.5 @@ -21407,7 +21208,7 @@ packages: /hastscript@6.0.0: resolution: {integrity: sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==} dependencies: - '@types/hast': 2.3.6 + '@types/hast': 2.3.7 comma-separated-tokens: 1.0.8 hast-util-parse-selector: 2.2.5 property-information: 5.6.0 @@ -21452,7 +21253,7 @@ packages: /history@4.10.1: resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==} dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 loose-envify: 1.4.0 resolve-pathname: 3.0.0 tiny-invariant: 1.3.1 @@ -21538,7 +21339,7 @@ packages: he: 1.2.0 param-case: 3.0.4 relateurl: 0.2.7 - terser: 5.21.0 + terser: 5.22.0 /html-rewriter-wasm@0.4.1: resolution: {integrity: sha512-lNovG8CMCCmcVB1Q7xggMSf7tqPCijZXaH4gL6iE8BFghdQCbaY5Met9i1x2Ex8m/cZHDUtXK9H6/znKamRP8Q==} @@ -21553,25 +21354,25 @@ packages: resolution: {integrity: sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==} dev: false - /html-webpack-plugin@4.5.2(webpack@5.88.2): + /html-webpack-plugin@4.5.2(webpack@5.89.0): resolution: {integrity: sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==} engines: {node: '>=6.9'} peerDependencies: webpack: ^4.0.0 || ^5.0.0 dependencies: '@types/html-minifier-terser': 5.1.2 - '@types/tapable': 1.0.9 - '@types/webpack': 4.41.34 + '@types/tapable': 1.0.10 + '@types/webpack': 4.41.35 html-minifier-terser: 5.1.1 loader-utils: 1.4.2 lodash: 4.17.21 pretty-error: 2.1.2 tapable: 1.1.3 util.promisify: 1.0.0 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: true - /html-webpack-plugin@5.5.3(webpack@5.88.2): + /html-webpack-plugin@5.5.3(webpack@5.89.0): resolution: {integrity: sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==} engines: {node: '>=10.13.0'} peerDependencies: @@ -21582,7 +21383,7 @@ packages: lodash: 4.17.21 pretty-error: 4.0.0 tapable: 2.2.1 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) /html2canvas@1.4.1: resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==} @@ -21662,7 +21463,7 @@ packages: - supports-color dev: true - /http-proxy-middleware@2.0.6(@types/express@4.17.19)(debug@4.3.4): + /http-proxy-middleware@2.0.6(@types/express@4.17.20)(debug@4.3.4): resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} engines: {node: '>=12.0.0'} peerDependencies: @@ -21671,8 +21472,8 @@ packages: '@types/express': optional: true dependencies: - '@types/express': 4.17.19 - '@types/http-proxy': 1.17.12 + '@types/express': 4.17.20 + '@types/http-proxy': 1.17.13 http-proxy: 1.18.1(debug@4.3.4) is-glob: 4.0.3 is-plain-obj: 3.0.0 @@ -21702,7 +21503,7 @@ packages: dependencies: assert-plus: 1.0.0 jsprim: 1.4.2 - sshpk: 1.17.0 + sshpk: 1.18.0 dev: true /http-signature@1.3.6: @@ -21711,7 +21512,7 @@ packages: dependencies: assert-plus: 1.0.0 jsprim: 2.0.2 - sshpk: 1.17.0 + sshpk: 1.18.0 dev: true /https-proxy-agent@5.0.1: @@ -21753,6 +21554,11 @@ packages: hasBin: true dev: true + /hyperlinker@1.0.0: + resolution: {integrity: sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==} + engines: {node: '>=4'} + dev: true + /hyphenate-style-name@1.0.4: resolution: {integrity: sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==} dev: false @@ -21822,6 +21628,10 @@ packages: resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} engines: {node: '>=0.8.0'} + /immutable@4.2.1: + resolution: {integrity: sha512-7WYV7Q5BTs0nlQm7tl92rDYYoyELLKHoDMBKhrxEoiV4mrfVdRz8hzPiYOzH7yWjzoVEamxRuAqhxL2PLRwZYQ==} + dev: true + /immutable@4.3.4: resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==} @@ -21971,7 +21781,6 @@ packages: interface-store: 2.0.2 nanoid: 3.3.6 uint8arrays: 3.1.1 - dev: false /interface-datastore@7.0.4: resolution: {integrity: sha512-Q8LZS/jfFFHz6XyZazLTAc078SSCoa27ZPBOfobWdpDiFO7FqPA2yskitUJIhaCgxNK8C+/lMBUTBNfVIDvLiw==} @@ -21992,7 +21801,6 @@ packages: /interface-store@2.0.2: resolution: {integrity: sha512-rScRlhDcz6k199EkHqT8NpM87ebN89ICOzILoBHgaG36/WX50N32BnU/kpZgCGPLhARRAWUUX5/cyaIjt7Kipg==} - dev: false /interface-store@3.0.4: resolution: {integrity: sha512-OjHUuGXbH4eXSBx1TF1tTySvjLldPLzRSYYXJwrEQI+XfH5JWYZofr0gVMV4F8XTwC+4V7jomDYkvGRmDSRKqQ==} @@ -22003,12 +21811,12 @@ packages: resolution: {integrity: sha512-SI2co5IAxAybBc9egRM2bXvHOa1RPh5SQQkO6di6t/aX92RbtzP4t8raB0l3GTzQmJADaBbzz8Tfa1QLgfMdGQ==} dev: false - /internal-slot@1.0.5: - resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + /internal-slot@1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} engines: {node: '>= 0.4'} dependencies: - get-intrinsic: 1.2.1 - has: 1.0.4 + get-intrinsic: 1.2.2 + hasown: 2.0.0 side-channel: 1.0.4 dev: true @@ -22051,7 +21859,6 @@ packages: /ip-regex@4.3.0: resolution: {integrity: sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==} engines: {node: '>=8'} - dev: false /ip-regex@5.0.0: resolution: {integrity: sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==} @@ -22206,7 +22013,7 @@ packages: '@libp2p/interface-peer-info': 1.0.10 '@libp2p/interface-pubsub': 3.0.7 '@multiformats/multiaddr': 11.6.1 - '@types/node': 18.15.13 + '@types/node': 18.18.6 interface-datastore: 7.0.4 ipfs-unixfs: 8.0.0 multiformats: 10.0.3 @@ -22226,6 +22033,18 @@ packages: - supports-color dev: false + /ipfs-core-types@0.9.0(node-fetch@3.3.2): + resolution: {integrity: sha512-VJ8vJSHvI1Zm7/SxsZo03T+zzpsg8pkgiIi5hfwSJlsrJ1E2v68QPlnLshGHUSYw89Oxq0IbETYl2pGTFHTWfg==} + deprecated: js-IPFS has been deprecated in favour of Helia - please see /~https://github.com/ipfs/js-ipfs/issues/4336 for details + dependencies: + interface-datastore: 6.1.1 + multiaddr: 10.0.1(node-fetch@3.3.2) + multiformats: 9.9.0 + transitivePeerDependencies: + - node-fetch + - supports-color + dev: true + /ipfs-core-utils@0.12.2(node-fetch@3.3.2): resolution: {integrity: sha512-RfxP3rPhXuqKIUmTAUhmee6fmaV3A7LMnjOUikRKpSyqESz/DR7aGK7tbttMxkZdkSEr0rFXlqbyb0vVwmn0wQ==} deprecated: js-IPFS has been deprecated in favour of Helia - please see /~https://github.com/ipfs/js-ipfs/issues/4336 for details @@ -22256,6 +22075,36 @@ packages: - supports-color dev: false + /ipfs-core-utils@0.13.0(node-fetch@3.3.2): + resolution: {integrity: sha512-HP5EafxU4/dLW3U13CFsgqVO5Ika8N4sRSIb/dTg16NjLOozMH31TXV0Grtu2ZWo1T10ahTzMvrfT5f4mhioXw==} + deprecated: js-IPFS has been deprecated in favour of Helia - please see /~https://github.com/ipfs/js-ipfs/issues/4336 for details + dependencies: + any-signal: 2.1.2 + blob-to-it: 1.0.4 + browser-readablestream-to-it: 1.0.3 + debug: 4.3.4(supports-color@8.1.1) + err-code: 3.0.1 + ipfs-core-types: 0.9.0(node-fetch@3.3.2) + ipfs-unixfs: 6.0.9 + ipfs-utils: 9.0.14 + it-all: 1.0.6 + it-map: 1.0.6 + it-peekable: 1.0.3 + it-to-stream: 1.0.0 + merge-options: 3.0.4 + multiaddr: 10.0.1(node-fetch@3.3.2) + multiaddr-to-uri: 8.0.0(node-fetch@3.3.2) + multiformats: 9.9.0 + nanoid: 3.3.6 + parse-duration: 1.1.0 + timeout-abort-controller: 2.0.0 + uint8arrays: 3.1.1 + transitivePeerDependencies: + - encoding + - node-fetch + - supports-color + dev: true + /ipfs-core-utils@0.17.0: resolution: {integrity: sha512-mZbQ9ZkLGGR988hO0iCsB6FXDb0fS0vYRue07Ia8O3ODdKjZ69Jx7zYoYqpjTQQCgEN6RrX98aCTOw+ifziGvw==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -22370,6 +22219,36 @@ packages: - utf-8-validate dev: false + /ipfs-http-client@55.0.0(node-fetch@3.3.2): + resolution: {integrity: sha512-GpvEs7C7WL9M6fN/kZbjeh4Y8YN7rY8b18tVWZnKxRsVwM25cIFrRI8CwNt3Ugin9yShieI3i9sPyzYGMrLNnQ==} + engines: {node: '>=14.0.0', npm: '>=3.0.0'} + deprecated: js-IPFS has been deprecated in favour of Helia - please see /~https://github.com/ipfs/js-ipfs/issues/4336 for details + dependencies: + '@ipld/dag-cbor': 7.0.3 + '@ipld/dag-json': 8.0.11 + '@ipld/dag-pb': 2.1.18 + abort-controller: 3.0.0 + any-signal: 2.1.2 + debug: 4.3.4(supports-color@8.1.1) + err-code: 3.0.1 + ipfs-core-types: 0.9.0(node-fetch@3.3.2) + ipfs-core-utils: 0.13.0(node-fetch@3.3.2) + ipfs-utils: 9.0.14 + it-first: 1.0.7 + it-last: 1.0.6 + merge-options: 3.0.4 + multiaddr: 10.0.1(node-fetch@3.3.2) + multiformats: 9.9.0 + native-abort-controller: 1.0.4(abort-controller@3.0.0) + parse-duration: 1.1.0 + stream-to-it: 0.2.4 + uint8arrays: 3.1.1 + transitivePeerDependencies: + - encoding + - node-fetch + - supports-color + dev: true + /ipfs-http-client@59.0.0: resolution: {integrity: sha512-cFMU8ykKgxK2/uAw4Hthy2Kd+UuoFBno89DOdUqHYvmilKrmfV5vrYwviVWLYveIpkkaj8FB5x4TBxsiU99y0Q==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -22546,7 +22425,6 @@ packages: dependencies: err-code: 3.0.1 protobufjs: 6.11.4 - dev: false /ipfs-unixfs@8.0.0: resolution: {integrity: sha512-PAHtfyjiFs2PZBbeft5QRyXpVOvZ2zsGqID+zVRla7fjC1zRTqJkrGY9h6dF03ldGv/mSmFlNZh479qPC6aZKg==} @@ -22578,7 +22456,6 @@ packages: stream-to-it: 0.2.4 transitivePeerDependencies: - encoding - dev: false /ipns@0.16.0: resolution: {integrity: sha512-fBYkRjN3/fc6IQujUF4WBEyOXegK715w+wx9IErV6H2B5JXsMnHOBceUKn3L90dj+wJfHs6T+hM/OZiTT6mQCw==} @@ -22642,14 +22519,14 @@ packages: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 has-tostringtag: 1.0.0 /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 is-typed-array: 1.1.12 dev: true @@ -22679,7 +22556,7 @@ packages: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 has-tostringtag: 1.0.0 dev: true @@ -22712,10 +22589,10 @@ packages: ci-info: 3.9.0 dev: true - /is-core-module@2.13.0: - resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} dependencies: - has: 1.0.4 + hasown: 2.0.0 /is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} @@ -22743,7 +22620,6 @@ packages: /is-electron@2.2.2: resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==} - dev: false /is-extendable@0.1.1: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} @@ -22757,7 +22633,7 @@ packages: /is-finalizationregistry@1.0.2: resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 dev: true /is-fullwidth-code-point@1.0.0: @@ -22820,7 +22696,6 @@ packages: engines: {node: '>=8'} dependencies: ip-regex: 4.3.0 - dev: false /is-ipfs@7.0.3: resolution: {integrity: sha512-IwjmN5DYrWQgk75dPX9WOFDbGpStJg6SLMLXXlxwpI3/SnwAIz3PwrdnxB+s2k+RjOTn9ueFIbGWxF2VMUYmLQ==} @@ -22951,13 +22826,13 @@ packages: /is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} dependencies: - '@types/estree': 1.0.2 + '@types/estree': 1.0.3 /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 has-tostringtag: 1.0.0 dev: true @@ -22989,7 +22864,7 @@ packages: /is-shared-array-buffer@1.0.2: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 dev: true /is-stream@1.1.0: @@ -23041,7 +22916,7 @@ packages: resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} engines: {node: '>= 0.4'} dependencies: - which-typed-array: 1.1.11 + which-typed-array: 1.1.13 /is-typedarray@1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} @@ -23076,14 +22951,14 @@ packages: /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 dev: true /is-weakset@2.0.2: resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 dev: true /is-what@4.1.15: @@ -23147,7 +23022,6 @@ packages: /iso-url@1.2.1: resolution: {integrity: sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==} engines: {node: '>=12'} - dev: false /isobject@3.0.1: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} @@ -23171,7 +23045,6 @@ packages: ws: '*' dependencies: ws: 7.5.9 - dev: false /isomorphic-ws@5.0.0(ws@8.12.0): resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} @@ -23192,7 +23065,7 @@ packages: peerDependencies: ws: '*' dependencies: - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) /isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} @@ -23297,7 +23170,6 @@ packages: /it-all@1.0.6: resolution: {integrity: sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A==} - dev: false /it-all@2.0.1: resolution: {integrity: sha512-9UuJcCRZsboz+HBQTNOau80Dw+ryGaHYFP/cPYzFBJBFcfDathMYnhHk4t52en9+fcyDGPTdLB+lFc1wzQIroA==} @@ -23341,7 +23213,6 @@ packages: /it-first@1.0.7: resolution: {integrity: sha512-nvJKZoBpZD/6Rtde6FXqwDqDZGF1sCADmr2Zoc0hZsIvnE449gRFnGctxDf09Bzc/FWnHXAdaHVIetY6lrE0/g==} - dev: false /it-first@2.0.1: resolution: {integrity: sha512-noC1oEQcWZZMUwq7VWxHNLML43dM+5bviZpfmkxkXlvBe60z7AFRqpZSga9uQBo792jKv9otnn1IjA4zwgNARw==} @@ -23369,7 +23240,6 @@ packages: dependencies: '@types/minimatch': 3.0.5 minimatch: 3.1.2 - dev: false /it-handshake@4.1.3: resolution: {integrity: sha512-V6Lt9A9usox9iduOX+edU1Vo94E6v9Lt9dOvg3ubFaw1qf5NCxXLi93Ao4fyCHWDYd8Y+DUhadwNtWVyn7qqLg==} @@ -23384,7 +23254,6 @@ packages: /it-last@1.0.6: resolution: {integrity: sha512-aFGeibeiX/lM4bX3JY0OkVCFkAw8+n9lkukkLNivbJRvNz8lI3YXv5xcqhFUV2lDJiraEK3OXRDbGuevnnR67Q==} - dev: false /it-last@2.0.1: resolution: {integrity: sha512-uVMedYW0wa2Cx0TAmcOCLbfuLLII7+vyURmhKa8Zovpd+aBTMsmINtsta2n364wJ5qsEDBH+akY1sUtAkaYBlg==} @@ -23421,7 +23290,6 @@ packages: /it-map@1.0.6: resolution: {integrity: sha512-XT4/RM6UHIFG9IobGlQPFQUrlEKkU4eBUFG3qhWhfAdh1JfF2x11ShCrKCdmZ0OiZppPfoLuzcfA4cey6q3UAQ==} - dev: false /it-map@2.0.1: resolution: {integrity: sha512-a2GcYDHiAh/eSU628xlvB56LA98luXZnniH2GlD0IdBzf15shEq9rBeb0Rg3o1SWtNILUAwqmQxEXcewGCdvmQ==} @@ -23480,7 +23348,6 @@ packages: /it-peekable@1.0.3: resolution: {integrity: sha512-5+8zemFS+wSfIkSZyf0Zh5kNN+iGyccN02914BY4w/Dj+uoFEoPSvj5vaWn8pNZJNSxzjW0zHRxC3LUb2KWJTQ==} - dev: false /it-peekable@2.0.1: resolution: {integrity: sha512-fJ/YTU9rHRhGJOM2hhQKKEfRM6uKB9r4yGGFLBHqp72ACC8Yi6+7/FhuBAMG8cpN6mLoj9auVX7ZJ3ul6qFpTA==} @@ -23579,7 +23446,6 @@ packages: p-defer: 3.0.0 p-fifo: 1.0.0 readable-stream: 3.6.2 - dev: false /it-ws@5.0.6: resolution: {integrity: sha512-TEEJQaGtkxgP/nGVq8dq48nPT85Afu8kwwvtDFLj4rQLWRhZcb26RWdXLdn9qhXkWPiWbK5H7JWBW1Bebj/SuQ==} @@ -23589,7 +23455,7 @@ packages: iso-url: 1.2.1 it-stream-types: 1.0.5 uint8arrays: 4.0.6 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -23599,7 +23465,7 @@ packages: resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} dependencies: define-properties: 1.2.1 - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 has-symbols: 1.0.3 reflect.getprototypeof: 1.0.4 set-function-name: 2.0.1 @@ -23613,16 +23479,49 @@ packages: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + /jake@10.8.7: + resolution: {integrity: sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.4 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + dev: true + /javascript-natural-sort@0.7.1: resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} dev: true + /jayson@4.0.0: + resolution: {integrity: sha512-v2RNpDCMu45fnLzSk47vx7I+QUaOsox6f5X0CUlabAFwxoP+8MfAY0NQRFwOEYXIxm8Ih5y6OaEa5KYiQMkyAA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + '@types/connect': 3.4.37 + '@types/node': 12.20.55 + '@types/ws': 7.4.7 + JSONStream: 1.3.5 + commander: 2.20.3 + delay: 5.0.0 + es6-promisify: 5.0.0 + eyes: 0.1.8 + isomorphic-ws: 4.0.1(ws@7.5.9) + json-stringify-safe: 5.0.1 + uuid: 8.3.2 + ws: 7.5.9 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + /jayson@4.1.0: resolution: {integrity: sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==} engines: {node: '>=8'} hasBin: true dependencies: - '@types/connect': 3.4.36 + '@types/connect': 3.4.37 '@types/node': 12.20.55 '@types/ws': 7.4.7 JSONStream: 1.3.5 @@ -23655,7 +23554,7 @@ packages: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -23675,7 +23574,7 @@ packages: - babel-plugin-macros - supports-color - /jest-cli@29.7.0(@types/node@18.15.13)(ts-node@10.9.1): + /jest-cli@29.7.0(@types/node@18.18.6)(ts-node@10.9.1): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -23689,10 +23588,10 @@ packages: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@18.15.13)(ts-node@10.9.1) + create-jest: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@18.15.13)(ts-node@10.9.1) + jest-config: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -23702,7 +23601,7 @@ packages: - supports-color - ts-node - /jest-config@29.7.0(@types/node@18.15.13)(ts-node@10.9.1): + /jest-config@29.7.0(@types/node@18.18.6)(ts-node@10.9.1): resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -23717,7 +23616,7 @@ packages: '@babel/core': 7.23.2 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 babel-jest: 29.7.0(@babel/core@7.23.2) chalk: 4.1.2 ci-info: 3.9.0 @@ -23737,7 +23636,7 @@ packages: pretty-format: 29.7.0 slash: 3.0.0 strip-json-comments: 3.1.1 - ts-node: 10.9.1(@types/node@18.15.13)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -23780,7 +23679,7 @@ packages: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 18.15.13 + '@types/node': 18.18.6 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -23797,7 +23696,7 @@ packages: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -23810,7 +23709,7 @@ packages: jest: optional: true dependencies: - jest: 29.7.0(@types/node@18.15.13)(ts-node@10.9.1) + jest: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) jest-diff: 29.7.0 jest-get-type: 29.6.3 dev: true @@ -23824,8 +23723,8 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.7 - '@types/node': 18.15.13 + '@types/graceful-fs': 4.1.8 + '@types/node': 18.18.6 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -23859,7 +23758,7 @@ packages: dependencies: '@babel/code-frame': 7.22.13 '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.1 + '@types/stack-utils': 2.0.2 chalk: 4.1.2 graceful-fs: 4.2.11 micromatch: 4.0.5 @@ -23872,7 +23771,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 jest-util: 29.7.0 /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -23926,7 +23825,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -23956,7 +23855,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -24006,7 +23905,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 18.15.13 + '@types/node': 18.18.6 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -24017,7 +23916,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -24040,7 +23939,7 @@ packages: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.15.13 + '@types/node': 18.18.6 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -24051,7 +23950,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -24059,12 +23958,12 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - /jest@29.7.0(@types/node@18.15.13)(ts-node@10.9.1): + /jest@29.7.0(@types/node@18.18.6)(ts-node@10.9.1): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -24077,7 +23976,7 @@ packages: '@jest/core': 29.7.0(ts-node@10.9.1) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@18.15.13)(ts-node@10.9.1) + jest-cli: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -24127,7 +24026,6 @@ packages: /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - requiresBuild: true /js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} @@ -24218,7 +24116,7 @@ packages: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -24274,6 +24172,15 @@ packages: eth-rpc-errors: 4.0.2 dev: false + /json-rpc-middleware-stream@4.2.3: + resolution: {integrity: sha512-4iFb0yffm5vo3eFKDbQgke9o17XBcLQ2c3sONrXSbcOLzP8LTojqo8hRGVgtJShhm5q4ZDSNq039fAx9o65E1w==} + engines: {node: '>=14.0.0'} + dependencies: + '@metamask/safe-event-emitter': 3.0.0 + json-rpc-engine: 6.1.0 + readable-stream: 2.3.8 + dev: false + /json-rpc-random-id@1.0.1: resolution: {integrity: sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA==} dev: false @@ -24282,8 +24189,8 @@ packages: resolution: {integrity: sha512-h9WqLkTVpBbiaPb5OmeUpz/FBLS/kvIJw4oRCPiEisIu2WjMh+aai0QIY2LoOhRFx5r92taGLcerIrzxKBAP6g==} engines: {node: '>=16'} dependencies: - '@babel/runtime': 7.23.1 - '@types/json-schema': 7.0.13 + '@babel/runtime': 7.23.2 + '@types/json-schema': 7.0.14 ts-algebra: 1.2.2 /json-schema-to-typescript@12.0.0: @@ -24292,8 +24199,8 @@ packages: hasBin: true dependencies: '@bcherny/json-schema-ref-parser': 10.0.5-fork - '@types/json-schema': 7.0.13 - '@types/lodash': 4.14.199 + '@types/json-schema': 7.0.14 + '@types/lodash': 4.14.200 '@types/prettier': 2.7.3 cli-color: 2.0.3 get-stdin: 8.0.0 @@ -24332,7 +24239,6 @@ packages: /json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true - requiresBuild: true dependencies: minimist: 1.2.8 dev: true @@ -24464,6 +24370,13 @@ packages: resolution: {integrity: sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==} dependencies: json-buffer: 3.0.0 + dev: true + + /keyv@3.1.0: + resolution: {integrity: sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==} + dependencies: + json-buffer: 3.0.0 + dev: false /keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -24475,8 +24388,8 @@ packages: resolution: {integrity: sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==} dev: false - /khroma@2.0.0: - resolution: {integrity: sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==} + /khroma@2.1.0: + resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} dev: false /kind-of@6.0.3: @@ -24688,7 +24601,7 @@ packages: resolution: {integrity: sha512-AeLaA+8KIhUhjpXZcs20+Pnf2wIBp+zdSYPD1IgGCF0PlMbTdCvaIqhPzpTSd3+e5k7NZlgpd/BvCOLgQbfm5Q==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} dependencies: - '@achingbrain/nat-port-mapper': 1.0.11 + '@achingbrain/nat-port-mapper': 1.0.12 '@libp2p/connection': 4.0.2 '@libp2p/crypto': 1.0.17 '@libp2p/interface-address-manager': 2.0.5 @@ -24847,7 +24760,7 @@ packages: /lit-html@2.8.0: resolution: {integrity: sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==} dependencies: - '@types/trusted-types': 2.0.4 + '@types/trusted-types': 2.0.5 dev: false /lit@2.7.5: @@ -25008,7 +24921,6 @@ packages: /lodash.isplainobject@4.0.6: resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - requiresBuild: true dev: true /lodash.isstring@4.0.1: @@ -25019,6 +24931,14 @@ packages: resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} dev: true + /lodash.lowercase@4.3.0: + resolution: {integrity: sha512-UcvP1IZYyDKyEL64mmrwoA1AbFu5ahojhTtkOUr1K9dbuxzS9ev8i4TxMMGCqRC9TE8uDaSoufNAXxRPNTseVA==} + dev: true + + /lodash.lowerfirst@4.3.1: + resolution: {integrity: sha512-UUKX7VhP1/JL54NXg2aq/E1Sfnjjes8fNYTNkPU8ZmsaVeBvPHKdbNaN79Re5XRL01u6wbq3j0cbYZj71Fcu5w==} + dev: true + /lodash.map@4.6.0: resolution: {integrity: sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==} dev: true @@ -25031,16 +24951,31 @@ packages: /lodash.mergewith@4.6.2: resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} - requiresBuild: true /lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} dev: true + /lodash.pad@4.5.1: + resolution: {integrity: sha512-mvUHifnLqM+03YNzeTBS1/Gr6JRFjd3rRx88FHWUvamVaT9k2O/kXha3yBSOwB9/DTQrSTLJNHvLBBt2FdX7Mg==} + dev: true + + /lodash.padend@4.6.1: + resolution: {integrity: sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==} + dev: true + + /lodash.padstart@4.6.1: + resolution: {integrity: sha512-sW73O6S8+Tg66eY56DBk85aQzzUJDtpoXFBgELMd5P/SotAguo+1kYO6RuYgXxA4HJH3LFTFPASX6ET6bjfriw==} + dev: true + /lodash.pullall@4.2.0: resolution: {integrity: sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg==} dev: false + /lodash.repeat@4.1.0: + resolution: {integrity: sha512-eWsgQW89IewS95ZOcr15HHCX6FVDxq3f2PNUIng3fyzsPev9imFQxIYdFZ6crl8L56UR6ZlGDLcEb3RZsCSSqw==} + dev: true + /lodash.snakecase@4.1.1: resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} dev: true @@ -25055,6 +24990,18 @@ packages: /lodash.topath@4.5.2: resolution: {integrity: sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==} + /lodash.trim@4.5.1: + resolution: {integrity: sha512-nJAlRl/K+eiOehWKDzoBVrSMhK0K3A3YQsUNXHQa5yIrKBAhsZgSu3KoAFoFT+mEgiyBHddZ0pRk1ITpIp90Wg==} + dev: true + + /lodash.trimend@4.5.1: + resolution: {integrity: sha512-lsD+k73XztDsMBKPKvzHXRKFNMohTjoTKIIo4ADLn5dA65LZ1BqlAvSXhR2rPEC3BgAUQnzMnorqDtqn2z4IHA==} + dev: true + + /lodash.trimstart@4.5.1: + resolution: {integrity: sha512-b/+D6La8tU76L/61/aN0jULWHkT0EeJCmVstPBn/K9MtD2qBW83AsBNrr63dKuWYwVMO7ucv13QNO/Ek/2RKaQ==} + dev: true + /lodash.truncate@4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} dev: true @@ -25066,6 +25013,10 @@ packages: resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==} dev: false + /lodash.uppercase@4.3.0: + resolution: {integrity: sha512-+Nbnxkj7s8K5U8z6KnEYPGUOGp3woZbB7Ecs7v3LkkjLQSm2kP9SKIILitN1ktn2mB/tmM9oSlku06I+/lH7QA==} + dev: true + /lodash.upperfirst@4.3.1: resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} dev: true @@ -25073,6 +25024,13 @@ packages: /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + /log-symbols@3.0.0: + resolution: {integrity: sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==} + engines: {node: '>=8'} + dependencies: + chalk: 2.4.2 + dev: true + /log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} @@ -25116,11 +25074,9 @@ packages: /long@4.0.0: resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} - dev: false /long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} - dev: false /longbits@1.1.0: resolution: {integrity: sha512-22U2exkkYy7sr7nuQJYx2NEZ2kEMsC69+BxM5h8auLvkVIJa+LwAB5mFIExnuW2dFuYXFOWsFMKXjaWiq/htYQ==} @@ -25141,8 +25097,8 @@ packages: dependencies: js-tokens: 4.0.0 - /loupe@2.3.6: - resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + /loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} dependencies: get-func-name: 2.0.2 dev: true @@ -25291,6 +25247,12 @@ packages: hasBin: true dev: true + /matchstick-as@0.6.0: + resolution: {integrity: sha512-E36fWsC1AbCkBFt05VsDDRoFvGSdcZg6oZJrtIe/YDBbuFh8SKbR5FcoqDhNWqSN+F7bN/iS2u8Md0SM+4pUpw==} + dependencies: + wabt: 1.0.24 + dev: true + /mcl-wasm@0.7.9: resolution: {integrity: sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==} engines: {node: '>=8.9.0'} @@ -25317,16 +25279,16 @@ packages: /mdast-util-definitions@5.1.2: resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} dependencies: - '@types/mdast': 3.0.13 - '@types/unist': 2.0.8 + '@types/mdast': 3.0.14 + '@types/unist': 2.0.9 unist-util-visit: 4.1.2 dev: false /mdast-util-from-markdown@1.3.1: resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==} dependencies: - '@types/mdast': 3.0.13 - '@types/unist': 2.0.8 + '@types/mdast': 3.0.14 + '@types/unist': 2.0.9 decode-named-character-reference: 1.0.2 mdast-util-to-string: 3.2.0 micromark: 3.2.0 @@ -25344,8 +25306,8 @@ packages: /mdast-util-to-hast@10.0.1: resolution: {integrity: sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==} dependencies: - '@types/mdast': 3.0.13 - '@types/unist': 2.0.8 + '@types/mdast': 3.0.14 + '@types/unist': 2.0.9 mdast-util-definitions: 4.0.0 mdurl: 1.0.1 unist-builder: 2.0.3 @@ -25357,8 +25319,8 @@ packages: /mdast-util-to-hast@12.3.0: resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==} dependencies: - '@types/hast': 2.3.6 - '@types/mdast': 3.0.13 + '@types/hast': 2.3.7 + '@types/mdast': 3.0.14 mdast-util-definitions: 5.1.2 micromark-util-sanitize-uri: 1.2.0 trim-lines: 3.0.1 @@ -25374,7 +25336,7 @@ packages: /mdast-util-to-string@3.2.0: resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==} dependencies: - '@types/mdast': 3.0.13 + '@types/mdast': 3.0.14 dev: false /mdn-data@2.0.14: @@ -25400,7 +25362,7 @@ packages: /media-query-parser@2.0.2: resolution: {integrity: sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==} dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 dev: false /media-typer@0.3.0: @@ -25457,7 +25419,7 @@ packages: resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} engines: {node: '>=10'} dependencies: - '@types/minimist': 1.2.3 + '@types/minimist': 1.2.4 camelcase-keys: 6.2.2 decamelize-keys: 1.1.1 hard-rejection: 2.1.0 @@ -25474,7 +25436,7 @@ packages: resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==} engines: {node: '>=10'} dependencies: - '@types/minimist': 1.2.3 + '@types/minimist': 1.2.4 camelcase-keys: 6.2.2 decamelize: 1.2.0 decamelize-keys: 1.1.1 @@ -25496,7 +25458,6 @@ packages: engines: {node: '>=10'} dependencies: is-plain-obj: 2.1.0 - dev: false /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -25532,7 +25493,7 @@ packages: dayjs: 1.11.10 dompurify: 2.4.3 elkjs: 0.8.2 - khroma: 2.0.0 + khroma: 2.1.0 lodash-es: 4.17.21 non-layered-tidy-tree-layout: 2.0.2 stylis: 4.3.0 @@ -25541,7 +25502,7 @@ packages: web-worker: 1.2.0 dev: false - /meros@1.3.0(@types/node@18.15.13): + /meros@1.3.0(@types/node@18.18.6): resolution: {integrity: sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==} engines: {node: '>=13'} peerDependencies: @@ -25550,7 +25511,7 @@ packages: '@types/node': optional: true dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} @@ -25642,7 +25603,7 @@ packages: resolution: {integrity: sha512-Orbvg18qXHCrSj1KbaeSDVYRy/gkro2PC7Fy2tDSH1c9RB4aH8tuMOIXnKJE+1SXxBtjWmQ5Yirwkth2DyyEZA==} engines: {node: '>=16'} dependencies: - terser: 5.21.0 + terser: 5.22.0 /metro-minify-uglify@0.76.8: resolution: {integrity: sha512-6l8/bEvtVaTSuhG1FqS0+Mc8lZ3Bl4RI8SeRIifVLC21eeSDp4CEBUWSGjpFyUDfi6R5dXzYaFnSgMNyfxADiQ==} @@ -25686,7 +25647,7 @@ packages: '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.2) '@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.23.2) '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.2) - '@babel/plugin-transform-runtime': 7.22.15(@babel/core@7.23.2) + '@babel/plugin-transform-runtime': 7.23.2(@babel/core@7.23.2) '@babel/plugin-transform-shorthand-properties': 7.22.5(@babel/core@7.23.2) '@babel/plugin-transform-spread': 7.22.5(@babel/core@7.23.2) '@babel/plugin-transform-sticky-regex': 7.22.5(@babel/core@7.23.2) @@ -25720,7 +25681,7 @@ packages: resolution: {integrity: sha512-XKahvB+iuYJSCr3QqCpROli4B4zASAYpkK+j3a0CJmokxCDNbgyI4Fp88uIL6rNaZfN0Mv35S0b99SdFXIfHjg==} engines: {node: '>=16'} dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 react-refresh: 0.4.3 /metro-source-map@0.76.8: @@ -26003,7 +25964,7 @@ packages: /micromark@3.2.0: resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==} dependencies: - '@types/debug': 4.1.9 + '@types/debug': 4.1.10 debug: 4.3.4(supports-color@8.1.1) decode-named-character-reference: 1.0.2 micromark-core-commonmark: 1.1.0 @@ -26092,14 +26053,14 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} - /mini-css-extract-plugin@2.7.6(webpack@5.88.2): + /mini-css-extract-plugin@2.7.6(webpack@5.89.0): resolution: {integrity: sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^5.0.0 dependencies: schema-utils: 4.2.0 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: false /miniflare@2.11.0: @@ -26174,6 +26135,13 @@ packages: brace-expansion: 2.0.1 dev: true + /minimatch@8.0.4: + resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimatch@9.0.3: resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} @@ -26195,10 +26163,35 @@ packages: /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: true + + /minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} + dev: true + + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: true + /minipass@7.0.4: resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} engines: {node: '>=16 || 14 >=14.17'} + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: true + /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -26322,7 +26315,7 @@ packages: '@mswjs/interceptors': 0.17.10 '@open-draft/until': 1.0.3 '@types/cookie': 0.4.1 - '@types/js-levenshtein': 1.1.1 + '@types/js-levenshtein': 1.1.2 chalk: 4.1.2 chokidar: 3.5.3 cookie: 0.4.2 @@ -26351,7 +26344,6 @@ packages: transitivePeerDependencies: - node-fetch - supports-color - dev: false /multiaddr@10.0.1(node-fetch@3.3.2): resolution: {integrity: sha512-G5upNcGzEGuTHkzxezPrrD6CaIHR9uo+7MwqhNVcXTs33IInon4y7nMiGxl2CY5hG7chvYQUQhz5V52/Qe3cbg==} @@ -26366,7 +26358,6 @@ packages: transitivePeerDependencies: - node-fetch - supports-color - dev: false /multicast-dns@7.2.5: resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} @@ -26392,7 +26383,6 @@ packages: /multiformats@9.9.0: resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} - dev: false /murmur-128@0.2.1: resolution: {integrity: sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==} @@ -26480,7 +26470,6 @@ packages: abort-controller: '*' dependencies: abort-controller: 3.0.0 - dev: false /native-fetch@3.0.0(node-fetch@2.7.0): resolution: {integrity: sha512-G3Z7vx0IFb/FQ4JxvtqGABsOTIqRWvgQz6e+erkB+JJD6LrszQtMozEHI4EkmgZQvnGHrpLVzUWk7t4sJCIkVw==} @@ -26488,7 +26477,6 @@ packages: node-fetch: '*' dependencies: node-fetch: 2.7.0 - dev: false /native-fetch@3.0.0(node-fetch@3.3.2): resolution: {integrity: sha512-G3Z7vx0IFb/FQ4JxvtqGABsOTIqRWvgQz6e+erkB+JJD6LrszQtMozEHI4EkmgZQvnGHrpLVzUWk7t4sJCIkVw==} @@ -26496,14 +26484,13 @@ packages: node-fetch: '*' dependencies: node-fetch: 3.3.2 - dev: false - /native-fetch@4.0.2(undici@5.26.0): + /native-fetch@4.0.2(undici@5.26.5): resolution: {integrity: sha512-4QcVlKFtv2EYVS5MBgsGX5+NWKtbDbIECdUXDBGDMAZXq3Jkv9zf+y8iS7Ub8fEdga3GpYeazp9gauNqXHJOCg==} peerDependencies: undici: '*' dependencies: - undici: 5.26.0 + undici: 5.26.5 dev: false /natural-compare-lite@1.4.0: @@ -26513,6 +26500,10 @@ packages: /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + /natural-orderby@2.0.3: + resolution: {integrity: sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==} + dev: true + /negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} @@ -26528,8 +26519,8 @@ packages: /next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - /next@13.5.4(@babel/core@7.23.2)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-+93un5S779gho8y9ASQhb/bTkQF17FNQOtXLKAj3lsNgltEcF0C5PMLLncDmH+8X1EnJH1kbqAERa29nRXqhjA==} + /next@13.5.6(@babel/core@7.23.2)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==} engines: {node: '>=16.14.0'} hasBin: true peerDependencies: @@ -26543,25 +26534,25 @@ packages: sass: optional: true dependencies: - '@next/env': 13.5.4 + '@next/env': 13.5.6 '@swc/helpers': 0.5.2 busboy: 1.6.0 - caniuse-lite: 1.0.30001547 + caniuse-lite: 1.0.30001553 postcss: 8.4.31 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) styled-jsx: 5.1.1(@babel/core@7.23.2)(react@18.2.0) watchpack: 2.4.0 optionalDependencies: - '@next/swc-darwin-arm64': 13.5.4 - '@next/swc-darwin-x64': 13.5.4 - '@next/swc-linux-arm64-gnu': 13.5.4 - '@next/swc-linux-arm64-musl': 13.5.4 - '@next/swc-linux-x64-gnu': 13.5.4 - '@next/swc-linux-x64-musl': 13.5.4 - '@next/swc-win32-arm64-msvc': 13.5.4 - '@next/swc-win32-ia32-msvc': 13.5.4 - '@next/swc-win32-x64-msvc': 13.5.4 + '@next/swc-darwin-arm64': 13.5.6 + '@next/swc-darwin-x64': 13.5.6 + '@next/swc-linux-arm64-gnu': 13.5.6 + '@next/swc-linux-arm64-musl': 13.5.6 + '@next/swc-linux-x64-gnu': 13.5.6 + '@next/swc-linux-x64-musl': 13.5.6 + '@next/swc-win32-arm64-msvc': 13.5.6 + '@next/swc-win32-ia32-msvc': 13.5.6 + '@next/swc-win32-x64-msvc': 13.5.6 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -26589,8 +26580,8 @@ packages: - supports-color dev: false - /nise@5.1.4: - resolution: {integrity: sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==} + /nise@5.1.5: + resolution: {integrity: sha512-VJuPIfUFaXNRzETTQEEItTOP8Y171ijr+JLq42wHes3DiryR8vT+1TXQW/Rx8JNUhyYYWyIvjXTU6dOhJcs9Nw==} dependencies: '@sinonjs/commons': 2.0.0 '@sinonjs/fake-timers': 10.3.0 @@ -26624,7 +26615,6 @@ packages: /node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} - dev: false /node-emoji@1.11.0: resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} @@ -26649,7 +26639,6 @@ packages: data-uri-to-buffer: 4.0.1 fetch-blob: 3.2.0 formdata-polyfill: 4.0.10 - dev: false /node-forge@1.3.1: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} @@ -26724,7 +26713,7 @@ packages: engines: {node: '>=10'} dependencies: hosted-git-info: 4.1.0 - is-core-module: 2.13.0 + is-core-module: 2.13.1 semver: 7.5.4 validate-npm-package-license: 3.0.4 @@ -26866,11 +26855,14 @@ packages: /object-inspect@1.12.3: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + /object-is@1.1.5: resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 dev: true @@ -26878,11 +26870,16 @@ packages: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} + /object-treeify@1.1.33: + resolution: {integrity: sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==} + engines: {node: '>= 10'} + dev: true + /object.assign@4.1.4: resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 @@ -26891,18 +26888,18 @@ packages: resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 + es-abstract: 1.22.3 dev: true /object.fromentries@2.0.7: resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 + es-abstract: 1.22.3 dev: true /object.getownpropertydescriptors@2.1.7: @@ -26910,35 +26907,35 @@ packages: engines: {node: '>= 0.8'} dependencies: array.prototype.reduce: 1.0.6 - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 + es-abstract: 1.22.3 safe-array-concat: 1.0.1 dev: true /object.groupby@1.0.1: resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - get-intrinsic: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 dev: true /object.hasown@1.1.3: resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==} dependencies: define-properties: 1.2.1 - es-abstract: 1.22.2 + es-abstract: 1.22.3 dev: true /object.values@1.1.7: resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 + es-abstract: 1.22.3 dev: true /obliterator@2.0.4: @@ -27050,6 +27047,19 @@ packages: type-check: 0.4.0 dev: true + /ora@4.0.2: + resolution: {integrity: sha512-YUOZbamht5mfLxPmk4M35CD/5DuOkAacxlEUbStVXpBAt4fyhBf+vZHI/HRkI++QUp3sNoeA2Gw4C+hi4eGSig==} + engines: {node: '>=8'} + dependencies: + chalk: 2.4.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.1 + is-interactive: 1.0.0 + log-symbols: 3.0.0 + strip-ansi: 5.2.0 + wcwidth: 1.0.1 + dev: true + /ora@5.4.1: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} @@ -27109,7 +27119,6 @@ packages: /p-defer@3.0.0: resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==} engines: {node: '>=8'} - dev: false /p-defer@4.0.0: resolution: {integrity: sha512-Vb3QRvQ0Y5XnF40ZUWW7JfLogicVh/EnA5gBIvKDJoYpeI82+1E3AlB9yOcKFS0AhHrWVnAQO39fbR0G99IVEQ==} @@ -27135,7 +27144,6 @@ packages: dependencies: fast-fifo: 1.3.2 p-defer: 3.0.0 - dev: false /p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} @@ -27326,7 +27334,6 @@ packages: /parse-duration@1.1.0: resolution: {integrity: sha512-z6t9dvSJYaPoQq7quMzdEagSFtpGu+utzHqqxmpVWNNZRIXnvqyCvn9XsTdh7c/w0Bqmdz3RB3YnRaKtpRtEXQ==} - dev: false /parse-entities@2.0.0: resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} @@ -27418,6 +27425,13 @@ packages: resolution: {integrity: sha512-BSExi0rRnCHReJys6NocaK+cfTXNinAegfWBvr0JD3hiaEG7Nuc7r0CIdOJunXrs8gU/sbHQ9dxVAtiVQisjmg==} engines: {node: '>=8'} + /password-prompt@1.1.3: + resolution: {integrity: sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw==} + dependencies: + ansi-escapes: 4.3.2 + cross-spawn: 7.0.3 + dev: true + /path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} @@ -27674,18 +27688,18 @@ packages: resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} dev: false - /playwright-core@1.38.1: - resolution: {integrity: sha512-tQqNFUKa3OfMf4b2jQ7aGLB8o9bS3bOY0yMEtldtC2+spf8QXG9zvXLTXUeRsoNuxEYMgLYR+NXfAa1rjKRcrg==} + /playwright-core@1.39.0: + resolution: {integrity: sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw==} engines: {node: '>=16'} hasBin: true dev: true - /playwright@1.38.1: - resolution: {integrity: sha512-oRMSJmZrOu1FP5iu3UrCx8JEFRIMxLDM0c/3o4bpzU5Tz97BypefWf7TuTNPWeCe279TPal5RtPPZ+9lW/Qkow==} + /playwright@1.39.0: + resolution: {integrity: sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw==} engines: {node: '>=16'} hasBin: true dependencies: - playwright-core: 1.38.1 + playwright-core: 1.39.0 optionalDependencies: fsevents: 2.3.2 dev: true @@ -27780,7 +27794,7 @@ packages: postcss-selector-parser: 6.0.13 dev: false - /postcss-loader@7.3.3(postcss@8.4.31)(typescript@4.9.5)(webpack@5.88.2): + /postcss-loader@7.3.3(postcss@8.4.31)(typescript@4.9.5)(webpack@5.89.0): resolution: {integrity: sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -27791,7 +27805,7 @@ packages: jiti: 1.20.0 postcss: 8.4.31 semver: 7.5.4 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - typescript dev: false @@ -28146,6 +28160,12 @@ packages: solidity-comments-extractor: 0.0.7 dev: true + /prettier@1.19.1: + resolution: {integrity: sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==} + engines: {node: '>=4'} + hasBin: true + dev: true + /prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} @@ -28207,8 +28227,8 @@ packages: engines: {node: '>=4'} dev: false - /primereact@9.6.2(@types/react@18.2.28)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-wc7bvhR+9TiWkHADp02R10lnLbtmXiJ0Pdix8jgVh9HdHMaT2tbA6zPuhaRvA1PVT49hvrDXRCL9QB6YtaCi3w==} + /primereact@9.6.3(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-E1Apj4zHeEqFuNR43PFmcpYO51V17PDaVuZmYggEUxZHUo7XWoqkOGg7896SRRMDMBQcO3+HXdJQXi6DOWRV1g==} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 react: ^17.0.0 || ^18.0.0 @@ -28217,8 +28237,8 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.28 - '@types/react-transition-group': 4.4.7 + '@types/react': 18.2.31 + '@types/react-transition-group': 4.4.8 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) @@ -28309,8 +28329,8 @@ packages: retry: 0.12.0 signal-exit: 3.0.7 - /property-expr@2.0.5: - resolution: {integrity: sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==} + /property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} dev: false /property-information@5.6.0: @@ -28339,9 +28359,8 @@ packages: '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 '@types/long': 4.0.2 - '@types/node': 18.15.13 + '@types/node': 18.18.6 long: 4.0.0 - dev: false /protobufjs@7.2.5: resolution: {integrity: sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==} @@ -28358,7 +28377,7 @@ packages: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 18.15.13 + '@types/node': 18.18.6 long: 5.2.3 dev: false @@ -28372,13 +28391,11 @@ packages: uint8arraylist: 2.4.3 dev: false - /protons-runtime@5.0.2(uint8arraylist@2.4.3): - resolution: {integrity: sha512-eKppVrIS5dDh+Y61Yj4bDEOs2sQLQbQGIhr7EBiybPQhIMGBynzVXlYILPWl3Td1GDadobc8qevh5D+JwfG9bw==} - peerDependencies: - uint8arraylist: ^2.3.2 + /protons-runtime@5.1.0: + resolution: {integrity: sha512-9zUaikdZj2u9Z/lFKH+qmtewvQdB1fIKTyN5Iytpdlt0rsHrfw8a14CqXKMWY4ow25HyGuu4D8+7wUbjmI/sdA==} dependencies: - protobufjs: 7.2.5 uint8arraylist: 2.4.3 + uint8arrays: 4.0.6 dev: false /proxy-addr@2.0.7: @@ -28407,6 +28424,13 @@ packages: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: true + /pump@1.0.3: + resolution: {integrity: sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + /pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} dependencies: @@ -28531,7 +28555,6 @@ packages: /querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - requiresBuild: true dev: true /queue-microtask@1.2.3: @@ -28607,6 +28630,15 @@ packages: iconv-lite: 0.4.24 unpipe: 1.0.0 + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + /rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -28626,7 +28658,7 @@ packages: pure-color: 1.3.0 dev: false - /react-dev-utils@12.0.1(typescript@4.9.5)(webpack@5.88.2): + /react-dev-utils@12.0.1(typescript@4.9.5)(webpack@5.89.0): resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} engines: {node: '>=14'} peerDependencies: @@ -28645,9 +28677,9 @@ packages: escape-string-regexp: 4.0.0 filesize: 8.0.7 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(typescript@4.9.5)(webpack@5.88.2) + fork-ts-checker-webpack-plugin: 6.5.3(typescript@4.9.5)(webpack@5.89.0) global-modules: 2.0.0 - globby: 11.0.4 + globby: 11.1.0 gzip-size: 6.0.0 immer: 9.0.21 is-root: 2.1.0 @@ -28661,7 +28693,7 @@ packages: strip-ansi: 6.0.1 text-table: 0.2.0 typescript: 4.9.5 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - eslint - supports-color @@ -28715,7 +28747,7 @@ packages: react: ^16.6.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 invariant: 2.2.4 prop-types: 15.8.1 react: 18.2.0 @@ -28753,28 +28785,28 @@ packages: resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} dev: false - /react-loadable-ssr-addon-v5-slorber@1.0.1(@docusaurus/react-loadable@5.5.2)(webpack@5.88.2): + /react-loadable-ssr-addon-v5-slorber@1.0.1(@docusaurus/react-loadable@5.5.2)(webpack@5.89.0): resolution: {integrity: sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==} engines: {node: '>=10.13.0'} peerDependencies: react-loadable: '*' webpack: '>=4.41.1 || 5.x' dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 react-loadable: /@docusaurus/react-loadable@5.5.2(react@18.2.0) - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: false - /react-markdown@8.0.7(@types/react@18.2.28)(react@18.2.0): + /react-markdown@8.0.7(@types/react@18.2.31)(react@18.2.0): resolution: {integrity: sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==} peerDependencies: '@types/react': '>=16' react: '>=16' dependencies: - '@types/hast': 2.3.6 - '@types/prop-types': 15.7.8 - '@types/react': 18.2.28 - '@types/unist': 2.0.8 + '@types/hast': 2.3.7 + '@types/prop-types': 15.7.9 + '@types/react': 18.2.31 + '@types/unist': 2.0.9 comma-separated-tokens: 2.0.3 hast-util-whitespace: 2.0.1 prop-types: 15.8.1 @@ -28784,7 +28816,7 @@ packages: remark-parse: 10.0.2 remark-rehype: 10.1.0 space-separated-tokens: 2.0.2 - style-to-object: 0.4.2 + style-to-object: 0.4.4 unified: 10.1.2 unist-util-visit: 4.1.2 vfile: 5.3.7 @@ -28796,9 +28828,8 @@ packages: resolution: {integrity: sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==} dependencies: p-defer: 3.0.0 - dev: false - /react-native-fs@2.20.0(react-native@0.72.5): + /react-native-fs@2.20.0(react-native@0.72.6): resolution: {integrity: sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==} peerDependencies: react-native: '*' @@ -28808,14 +28839,14 @@ packages: optional: true dependencies: base-64: 0.1.0 - react-native: 0.72.5(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(react@18.2.0) + react-native: 0.72.6(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(react@18.2.0) utf8: 3.0.0 /react-native-path@0.0.5: resolution: {integrity: sha512-WJr256xBquk7X2O83QYWKqgLg43Zg3SrgjPc/kr0gCD2LoXA+2L72BW4cmstH12GbGeutqs/eXk3jgDQ2iCSvQ==} - /react-native@0.72.5(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(react@18.2.0): - resolution: {integrity: sha512-oIewslu5DBwOmo7x5rdzZlZXCqDIna0R4dUwVpfmVteORYLr4yaZo5wQnMeR+H7x54GaMhmgeqp0ZpULtulJFg==} + /react-native@0.72.6(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(react@18.2.0): + resolution: {integrity: sha512-RafPY2gM7mcrFySS8TL8x+TIO3q7oAlHpzEmC7Im6pmXni6n1AuufGaVh0Narbr1daxstw7yW7T9BKW5dpVc2A==} engines: {node: '>=16'} hasBin: true peerDependencies: @@ -28830,7 +28861,7 @@ packages: '@react-native/gradle-plugin': 0.72.11 '@react-native/js-polyfills': 0.72.1 '@react-native/normalize-colors': 0.72.0 - '@react-native/virtualized-lists': 0.72.8(react-native@0.72.5) + '@react-native/virtualized-lists': 0.72.8(react-native@0.72.6) abort-controller: 3.0.0 anser: 1.4.10 base64-js: 1.5.1 @@ -28870,7 +28901,7 @@ packages: resolution: {integrity: sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA==} engines: {node: '>=0.10.0'} - /react-remove-scroll-bar@2.3.4(@types/react@18.2.28)(react@18.2.0): + /react-remove-scroll-bar@2.3.4(@types/react@18.2.31)(react@18.2.0): resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==} engines: {node: '>=10'} peerDependencies: @@ -28880,13 +28911,13 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 react: 18.2.0 - react-style-singleton: 2.2.1(@types/react@18.2.28)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.2.31)(react@18.2.0) tslib: 2.6.2 dev: false - /react-remove-scroll@2.5.4(@types/react@18.2.28)(react@18.2.0): + /react-remove-scroll@2.5.4(@types/react@18.2.31)(react@18.2.0): resolution: {integrity: sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==} engines: {node: '>=10'} peerDependencies: @@ -28896,13 +28927,13 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 react: 18.2.0 - react-remove-scroll-bar: 2.3.4(@types/react@18.2.28)(react@18.2.0) - react-style-singleton: 2.2.1(@types/react@18.2.28)(react@18.2.0) + react-remove-scroll-bar: 2.3.4(@types/react@18.2.31)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.2.31)(react@18.2.0) tslib: 2.6.2 - use-callback-ref: 1.3.0(@types/react@18.2.28)(react@18.2.0) - use-sidecar: 1.1.2(@types/react@18.2.28)(react@18.2.0) + use-callback-ref: 1.3.0(@types/react@18.2.31)(react@18.2.0) + use-sidecar: 1.1.2(@types/react@18.2.31)(react@18.2.0) dev: false /react-router-config@5.1.1(react-router@5.3.4)(react@18.2.0): @@ -28911,7 +28942,7 @@ packages: react: '>=15' react-router: '>=5' dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 react: 18.2.0 react-router: 5.3.4(react@18.2.0) dev: false @@ -28921,7 +28952,7 @@ packages: peerDependencies: react: '>=15' dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 history: 4.10.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -28936,7 +28967,7 @@ packages: peerDependencies: react: '>=15' dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 history: 4.10.1 hoist-non-react-statics: 3.3.2 loose-envify: 1.4.0 @@ -28957,7 +28988,7 @@ packages: react: 18.2.0 react-is: 18.2.0 - /react-style-singleton@2.2.1(@types/react@18.2.28)(react@18.2.0): + /react-style-singleton@2.2.1(@types/react@18.2.31)(react@18.2.0): resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} peerDependencies: @@ -28967,7 +28998,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 get-nonce: 1.0.1 invariant: 2.2.4 react: 18.2.0 @@ -28980,7 +29011,7 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 react: 18.2.0 use-composed-ref: 1.3.0(react@18.2.0) use-latest: 1.2.1(react@18.2.0) @@ -29005,7 +29036,7 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -29091,7 +29122,7 @@ packages: resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} engines: {node: '>=8'} dependencies: - '@types/normalize-package-data': 2.4.2 + '@types/normalize-package-data': 2.4.3 normalize-package-data: 2.5.0 parse-json: 5.2.0 type-fest: 0.6.0 @@ -29166,7 +29197,6 @@ packages: resolution: {integrity: sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A==} dependencies: ms: 2.1.3 - dev: false /rechoir@0.6.2: resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} @@ -29193,6 +29223,12 @@ packages: indent-string: 4.0.0 strip-indent: 3.0.0 + /redeyed@2.1.1: + resolution: {integrity: sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==} + dependencies: + esprima: 4.0.1 + dev: true + /reduce-flatten@2.0.0: resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} engines: {node: '>=6'} @@ -29201,10 +29237,10 @@ packages: resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - get-intrinsic: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 globalthis: 1.0.3 which-builtin-type: 1.1.3 dev: true @@ -29231,13 +29267,13 @@ packages: /regenerator-transform@0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 /regexp.prototype.flags@1.5.1: resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 set-function-name: 2.0.1 dev: true @@ -29299,7 +29335,7 @@ packages: /relay-runtime@12.0.0: resolution: {integrity: sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==} dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 fbjs: 3.0.5 invariant: 2.2.4 transitivePeerDependencies: @@ -29342,7 +29378,7 @@ packages: /remark-parse@10.0.2: resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==} dependencies: - '@types/mdast': 3.0.13 + '@types/mdast': 3.0.14 mdast-util-from-markdown: 1.3.1 unified: 10.1.2 transitivePeerDependencies: @@ -29373,8 +29409,8 @@ packages: /remark-rehype@10.1.0: resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} dependencies: - '@types/hast': 2.3.6 - '@types/mdast': 3.0.13 + '@types/hast': 2.3.7 + '@types/mdast': 3.0.14 mdast-util-to-hast: 12.3.0 unified: 10.1.2 dev: false @@ -29489,7 +29525,6 @@ packages: /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - requiresBuild: true /resize-observer-polyfill@1.5.1: resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} @@ -29553,7 +29588,7 @@ packages: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true dependencies: - is-core-module: 2.13.0 + is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -29561,7 +29596,7 @@ packages: resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} hasBin: true dependencies: - is-core-module: 2.13.0 + is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true @@ -29597,7 +29632,6 @@ packages: /retimer@3.0.0: resolution: {integrity: sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA==} - dev: false /retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} @@ -29742,7 +29776,7 @@ packages: - supports-color dev: true - /rollup-plugin-esbuild@6.1.0(esbuild@0.18.20)(rollup@4.1.4): + /rollup-plugin-esbuild@6.1.0(esbuild@0.19.5)(rollup@4.1.4): resolution: {integrity: sha512-HPpXU65V8bSpW8eSYPahtUJaJHmbxJGybuf/M8B3bz/6i11YaYHlNNJIQ38gSEV0FyohQOgVxJ2YMEEZtEmwvA==} engines: {node: '>=14.18.0'} peerDependencies: @@ -29752,7 +29786,7 @@ packages: '@rollup/pluginutils': 5.0.5(rollup@4.1.4) debug: 4.3.4(supports-color@8.1.1) es-module-lexer: 1.3.1 - esbuild: 0.18.20 + esbuild: 0.19.5 get-tsconfig: 4.7.2 rollup: 4.1.4 transitivePeerDependencies: @@ -29816,22 +29850,22 @@ packages: fsevents: 2.3.3 dev: true - /rpc-websockets@7.6.0: - resolution: {integrity: sha512-Jgcs8q6t8Go98dEulww1x7RysgTkzpCMelVxZW4hvuyFtOGpeUz9prpr2KjUa/usqxgFCd9Tu3+yhHEP9GVmiQ==} + /rpc-websockets@7.6.1: + resolution: {integrity: sha512-MmRGaJJvxTHSRxYPjJJqcj2zWnCetw7YbYbKlD0Yc7qVw6PsZhRJg1MI3mpWlpBs+4zO+urlNfLl9zLsdOD/gA==} dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 eventemitter3: 4.0.7 uuid: 8.3.2 - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) optionalDependencies: - bufferutil: 4.0.7 + bufferutil: 4.0.8 utf-8-validate: 5.0.10 dev: false /rtl-css-js@1.16.1: resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==} dependencies: - '@babel/runtime': 7.23.1 + '@babel/runtime': 7.23.2 dev: false /rtl-detect@1.0.4: @@ -29893,8 +29927,8 @@ packages: resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} engines: {node: '>=0.4'} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 has-symbols: 1.0.3 isarray: 2.0.5 dev: true @@ -29912,8 +29946,8 @@ packages: /safe-regex-test@1.0.0: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 is-regex: 1.1.4 dev: true @@ -29980,7 +30014,7 @@ packages: resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==} engines: {node: '>= 8.9.0'} dependencies: - '@types/json-schema': 7.0.13 + '@types/json-schema': 7.0.14 ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) dev: false @@ -29989,7 +30023,7 @@ packages: resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==} engines: {node: '>= 8.9.0'} dependencies: - '@types/json-schema': 7.0.13 + '@types/json-schema': 7.0.14 ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) dev: false @@ -29998,7 +30032,7 @@ packages: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/json-schema': 7.0.13 + '@types/json-schema': 7.0.14 ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) @@ -30006,7 +30040,7 @@ packages: resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} engines: {node: '>= 12.13.0'} dependencies: - '@types/json-schema': 7.0.13 + '@types/json-schema': 7.0.14 ajv: 8.12.0 ajv-formats: 2.1.1(ajv@8.12.0) ajv-keywords: 5.1.0(ajv@8.12.0) @@ -30019,8 +30053,8 @@ packages: /scrypt-js@3.0.1: resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} - /search-insights@2.8.3: - resolution: {integrity: sha512-W9rZfQ9XEfF0O6ntgQOTI7Txc8nkZrO4eJ/pTHK0Br6wWND2sPGPoWg+yGhdIW7wMbLqk8dc23IyEtLlNGpeNw==} + /search-insights@2.9.0: + resolution: {integrity: sha512-bkWW9nIHOFkLwjQ1xqVaMbjjO5vhP26ERsH9Y3pKr8imthofEFIxlnOabkmGcw6ksRj9jWidcI65vvjJH/nTGg==} dev: false /secp256k1@4.0.3: @@ -30084,6 +30118,22 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true + /semver@7.3.5: + resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /semver@7.4.0: + resolution: {integrity: sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + /semver@7.5.4: resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} @@ -30205,13 +30255,22 @@ packages: resolution: {integrity: sha512-29fhAwuZlLcuBnW/EwxvLcg2D3ELX+VBDNhnavs3YYkab72qmrcSeQNVdzl8EcPPahGQXhBM6MKdPLCQGMDakw==} dev: false + /set-function-length@1.1.1: + resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + /set-function-name@2.0.1: resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} engines: {node: '>= 0.4'} dependencies: - define-data-property: 1.1.0 + define-data-property: 1.1.1 functions-have-names: 1.2.3 - has-property-descriptors: 1.0.0 + has-property-descriptors: 1.0.1 dev: true /set-harmonic-interval@1.0.1: @@ -30294,9 +30353,9 @@ packages: /side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - object-inspect: 1.12.3 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 /siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -30314,12 +30373,13 @@ packages: /sinon@15.2.0: resolution: {integrity: sha512-nPS85arNqwBXaIsFCkolHjGIkFo+Oxu9vbgmBJizLAhqe6P2o3Qmj3KCUoRkfhHtvgDhZdWD3risLHAUJ8npjw==} + deprecated: 16.1.1 dependencies: '@sinonjs/commons': 3.0.0 '@sinonjs/fake-timers': 10.3.0 '@sinonjs/samsam': 8.0.0 diff: 5.1.0 - nise: 5.1.4 + nise: 5.1.5 supports-color: 7.2.0 dev: true @@ -30341,7 +30401,7 @@ packages: hasBin: true dependencies: '@types/node': 17.0.45 - '@types/sax': 1.2.5 + '@types/sax': 1.2.6 arg: 5.0.2 sax: 1.3.0 dev: false @@ -30544,7 +30604,7 @@ packages: sc-istanbul: 0.4.6 semver: 7.5.4 shelljs: 0.8.5 - web3-utils: 1.10.2 + web3-utils: 1.10.3 transitivePeerDependencies: - supports-color dev: true @@ -30700,14 +30760,18 @@ packages: transitivePeerDependencies: - supports-color - /speed-measure-webpack-plugin@1.4.2(webpack@5.88.2): + /speed-measure-webpack-plugin@1.4.2(webpack@5.89.0): resolution: {integrity: sha512-AtVzD0bnIy2/B0fWqJpJgmhcrfWFhBlduzSo0uwplr/QvB33ZNZj2NEth3NONgdnZJqicK0W0mSxnLSbsVCDbw==} engines: {node: '>=6.0.0'} peerDependencies: webpack: ^1 || ^2 || ^3 || ^4 || ^5 dependencies: chalk: 4.1.2 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) + dev: true + + /split-ca@1.0.1: + resolution: {integrity: sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==} dev: true /split-on-first@1.1.0: @@ -30743,8 +30807,8 @@ packages: engines: {node: '>=6.0.0'} dev: true - /sshpk@1.17.0: - resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==} + /sshpk@1.18.0: + resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} engines: {node: '>=0.10.0'} hasBin: true dependencies: @@ -30827,7 +30891,7 @@ packages: resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} engines: {node: '>= 0.4'} dependencies: - internal-slot: 1.0.5 + internal-slot: 1.0.6 dev: true /stream-browserify@3.0.0: @@ -30845,7 +30909,6 @@ packages: resolution: {integrity: sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ==} dependencies: get-iterator: 1.0.2 - dev: false /streaming-iterables@6.2.0: resolution: {integrity: sha512-3AYC8oB60WyD1ic7uHmN/vm2oRGzRnQ3XFBl/bFMDi1q1+nc5/vjMmiE4vroIya3jG59t87VpyAj/iXYxyw9AA==} @@ -30932,12 +30995,12 @@ packages: /string.prototype.matchall@4.0.10: resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 - get-intrinsic: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 has-symbols: 1.0.3 - internal-slot: 1.0.5 + internal-slot: 1.0.6 regexp.prototype.flags: 1.5.1 set-function-name: 2.0.1 side-channel: 1.0.4 @@ -30947,25 +31010,25 @@ packages: resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 + es-abstract: 1.22.3 dev: true /string.prototype.trimend@1.0.7: resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 + es-abstract: 1.22.3 dev: true /string.prototype.trimstart@1.0.7: resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 define-properties: 1.2.1 - es-abstract: 1.22.2 + es-abstract: 1.22.3 dev: true /string_decoder@0.10.31: @@ -31100,8 +31163,8 @@ packages: inline-style-parser: 0.1.1 dev: false - /style-to-object@0.4.2: - resolution: {integrity: sha512-1JGpfPB3lo42ZX8cuPrheZbfQ6kqPPnPHlKMyeRYtfKD+0jG+QsXgXN57O/dvJlzlB2elI6dGmrPnl5VPQFPaA==} + /style-to-object@0.4.4: + resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} dependencies: inline-style-parser: 0.1.1 dev: false @@ -31172,7 +31235,6 @@ packages: /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} - requiresBuild: true dependencies: has-flag: 3.0.0 @@ -31188,6 +31250,14 @@ packages: dependencies: has-flag: 4.0.0 + /supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + dev: true + /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -31275,6 +31345,15 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + /tar-fs@1.16.3: + resolution: {integrity: sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==} + dependencies: + chownr: 1.1.4 + mkdirp: 0.5.6 + pump: 1.0.3 + tar-stream: 1.6.2 + dev: true + /tar-stream@1.6.2: resolution: {integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==} engines: {node: '>= 0.8.0'} @@ -31288,13 +31367,25 @@ packages: xtend: 4.0.2 dev: true + /tar@6.2.0: + resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: true + /temp@0.8.4: resolution: {integrity: sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==} engines: {node: '>=6.0.0'} dependencies: rimraf: 2.6.3 - /terser-webpack-plugin@5.3.9(webpack@5.88.2): + /terser-webpack-plugin@5.3.9(webpack@5.89.0): resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -31310,12 +31401,12 @@ packages: uglify-js: optional: true dependencies: - '@jridgewell/trace-mapping': 0.3.19 + '@jridgewell/trace-mapping': 0.3.20 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.1 - terser: 5.21.0 - webpack: 5.88.2(webpack-cli@5.1.4) + terser: 5.22.0 + webpack: 5.89.0(webpack-cli@5.1.4) /terser@4.8.1: resolution: {integrity: sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==} @@ -31328,8 +31419,8 @@ packages: source-map-support: 0.5.21 dev: true - /terser@5.21.0: - resolution: {integrity: sha512-WtnFKrxu9kaoXuiZFSGrcAvvBqAdmKx0SFNmVNYdJamMu9yyN3I/QF0FbH4QcqJQ+y1CJnzxGIKH0cSj+FGYRw==} + /terser@5.22.0: + resolution: {integrity: sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw==} engines: {node: '>=10'} hasBin: true dependencies: @@ -31376,10 +31467,10 @@ packages: '@types/concat-stream': 1.6.1 '@types/form-data': 0.0.33 '@types/node': 8.10.66 - '@types/qs': 6.9.8 + '@types/qs': 6.9.9 caseless: 0.12.0 concat-stream: 1.6.2 - form-data: 2.3.3 + form-data: 2.5.1 http-basic: 8.1.3 http-response-object: 3.0.2 promise: 8.3.0 @@ -31451,6 +31542,14 @@ packages: retimer: 2.0.0 dev: false + /timeout-abort-controller@2.0.0: + resolution: {integrity: sha512-2FAPXfzTPYEgw27bQGTHc0SzrbmnU2eso4qo172zMLZzaGqeu09PFa5B2FCUHM1tflgRqPgn5KQgp6+Vex4uNA==} + dependencies: + abort-controller: 3.0.0 + native-abort-controller: 1.0.4(abort-controller@3.0.0) + retimer: 3.0.0 + dev: true + /timeout-abort-controller@3.0.0: resolution: {integrity: sha512-O3e+2B8BKrQxU2YRyEjC/2yFdb33slI22WRdUaDx6rvysfi9anloNZyR2q0l6LnePo5qH7gSM7uZtvvwZbc2yA==} dependencies: @@ -31504,6 +31603,12 @@ packages: dependencies: tslib: 2.6.2 + /tmp-promise@3.0.3: + resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} + dependencies: + tmp: 0.2.1 + dev: true + /tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -31572,7 +31677,6 @@ packages: /tough-cookie@4.1.3: resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} engines: {node: '>=6'} - requiresBuild: true dependencies: psl: 1.9.0 punycode: 2.3.0 @@ -31707,7 +31811,7 @@ packages: bs-logger: 0.2.6 esbuild: 0.17.19 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.15.13)(ts-node@10.9.1) + jest: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -31717,7 +31821,7 @@ packages: yargs-parser: 21.1.1 dev: true - /ts-loader@9.5.0(typescript@4.9.5)(webpack@5.88.2): + /ts-loader@9.5.0(typescript@4.9.5)(webpack@5.89.0): resolution: {integrity: sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg==} engines: {node: '>=12.0.0'} peerDependencies: @@ -31730,7 +31834,7 @@ packages: semver: 7.5.4 source-map: 0.7.4 typescript: 4.9.5 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: true /ts-mocha@10.0.0(mocha@10.2.0): @@ -31746,7 +31850,7 @@ packages: tsconfig-paths: 3.14.2 dev: true - /ts-node@10.9.1(@types/node@18.15.13)(typescript@4.9.5): + /ts-node@10.9.1(@types/node@18.18.6)(typescript@4.9.5): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -31765,7 +31869,7 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 18.15.13 + '@types/node': 18.18.6 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 @@ -31776,7 +31880,7 @@ packages: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - /ts-node@10.9.1(@types/node@18.15.13)(typescript@5.1.6): + /ts-node@10.9.1(@types/node@18.18.6)(typescript@5.1.6): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -31795,7 +31899,7 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 18.15.13 + '@types/node': 18.18.6 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 @@ -31806,6 +31910,38 @@ packages: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + /ts-node@10.9.1(@types/node@18.18.6)(typescript@5.2.2): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 18.18.6 + acorn: 8.10.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.2.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + optional: true + /ts-node@10.9.1(@types/node@20.5.1)(typescript@4.9.5): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true @@ -31854,7 +31990,6 @@ packages: /tsconfig-paths@3.14.2: resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} - requiresBuild: true dependencies: '@types/json5': 0.0.29 json5: 1.0.2 @@ -31873,8 +32008,8 @@ packages: /tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - /tslib@2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + /tslib@2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} /tslib@2.5.3: resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} @@ -31925,64 +32060,64 @@ packages: safe-buffer: 5.2.1 dev: true - /turbo-darwin-64@1.10.15: - resolution: {integrity: sha512-Sik5uogjkRTe1XVP9TC2GryEMOJCaKE2pM/O9uLn4koQDnWKGcLQv+mDU+H+9DXvKLnJnKCD18OVRkwK5tdpoA==} + /turbo-darwin-64@1.10.16: + resolution: {integrity: sha512-+Jk91FNcp9e9NCLYlvDDlp2HwEDp14F9N42IoW3dmHI5ZkGSXzalbhVcrx3DOox3QfiNUHxzWg4d7CnVNCuuMg==} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true - /turbo-darwin-arm64@1.10.15: - resolution: {integrity: sha512-xwqyFDYUcl2xwXyGPmHkmgnNm4Cy0oNzMpMOBGRr5x64SErS7QQLR4VHb0ubiR+VAb8M+ECPklU6vD1Gm+wekg==} + /turbo-darwin-arm64@1.10.16: + resolution: {integrity: sha512-jqGpFZipIivkRp/i+jnL8npX0VssE6IAVNKtu573LXtssZdV/S+fRGYA16tI46xJGxSAivrZ/IcgZrV6Jk80bw==} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /turbo-linux-64@1.10.15: - resolution: {integrity: sha512-dM07SiO3RMAJ09Z+uB2LNUSkPp3I1IMF8goH5eLj+d8Kkwoxd/+qbUZOj9RvInyxU/IhlnO9w3PGd3Hp14m/nA==} + /turbo-linux-64@1.10.16: + resolution: {integrity: sha512-PpqEZHwLoizQ6sTUvmImcRmACyRk9EWLXGlqceogPZsJ1jTRK3sfcF9fC2W56zkSIzuLEP07k5kl+ZxJd8JMcg==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /turbo-linux-arm64@1.10.15: - resolution: {integrity: sha512-MkzKLkKYKyrz4lwfjNXH8aTny5+Hmiu4SFBZbx+5C0vOlyp6fV5jZANDBvLXWiDDL4DSEAuCEK/2cmN6FVH1ow==} + /turbo-linux-arm64@1.10.16: + resolution: {integrity: sha512-TMjFYz8to1QE0fKVXCIvG/4giyfnmqcQIwjdNfJvKjBxn22PpbjeuFuQ5kNXshUTRaTJihFbuuCcb5OYFNx4uw==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /turbo-windows-64@1.10.15: - resolution: {integrity: sha512-3TdVU+WEH9ThvQGwV3ieX/XHebtYNHv9HARHauPwmVj3kakoALkpGxLclkHFBLdLKkqDvmHmXtcsfs6cXXRHJg==} + /turbo-windows-64@1.10.16: + resolution: {integrity: sha512-+jsf68krs0N66FfC4/zZvioUap/Tq3sPFumnMV+EBo8jFdqs4yehd6+MxIwYTjSQLIcpH8KoNMB0gQYhJRLZzw==} cpu: [x64] os: [win32] requiresBuild: true dev: true optional: true - /turbo-windows-arm64@1.10.15: - resolution: {integrity: sha512-l+7UOBCbfadvPMYsX08hyLD+UIoAkg6ojfH+E8aud3gcA1padpjCJTh9gMpm3QdMbKwZteT5uUM+wyi6Rbbyww==} + /turbo-windows-arm64@1.10.16: + resolution: {integrity: sha512-sKm3hcMM1bl0B3PLG4ifidicOGfoJmOEacM5JtgBkYM48ncMHjkHfFY7HrJHZHUnXM4l05RQTpLFoOl/uIo2HQ==} cpu: [arm64] os: [win32] requiresBuild: true dev: true optional: true - /turbo@1.10.15: - resolution: {integrity: sha512-mKKkqsuDAQy1wCCIjCdG+jOCwUflhckDMSRoeBPcIL/CnCl7c5yRDFe7SyaXloUUkt4tUR0rvNIhVCcT7YeQpg==} + /turbo@1.10.16: + resolution: {integrity: sha512-2CEaK4FIuSZiP83iFa9GqMTQhroW2QryckVqUydmg4tx78baftTOS0O+oDAhvo9r9Nit4xUEtC1RAHoqs6ZEtg==} hasBin: true optionalDependencies: - turbo-darwin-64: 1.10.15 - turbo-darwin-arm64: 1.10.15 - turbo-linux-64: 1.10.15 - turbo-linux-arm64: 1.10.15 - turbo-windows-64: 1.10.15 - turbo-windows-arm64: 1.10.15 + turbo-darwin-64: 1.10.16 + turbo-darwin-arm64: 1.10.16 + turbo-linux-64: 1.10.16 + turbo-linux-arm64: 1.10.16 + turbo-windows-64: 1.10.16 + turbo-windows-arm64: 1.10.16 dev: true /tweetnacl-util@0.15.1: @@ -32059,8 +32194,8 @@ packages: /type@2.7.2: resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} - /typechain@8.3.1(typescript@4.9.5): - resolution: {integrity: sha512-fA7clol2IP/56yq6vkMTR+4URF1nGjV82Wx6Rf09EsqD4tkzMAvEaqYxVFCavJm/1xaRga/oD55K+4FtuXwQOQ==} + /typechain@8.3.2(typescript@4.9.5): + resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} hasBin: true peerDependencies: typescript: '>=4.3.0' @@ -32079,8 +32214,8 @@ packages: transitivePeerDependencies: - supports-color - /typechain@8.3.1(typescript@5.1.6): - resolution: {integrity: sha512-fA7clol2IP/56yq6vkMTR+4URF1nGjV82Wx6Rf09EsqD4tkzMAvEaqYxVFCavJm/1xaRga/oD55K+4FtuXwQOQ==} + /typechain@8.3.2(typescript@5.1.6): + resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} hasBin: true peerDependencies: typescript: '>=4.3.0' @@ -32104,8 +32239,8 @@ packages: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 is-typed-array: 1.1.12 dev: true @@ -32113,7 +32248,7 @@ packages: resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 @@ -32124,7 +32259,7 @@ packages: engines: {node: '>= 0.4'} dependencies: available-typed-arrays: 1.0.5 - call-bind: 1.0.2 + call-bind: 1.0.5 for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 @@ -32133,7 +32268,7 @@ packages: /typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 for-each: 0.3.3 is-typed-array: 1.1.12 dev: true @@ -32188,6 +32323,14 @@ packages: engines: {node: '>=14.17'} hasBin: true + /typescript@5.2.2: + resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + engines: {node: '>=14.17'} + hasBin: true + requiresBuild: true + dev: true + optional: true + /typical@4.0.0: resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} engines: {node: '>=8'} @@ -32247,7 +32390,6 @@ packages: resolution: {integrity: sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==} dependencies: multiformats: 9.9.0 - dev: false /uint8arrays@4.0.6: resolution: {integrity: sha512-4ZesjQhqOU2Ip6GPReIwN60wRxIupavL8T0Iy36BBHr2qyMrNxsPJvr7vpS4eFt8F8kSguWUPad6ZM9izs/vyw==} @@ -32258,7 +32400,7 @@ packages: /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 @@ -32279,8 +32421,8 @@ packages: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} dev: true - /undici@5.26.0: - resolution: {integrity: sha512-MLqGMyaJk2ubSl7FrmWuV7ZOsYWmdF7gcBHDRxm4AR8NoodQhgy3vO/D1god79HoetxR0uAeVNB65yj2lNRQnQ==} + /undici@5.26.5: + resolution: {integrity: sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw==} engines: {node: '>=14.0'} dependencies: '@fastify/busboy': 2.0.0 @@ -32322,7 +32464,7 @@ packages: /unified@10.1.2: resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 bail: 2.0.2 extend: 3.0.2 is-buffer: 2.0.5 @@ -32334,7 +32476,7 @@ packages: /unified@9.2.0: resolution: {integrity: sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 bail: 1.0.5 extend: 3.0.2 is-buffer: 2.0.5 @@ -32346,7 +32488,7 @@ packages: /unified@9.2.2: resolution: {integrity: sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 bail: 1.0.5 extend: 3.0.2 is-buffer: 2.0.5 @@ -32381,7 +32523,7 @@ packages: /unist-util-is@5.2.1: resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 dev: false /unist-util-position@3.1.0: @@ -32391,7 +32533,7 @@ packages: /unist-util-position@4.0.4: resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 dev: false /unist-util-remove-position@2.0.1: @@ -32409,33 +32551,33 @@ packages: /unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 dev: false /unist-util-stringify-position@3.0.3: resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 dev: false /unist-util-visit-parents@3.1.1: resolution: {integrity: sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 unist-util-is: 4.1.0 dev: false /unist-util-visit-parents@5.1.3: resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 unist-util-is: 5.2.1 dev: false /unist-util-visit@2.0.3: resolution: {integrity: sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 unist-util-is: 4.1.0 unist-util-visit-parents: 3.1.1 dev: false @@ -32443,7 +32585,7 @@ packages: /unist-util-visit@4.1.2: resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 unist-util-is: 5.2.1 unist-util-visit-parents: 5.1.3 dev: false @@ -32455,7 +32597,6 @@ packages: /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} - requiresBuild: true dev: true /universalify@2.0.0: @@ -32529,7 +32670,7 @@ packages: dependencies: punycode: 2.3.0 - /url-loader@4.1.1(file-loader@6.2.0)(webpack@5.88.2): + /url-loader@4.1.1(file-loader@6.2.0)(webpack@5.89.0): resolution: {integrity: sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -32539,11 +32680,11 @@ packages: file-loader: optional: true dependencies: - file-loader: 6.2.0(webpack@5.88.2) + file-loader: 6.2.0(webpack@5.89.0) loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.3.0 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: false /url-parse-lax@3.0.0: @@ -32554,7 +32695,6 @@ packages: /url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - requiresBuild: true dependencies: querystringify: 2.2.0 requires-port: 1.0.0 @@ -32582,7 +32722,7 @@ packages: /urlpattern-polyfill@9.0.0: resolution: {integrity: sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==} - /use-callback-ref@1.3.0(@types/react@18.2.28)(react@18.2.0): + /use-callback-ref@1.3.0(@types/react@18.2.31)(react@18.2.0): resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} engines: {node: '>=10'} peerDependencies: @@ -32592,7 +32732,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 react: 18.2.0 tslib: 2.6.2 dev: false @@ -32630,7 +32770,7 @@ packages: use-isomorphic-layout-effect: 1.1.2(react@18.2.0) dev: false - /use-sidecar@1.1.2(@types/react@18.2.28)(react@18.2.0): + /use-sidecar@1.1.2(@types/react@18.2.31)(react@18.2.0): resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} engines: {node: '>=10'} peerDependencies: @@ -32640,7 +32780,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 detect-node-es: 1.1.0 react: 18.2.0 tslib: 2.6.2 @@ -32700,7 +32840,7 @@ packages: is-arguments: 1.1.1 is-generator-function: 1.0.10 is-typed-array: 1.1.12 - which-typed-array: 1.1.11 + which-typed-array: 1.1.13 /utila@0.4.0: resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} @@ -32756,8 +32896,8 @@ packages: resolution: {integrity: sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==} engines: {node: '>=10.12.0'} dependencies: - '@jridgewell/trace-mapping': 0.3.19 - '@types/istanbul-lib-coverage': 2.0.4 + '@jridgewell/trace-mapping': 0.3.20 + '@types/istanbul-lib-coverage': 2.0.5 convert-source-map: 2.0.0 /validate-npm-package-license@3.0.4: @@ -32808,7 +32948,6 @@ packages: /varint@6.0.0: resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} - dev: false /vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} @@ -32830,21 +32969,21 @@ packages: /vfile-message@2.0.4: resolution: {integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 unist-util-stringify-position: 2.0.3 dev: false /vfile-message@3.1.4: resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 unist-util-stringify-position: 3.0.3 dev: false /vfile@4.2.1: resolution: {integrity: sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 is-buffer: 2.0.5 unist-util-stringify-position: 2.0.3 vfile-message: 2.0.4 @@ -32853,7 +32992,7 @@ packages: /vfile@5.3.7: resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.9 is-buffer: 2.0.5 unist-util-stringify-position: 3.0.3 vfile-message: 3.1.4 @@ -32891,7 +33030,7 @@ packages: '@noble/hashes': 1.3.0 '@scure/bip32': 1.3.0 '@scure/bip39': 1.2.0 - '@types/ws': 8.5.7 + '@types/ws': 8.5.8 '@wagmi/chains': 1.6.0(typescript@5.1.6) abitype: 0.9.3(typescript@5.1.6)(zod@3.22.4) isomorphic-ws: 5.0.0(ws@8.12.0) @@ -32903,7 +33042,7 @@ packages: - zod dev: false - /vite-node@0.28.5(@types/node@18.15.13): + /vite-node@0.28.5(@types/node@18.18.6): resolution: {integrity: sha512-LmXb9saMGlrMZbXTvOveJKwMTBTNUH66c8rJnQ0ZPNX+myPEol64+szRzXtV5ORb0Hb/91yq+/D3oERoyAt6LA==} engines: {node: '>=v14.16.0'} hasBin: true @@ -32915,7 +33054,7 @@ packages: picocolors: 1.0.0 source-map: 0.6.1 source-map-support: 0.5.21 - vite: 4.4.11(@types/node@18.15.13) + vite: 4.5.0(@types/node@18.18.6) transitivePeerDependencies: - '@types/node' - less @@ -32927,8 +33066,8 @@ packages: - terser dev: true - /vite@4.4.11(@types/node@18.15.13): - resolution: {integrity: sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==} + /vite@4.5.0(@types/node@18.18.6): + resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: @@ -32955,7 +33094,7 @@ packages: terser: optional: true dependencies: - '@types/node': 18.15.13 + '@types/node': 18.18.6 esbuild: 0.18.20 postcss: 8.4.31 rollup: 3.29.4 @@ -32985,9 +33124,9 @@ packages: jsdom: optional: true dependencies: - '@types/chai': 4.3.7 - '@types/chai-subset': 1.3.3 - '@types/node': 18.15.13 + '@types/chai': 4.3.9 + '@types/chai-subset': 1.3.4 + '@types/node': 18.18.6 '@vitest/expect': 0.28.5 '@vitest/runner': 0.28.5 '@vitest/spy': 0.28.5 @@ -33006,8 +33145,8 @@ packages: tinybench: 2.5.1 tinypool: 0.3.1 tinyspy: 1.1.1 - vite: 4.4.11(@types/node@18.15.13) - vite-node: 0.28.5(@types/node@18.15.13) + vite: 4.5.0(@types/node@18.18.6) + vite-node: 0.28.5(@types/node@18.18.6) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -33051,7 +33190,12 @@ packages: - supports-color dev: false - /wagmi@1.3.9(@types/react@18.2.28)(react-dom@18.2.0)(react-native@0.72.5)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): + /wabt@1.0.24: + resolution: {integrity: sha512-8l7sIOd3i5GWfTWciPL0+ff/FK/deVK2Q6FN+MPz4vfUcD78i2M/49XJTwF6aml91uIiuXJEsLKWMB2cw/mtKg==} + hasBin: true + dev: true + + /wagmi@1.3.9(@types/react@18.2.31)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): resolution: {integrity: sha512-BQbl+vWLNpLraXd/MWsl1P3I41l7DHrujx6qshIa1HDV7Mdh0GNrDuluRYBtuK2bBx9WM/Fjw45Ef2aKADan9A==} peerDependencies: react: '>=17.0.0' @@ -33062,9 +33206,9 @@ packages: optional: true dependencies: '@tanstack/query-sync-storage-persister': 4.36.1 - '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react-native@0.72.5)(react@18.2.0) + '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0) '@tanstack/react-query-persist-client': 4.36.1(@tanstack/react-query@4.36.1) - '@wagmi/core': 1.3.8(@types/react@18.2.28)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + '@wagmi/core': 1.3.8(@types/react@18.2.31)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) abitype: 0.8.7(typescript@5.1.6)(zod@3.22.4) react: 18.2.0 typescript: 5.1.6 @@ -33153,8 +33297,16 @@ packages: resolution: {integrity: sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==} dev: false - /web3-utils@1.10.2: - resolution: {integrity: sha512-TdApdzdse5YR+5GCX/b/vQnhhbj1KSAtfrDtRW7YS0kcWp1gkJsN62gw6GzCaNTeXookB7UrLtmDUuMv65qgow==} + /web3-eth-abi@1.7.0: + resolution: {integrity: sha512-heqR0bWxgCJwjWIhq2sGyNj9bwun5+Xox/LdZKe+WMyTSy0cXDXEAgv3XKNkXC4JqdDt/ZlbTEx4TWak4TRMSg==} + engines: {node: '>=8.0.0'} + dependencies: + '@ethersproject/abi': 5.0.7 + web3-utils: 1.7.0 + dev: true + + /web3-utils@1.10.3: + resolution: {integrity: sha512-OqcUrEE16fDBbGoQtZXWdavsPzbGIDc5v3VrRTZ0XrIpefC/viZ1ZU9bGEemazyS0catk/3rkOOxpzTfY+XsyQ==} engines: {node: '>=8.0.0'} dependencies: '@ethereumjs/util': 8.1.0 @@ -33167,6 +33319,19 @@ packages: utf8: 3.0.0 dev: true + /web3-utils@1.7.0: + resolution: {integrity: sha512-O8Tl4Ky40Sp6pe89Olk2FsaUkgHyb5QAXuaKo38ms3CxZZ4d3rPGfjP9DNKGm5+IUgAZBNpF1VmlSmNCqfDI1w==} + engines: {node: '>=8.0.0'} + dependencies: + bn.js: 4.12.0 + ethereum-bloom-filters: 1.0.10 + ethereumjs-util: 7.1.5 + ethjs-unit: 0.1.6 + number-to-bn: 1.7.0 + randombytes: 2.1.0 + utf8: 3.0.0 + dev: true + /web3.storage@4.5.5(node-fetch@3.3.2): resolution: {integrity: sha512-ABW1Gk4gpkVkEIgeQTcoqZ1pI1YKQiBbZDploAcyldFWCXtdBpsijrRHg0S5Mwlvllw4E8OsRm/9HG2nVaGsCg==} dependencies: @@ -33195,12 +33360,16 @@ packages: /webcrypto-core@1.7.7: resolution: {integrity: sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==} dependencies: - '@peculiar/asn1-schema': 2.3.6 + '@peculiar/asn1-schema': 2.3.8 '@peculiar/json-schema': 1.1.12 asn1js: 3.0.5 pvtsutils: 1.3.5 tslib: 2.6.2 + /webextension-polyfill@0.10.0: + resolution: {integrity: sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==} + dev: false + /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -33236,7 +33405,7 @@ packages: - utf-8-validate dev: false - /webpack-cli@5.1.4(webpack@5.88.2): + /webpack-cli@5.1.4(webpack@5.89.0): resolution: {integrity: sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==} engines: {node: '>=14.15.0'} hasBin: true @@ -33254,9 +33423,9 @@ packages: optional: true dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.88.2) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.88.2) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack@5.88.2) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.89.0) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.89.0) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack@5.89.0) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.3 @@ -33265,10 +33434,10 @@ packages: import-local: 3.1.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.88.2(webpack-cli@5.1.4) - webpack-merge: 5.9.0 + webpack: 5.89.0(webpack-cli@5.1.4) + webpack-merge: 5.10.0 - /webpack-dev-middleware@5.3.3(webpack@5.88.2): + /webpack-dev-middleware@5.3.3(webpack@5.89.0): resolution: {integrity: sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -33279,9 +33448,9 @@ packages: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.2.0 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) - /webpack-dev-server@4.15.1(debug@4.3.4)(webpack@5.88.2): + /webpack-dev-server@4.15.1(debug@4.3.4)(webpack@5.89.0): resolution: {integrity: sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==} engines: {node: '>= 12.13.0'} hasBin: true @@ -33294,13 +33463,13 @@ packages: webpack-cli: optional: true dependencies: - '@types/bonjour': 3.5.11 - '@types/connect-history-api-fallback': 1.5.1 - '@types/express': 4.17.19 - '@types/serve-index': 1.9.2 - '@types/serve-static': 1.15.3 - '@types/sockjs': 0.3.34 - '@types/ws': 8.5.7 + '@types/bonjour': 3.5.12 + '@types/connect-history-api-fallback': 1.5.2 + '@types/express': 4.17.20 + '@types/serve-index': 1.9.3 + '@types/serve-static': 1.15.4 + '@types/sockjs': 0.3.35 + '@types/ws': 8.5.8 ansi-html-community: 0.0.8 bonjour-service: 1.1.1 chokidar: 3.5.3 @@ -33311,7 +33480,7 @@ packages: express: 4.18.2 graceful-fs: 4.2.11 html-entities: 2.4.0 - http-proxy-middleware: 2.0.6(@types/express@4.17.19)(debug@4.3.4) + http-proxy-middleware: 2.0.6(@types/express@4.17.20)(debug@4.3.4) ipaddr.js: 2.1.0 launch-editor: 2.6.1 open: 8.4.2 @@ -33322,28 +33491,29 @@ packages: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack: 5.88.2(webpack-cli@5.1.4) - webpack-dev-middleware: 5.3.3(webpack@5.88.2) - ws: 8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10) + webpack: 5.89.0(webpack-cli@5.1.4) + webpack-dev-middleware: 5.3.3(webpack@5.89.0) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - debug - supports-color - utf-8-validate - /webpack-merge@5.9.0: - resolution: {integrity: sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==} + /webpack-merge@5.10.0: + resolution: {integrity: sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==} engines: {node: '>=10.0.0'} dependencies: clone-deep: 4.0.1 + flat: 5.0.2 wildcard: 2.0.1 /webpack-sources@3.2.3: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - /webpack@5.88.2(webpack-cli@5.1.4): - resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} + /webpack@5.89.0(webpack-cli@5.1.4): + resolution: {integrity: sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -33352,8 +33522,8 @@ packages: webpack-cli: optional: true dependencies: - '@types/eslint-scope': 3.7.5 - '@types/estree': 1.0.2 + '@types/eslint-scope': 3.7.6 + '@types/estree': 1.0.3 '@webassemblyjs/ast': 1.11.6 '@webassemblyjs/wasm-edit': 1.11.6 '@webassemblyjs/wasm-parser': 1.11.6 @@ -33373,16 +33543,16 @@ packages: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.9(webpack@5.88.2) + terser-webpack-plugin: 5.3.9(webpack@5.89.0) watchpack: 2.4.0 - webpack-cli: 5.1.4(webpack@5.88.2) + webpack-cli: 5.1.4(webpack@5.89.0) webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' - esbuild - uglify-js - /webpackbar@5.0.2(webpack@5.88.2): + /webpackbar@5.0.2(webpack@5.89.0): resolution: {integrity: sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==} engines: {node: '>=12'} peerDependencies: @@ -33392,7 +33562,7 @@ packages: consola: 2.15.3 pretty-time: 1.1.0 std-env: 3.4.3 - webpack: 5.88.2(webpack-cli@5.1.4) + webpack: 5.89.0(webpack-cli@5.1.4) dev: false /websocket-driver@0.7.4: @@ -33411,7 +33581,7 @@ packages: resolution: {integrity: sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==} engines: {node: '>=4.0.0'} dependencies: - bufferutil: 4.0.7 + bufferutil: 4.0.8 debug: 2.6.9 es5-ext: 0.10.62 typedarray-to-buffer: 3.1.5 @@ -33482,7 +33652,7 @@ packages: isarray: 2.0.5 which-boxed-primitive: 1.0.2 which-collection: 1.0.1 - which-typed-array: 1.1.11 + which-typed-array: 1.1.13 dev: true /which-collection@1.0.1: @@ -33501,12 +33671,12 @@ packages: /which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - /which-typed-array@1.1.11: - resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} + /which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} engines: {node: '>= 0.4'} dependencies: available-typed-arrays: 1.0.5 - call-bind: 1.0.2 + call-bind: 1.0.5 for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.0 @@ -33538,7 +33708,6 @@ packages: engines: {node: '>=8'} dependencies: string-width: 4.2.3 - dev: false /widest-line@4.0.1: resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} @@ -33740,7 +33909,7 @@ packages: utf-8-validate: optional: true - /ws@8.14.2(bufferutil@4.0.7)(utf-8-validate@5.0.10): + /ws@8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10): resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} engines: {node: '>=10.0.0'} peerDependencies: @@ -33752,7 +33921,7 @@ packages: utf-8-validate: optional: true dependencies: - bufferutil: 4.0.7 + bufferutil: 4.0.8 utf-8-validate: 5.0.10 /xdg-basedir@4.0.0: @@ -33772,14 +33941,6 @@ packages: engines: {node: '>=12'} dev: true - /xml2js@0.5.0: - resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} - engines: {node: '>=4.0.0'} - dependencies: - sax: 1.3.0 - xmlbuilder: 11.0.1 - dev: false - /xml2js@0.6.2: resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} engines: {node: '>=4.0.0'} @@ -33839,11 +34000,15 @@ packages: /yaml@1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} - dev: false /yaml@2.3.1: resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==} engines: {node: '>= 14'} + dev: true + + /yaml@2.3.3: + resolution: {integrity: sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==} + engines: {node: '>= 14'} /yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} @@ -33976,12 +34141,12 @@ packages: resolution: {integrity: sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==} engines: {node: '>=10'} dependencies: - '@babel/runtime': 7.23.1 - '@types/lodash': 4.14.199 + '@babel/runtime': 7.23.2 + '@types/lodash': 4.14.200 lodash: 4.17.21 lodash-es: 4.17.21 nanoclone: 0.2.1 - property-expr: 2.0.5 + property-expr: 2.0.6 toposort: 2.0.2 dev: false @@ -34005,8 +34170,8 @@ packages: /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} - /zustand@4.4.3(@types/react@18.2.28)(react@18.2.0): - resolution: {integrity: sha512-oRy+X3ZazZvLfmv6viIaQmtLOMeij1noakIsK/Y47PWYhT8glfXzQ4j0YcP5i0P0qI1A4rIB//SGROGyZhx91A==} + /zustand@4.4.4(@types/react@18.2.31)(react@18.2.0): + resolution: {integrity: sha512-5UTUIAiHMNf5+mFp7/AnzJXS7+XxktULFN0+D1sCiZWyX7ZG+AQpqs2qpYrynRij4QvoDdCD+U+bmg/cG3Ucxw==} engines: {node: '>=12.7.0'} peerDependencies: '@types/react': '>=16.8' @@ -34020,7 +34185,7 @@ packages: react: optional: true dependencies: - '@types/react': 18.2.28 + '@types/react': 18.2.31 react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) dev: false diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 697ff688..aaa9186b 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,6 +3,7 @@ packages: - "defender" - "docs" - "frontend" + - "graph" - "vendor/observabletreemap" - "sdk" - - "contracts" \ No newline at end of file + - "contracts" diff --git a/sdk/package.json b/sdk/package.json index 81556561..1227f74b 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@hypercerts-org/sdk", - "version": "0.8.13", + "version": "0.8.16", "description": "SDK for hypercerts protocol", "repository": "git@github.com:hypercerts-org/hypercerts.git", "author": "Hypercerts team", diff --git a/sdk/src/constants.ts b/sdk/src/constants.ts index 0ee3743b..da4383b5 100644 --- a/sdk/src/constants.ts +++ b/sdk/src/constants.ts @@ -23,6 +23,12 @@ const DEPLOYMENTS: { [key in SupportedChainIds]: Deployment } = { contractAddress: "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", graphUrl: `${DEFAULT_GRAPH_BASE_URL}/hypercerts-optimism-mainnet`, } as const, + 42220: { + chainId: 42220, + chainName: "celo-mainnet", + contractAddress: "0x16ba53b74c234c870c61efc04cd418b8f2865959", + graphUrl: `${DEFAULT_GRAPH_BASE_URL}/hypercerts-celo`, + }, 11155111: { chainId: 11155111, chainName: "sepolia", diff --git a/sdk/src/types/client.ts b/sdk/src/types/client.ts index 407a3fd0..7d803a0c 100644 --- a/sdk/src/types/client.ts +++ b/sdk/src/types/client.ts @@ -7,7 +7,7 @@ import HypercertIndexer from "../indexer.js"; import { AllowlistEntry, TransferRestrictions } from "./hypercerts.js"; import { HypercertMetadata } from "./metadata.js"; -export type SupportedChainIds = 5 | 10 | 11155111; +export type SupportedChainIds = 5 | 10 | 42220 | 11155111; /** * Represents a deployment of a contract on a specific network. diff --git a/sdk/src/utils/config.ts b/sdk/src/utils/config.ts index bd59eabd..a9dfb228 100644 --- a/sdk/src/utils/config.ts +++ b/sdk/src/utils/config.ts @@ -39,7 +39,7 @@ export const getConfig = (overrides: Partial) => { unsafeForceOverrideConfig: overrides.unsafeForceOverrideConfig, }; } else { - if (!chainId || [5, 10, 11155111].indexOf(chainId) === -1) { + if (!chainId || [5, 10, 42220, 11155111].indexOf(chainId) === -1) { throw new UnsupportedChainError(`chainId=${chainId} is not yet supported`, { chainID: chainId?.toString() || "undefined", }); @@ -87,6 +87,9 @@ const getChainConfig = (overrides: Partial) => { case 10: chainName = "optimism-mainnet"; break; + case 42220: + chainName = "celo"; + break; case 11155111: chainName = "sepolia"; break; From 728e9c746fdbe9353391992c6c0edc2ac7813c73 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Wed, 25 Oct 2023 16:51:04 +0200 Subject: [PATCH 11/49] chore(prep): protocol contracts to protocol dir --- contracts/contracts/HypercertMinter.sol | 229 --------- contracts/contracts/SemiFungible1155.sol | 433 ------------------ .../contracts/interfaces/IHypercertToken.sol | 62 --- contracts/remappings.txt | 1 + contracts/src/AllowlistMinter.sol | 70 --- contracts/src/interfaces/IAllowlist.sol | 14 - contracts/src/libs/Errors.sol | 15 - .../protocol}/AllowlistMinter.sol | 0 .../src/{ => protocol}/HypercertMinter.sol | 0 .../src/{ => protocol}/HypercertTrader.sol | 0 .../src/{ => protocol}/SemiFungible1155.sol | 0 .../protocol}/interfaces/IAllowlist.sol | 0 .../interfaces/IHypercertToken.sol | 0 .../interfaces/IHypercertTrader.sol | 0 .../protocol}/libs/Errors.sol | 0 contracts/test/foundry/AllowlistMinter.t.sol | 4 +- .../HypercertMinter.batchminting.t.sol | 4 +- .../foundry/HypercertMinter.pausable.t.sol | 4 +- contracts/test/foundry/HypercertMinter.t.sol | 4 +- .../foundry/HypercertMinter.transfers.t.sol | 6 +- .../test/foundry/HypercertTrader.admin.t.sol | 6 +- .../test/foundry/HypercertTrader.offers.t.sol | 6 +- .../test/foundry/HypercertTrader.sales.t.sol | 6 +- .../test/foundry/PerformanceTesting.t.sol | 4 +- contracts/test/foundry/SemiFungibleHelper.sol | 2 +- 25 files changed, 24 insertions(+), 846 deletions(-) delete mode 100644 contracts/contracts/HypercertMinter.sol delete mode 100644 contracts/contracts/SemiFungible1155.sol delete mode 100644 contracts/contracts/interfaces/IHypercertToken.sol delete mode 100644 contracts/src/AllowlistMinter.sol delete mode 100644 contracts/src/interfaces/IAllowlist.sol delete mode 100644 contracts/src/libs/Errors.sol rename contracts/{contracts => src/protocol}/AllowlistMinter.sol (100%) rename contracts/src/{ => protocol}/HypercertMinter.sol (100%) rename contracts/src/{ => protocol}/HypercertTrader.sol (100%) rename contracts/src/{ => protocol}/SemiFungible1155.sol (100%) rename contracts/{contracts => src/protocol}/interfaces/IAllowlist.sol (100%) rename contracts/src/{ => protocol}/interfaces/IHypercertToken.sol (100%) rename contracts/src/{ => protocol}/interfaces/IHypercertTrader.sol (100%) rename contracts/{contracts => src/protocol}/libs/Errors.sol (100%) diff --git a/contracts/contracts/HypercertMinter.sol b/contracts/contracts/HypercertMinter.sol deleted file mode 100644 index 917c02c5..00000000 --- a/contracts/contracts/HypercertMinter.sol +++ /dev/null @@ -1,229 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import { IHypercertToken } from "./interfaces/IHypercertToken.sol"; -import { SemiFungible1155 } from "./SemiFungible1155.sol"; -import { AllowlistMinter } from "./AllowlistMinter.sol"; -import { PausableUpgradeable } from "oz-upgradeable/security/PausableUpgradeable.sol"; - -import { Errors } from "./libs/Errors.sol"; - -/// @title Contract for managing hypercert claims and whitelists -/// @author bitbeckers -/// @notice Implementation of the HypercertTokenInterface using { SemiFungible1155 } as underlying token. -/// @notice This contract supports whitelisted minting via { AllowlistMinter }. -/// @dev Wrapper contract to expose and chain functions. -contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, PausableUpgradeable { - // solhint-disable-next-line const-name-snakecase - string public constant name = "HypercertMinter"; - /// @dev from typeID to a transfer policy - mapping(uint256 => TransferRestrictions) internal typeRestrictions; - - /// INIT - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - function initialize() public virtual initializer { - __SemiFungible1155_init(); - __Pausable_init(); - } - - /// EXTERNAL - - /// @notice Mint a semi-fungible token for the impact claim referenced via `uri` - /// @dev see {IHypercertToken} - function mintClaim( - address account, - uint256 units, - string memory _uri, - TransferRestrictions restrictions - ) external override whenNotPaused { - // This enables us to release this restriction in the future - if (msg.sender != account) revert Errors.NotAllowed(); - uint256 claimID = _mintNewTypeWithToken(account, units, _uri); - typeRestrictions[claimID] = restrictions; - emit ClaimStored(claimID, _uri, units); - } - - /// @notice Mint semi-fungible tokens for the impact claim referenced via `uri` - /// @dev see {IHypercertToken} - function mintClaimWithFractions( - address account, - uint256 units, - uint256[] calldata fractions, - string memory _uri, - TransferRestrictions restrictions - ) external override whenNotPaused { - // This enables us to release this restriction in the future - if (msg.sender != account) revert Errors.NotAllowed(); - //Using sum to compare units and fractions (sanity check) - if (_getSum(fractions) != units) revert Errors.Invalid(); - - uint256 claimID = _mintNewTypeWithTokens(account, fractions, _uri); - typeRestrictions[claimID] = restrictions; - emit ClaimStored(claimID, _uri, units); - } - - /// @notice Mint a semi-fungible token representing a fraction of the claim - /// @dev Calls AllowlistMinter to verify `proof`. - /// @dev Mints the `amount` of units for the hypercert stored under `claimID` - function mintClaimFromAllowlist( - address account, - bytes32[] calldata proof, - uint256 claimID, - uint256 units - ) external whenNotPaused { - _processClaim(proof, claimID, units); - _mintToken(account, claimID, units); - } - - /// @notice Mint semi-fungible tokens representing a fraction of the claims in `claimIDs` - /// @dev Calls AllowlistMinter to verify `proofs`. - /// @dev Mints the `amount` of units for the hypercert stored under `claimIDs` - function batchMintClaimsFromAllowlists( - address account, - bytes32[][] calldata proofs, - uint256[] calldata claimIDs, - uint256[] calldata units - ) external whenNotPaused { - uint256 len = claimIDs.length; - for (uint256 i; i < len; ) { - _processClaim(proofs[i], claimIDs[i], units[i]); - unchecked { - ++i; - } - } - _batchMintTokens(account, claimIDs, units); - } - - /// @notice Register a claim and the whitelist for minting token(s) belonging to that claim - /// @dev Calls SemiFungible1155 to store the claim referenced in `uri` with amount of `units` - /// @dev Calls AllowlistMinter to store the `merkleRoot` as proof to authorize claims - function createAllowlist( - address account, - uint256 units, - bytes32 merkleRoot, - string memory _uri, - TransferRestrictions restrictions - ) external whenNotPaused { - uint256 claimID = _createTokenType(account, units, _uri); - _createAllowlist(claimID, merkleRoot, units); - typeRestrictions[claimID] = restrictions; - emit ClaimStored(claimID, _uri, units); - } - - /// @notice Split a claimtokens value into parts with summed value equal to the original - /// @dev see {IHypercertToken} - function splitFraction( - address _account, - uint256 _tokenID, - uint256[] calldata _newFractions - ) external whenNotPaused { - _splitTokenUnits(_account, _tokenID, _newFractions); - } - - /// @notice Merge the value of tokens belonging to the same claim - /// @dev see {IHypercertToken} - function mergeFractions(address _account, uint256[] calldata _fractionIDs) external whenNotPaused { - _mergeTokensUnits(_account, _fractionIDs); - } - - /// @notice Burn a claimtoken - /// @dev see {IHypercertToken} - function burnFraction(address _account, uint256 _tokenID) external whenNotPaused { - _burnToken(_account, _tokenID); - } - - /// @dev see {IHypercertToken} - function unitsOf(uint256 tokenID) external view override returns (uint256 units) { - units = _unitsOf(tokenID); - } - - /// @dev see {IHypercertToken} - function unitsOf(address account, uint256 tokenID) external view override returns (uint256 units) { - units = _unitsOf(account, tokenID); - } - - /// PAUSABLE - - function pause() external onlyOwner { - _pause(); - } - - function unpause() external onlyOwner { - _unpause(); - } - - /// METADATA - - /// @dev see { IHypercertMetadata} - function uri(uint256 tokenID) public view override(IHypercertToken, SemiFungible1155) returns (string memory _uri) { - _uri = SemiFungible1155.uri(tokenID); - } - - /// TRANSFER RESTRICTIONS - - function readTransferRestriction(uint256 tokenID) external view returns (string memory) { - TransferRestrictions temp = typeRestrictions[getBaseType(tokenID)]; - if (temp == TransferRestrictions.AllowAll) return "AllowAll"; - if (temp == TransferRestrictions.DisallowAll) return "DisallowAll"; - if (temp == TransferRestrictions.FromCreatorOnly) return "FromCreatorOnly"; - return ""; - } - - /// INTERNAL - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol } - function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { - // solhint-disable-previous-line no-empty-blocks - } - - function _beforeTokenTransfer( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual override { - super._beforeTokenTransfer(operator, from, to, ids, amounts, data); - - // By-pass transfer restrictions for minting and burning - if (from == address(0)) { - // Minting - return; - } else if (to == address(0)) { - // Burning - return; - } - - // Transfer case, where to and from are non-zero - uint256 len = ids.length; - for (uint256 i; i < len; ) { - uint256 typeID = getBaseType(ids[i]); - TransferRestrictions policy = typeRestrictions[typeID]; - if (policy == TransferRestrictions.DisallowAll) { - revert Errors.TransfersNotAllowed(); - } else if (policy == TransferRestrictions.FromCreatorOnly && from != creators[typeID]) { - revert Errors.TransfersNotAllowed(); - } - unchecked { - ++i; - } - } - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - * Assuming 30 available slots (slots cost space, cost gas) - * 1. typeRestrictions - */ - uint256[29] private __gap; -} diff --git a/contracts/contracts/SemiFungible1155.sol b/contracts/contracts/SemiFungible1155.sol deleted file mode 100644 index cd88714a..00000000 --- a/contracts/contracts/SemiFungible1155.sol +++ /dev/null @@ -1,433 +0,0 @@ -// SPDX-License-Identifier: MIT -// Used components of Enjin example implementation for mixed fungibility -// /~https://github.com/enjin/erc-1155/blob/master/contracts/ERC1155MixedFungibleMintable.sol -pragma solidity 0.8.16; - -import { ERC1155Upgradeable } from "oz-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; -import { ERC1155BurnableUpgradeable } from "oz-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol"; -import { ERC1155URIStorageUpgradeable } from "oz-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol"; -import { OwnableUpgradeable } from "oz-upgradeable/access/OwnableUpgradeable.sol"; -import { Initializable } from "oz-upgradeable/proxy/utils/Initializable.sol"; -import { UUPSUpgradeable } from "oz-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { Errors } from "./libs/Errors.sol"; - -/// @title Contract for minting semi-fungible EIP1155 tokens -/// @author bitbeckers -/// @notice Extends { Upgradeable1155 } token with semi-fungible properties and the concept of `units` -/// @dev Adds split bit strategy as described in [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155#non-fungible-tokens) -contract SemiFungible1155 is - Initializable, - ERC1155Upgradeable, - ERC1155BurnableUpgradeable, - ERC1155URIStorageUpgradeable, - OwnableUpgradeable, - UUPSUpgradeable -{ - /// @dev Counter used to generate next typeID. - uint256 internal typeCounter; - - /// @dev Bitmask used to expose only upper 128 bits of uint256 - uint256 internal constant TYPE_MASK = type(uint256).max << 128; - - /// @dev Bitmask used to expose only lower 128 bits of uint256 - uint256 internal constant NF_INDEX_MASK = type(uint256).max >> 128; - - uint256 internal constant FRACTION_LIMIT = 253; - - /// @dev Mapping of `tokenID` to address of `owner` - mapping(uint256 => address) internal owners; - - /// @dev Mapping of `tokenID` to address of `creator` - mapping(uint256 => address) internal creators; - - /// @dev Used to determine amount of `units` stored in token at `tokenID` - mapping(uint256 => uint256) internal tokenValues; - - /// @dev Used to find highest index of token belonging to token at `typeID` - mapping(uint256 => uint256) internal maxIndex; - - /// @dev Emitted on transfer of `value` between `fromTokenID` to `toTokenID` of the same `claimID` - event ValueTransfer(uint256 claimID, uint256 fromTokenID, uint256 toTokenID, uint256 value); - - /// @dev Emitted on transfer of `values` between `fromTokenIDs` to `toTokenIDs` of `claimIDs` - event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values); - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - // solhint-disable-next-line func-name-mixedcase - function __SemiFungible1155_init() public virtual onlyInitializing { - __ERC1155_init(""); - __ERC1155Burnable_init(); - __ERC1155URIStorage_init(); - __Ownable_init(); - __UUPSUpgradeable_init(); - } - - /// @dev Get index of fractional token at `_id` by returning lower 128 bit values - /// @dev Returns 0 if `_id` is a baseType - function getItemIndex(uint256 tokenID) internal pure returns (uint256) { - return tokenID & NF_INDEX_MASK; - } - - /// @dev Get base type ID for token at `_id` by returning upper 128 bit values - function getBaseType(uint256 tokenID) internal pure returns (uint256) { - return tokenID & TYPE_MASK; - } - - /// @dev Identify that token at `_id` is base type. - /// @dev Upper 128 bits identify base type ID, lower bits should be 0 - function isBaseType(uint256 tokenID) internal pure returns (bool) { - return (tokenID & TYPE_MASK == tokenID) && (tokenID & NF_INDEX_MASK == 0); - } - - /// @dev Identify that token at `_id` is fraction of a claim. - /// @dev Upper 128 bits identify base type ID, lower bits should be > 0 - function isTypedItem(uint256 tokenID) internal pure returns (bool) { - return (tokenID & TYPE_MASK != 0) && (tokenID & NF_INDEX_MASK != 0); - } - - /// READ - function ownerOf(uint256 tokenID) public view returns (address _owner) { - _owner = owners[tokenID]; - } - - /// @dev see {IHypercertToken} - function _unitsOf(uint256 tokenID) internal view returns (uint256 units) { - units = tokenValues[tokenID]; - } - - /// @dev see {IHypercertToken} - function _unitsOf(address account, uint256 tokenID) internal view returns (uint256 units) { - // Check if fraction token and accounts owns it - if (ownerOf(tokenID) == account) { - units = tokenValues[tokenID]; - } - } - - /// MUTATE - - /// @dev create token type ID based of token counter - - function _createTokenType(address _account, uint256 units, string memory _uri) internal returns (uint256 typeID) { - _notMaxType(typeCounter); - typeID = ++typeCounter << 128; - - creators[typeID] = _account; - tokenValues[typeID] = units; - - _setURI(typeID, _uri); - - //Event emitted for indexing purposes - emit TransferSingle(_account, address(0), address(0), typeID, 0); - } - - /// @dev Mint a new token type and the initial units - function _mintNewTypeWithToken( - address _account, - uint256 _units, - string memory _uri - ) internal returns (uint256 typeID) { - if (_units == 0) { - revert Errors.NotAllowed(); - } - typeID = _createTokenType(_account, _units, _uri); - - uint256 tokenID = typeID + ++maxIndex[typeID]; //1 based indexing, 0 holds type data - - tokenValues[tokenID] = _units; - - _mint(_account, tokenID, 1, ""); - emit ValueTransfer(typeID, 0, tokenID, _units); - } - - /// @dev Mint a new token type and the initial fractions - function _mintNewTypeWithTokens( - address _account, - uint256[] calldata _fractions, - string memory _uri - ) internal returns (uint256 typeID) { - typeID = _mintNewTypeWithToken(_account, _getSum(_fractions), _uri); - _splitTokenUnits(_account, typeID + maxIndex[typeID], _fractions); - } - - /// @dev Mint a new token for an existing type - function _mintToken(address _account, uint256 _typeID, uint256 _units) internal returns (uint256 tokenID) { - if (!isBaseType(_typeID)) revert Errors.NotAllowed(); - - _notMaxItem(maxIndex[_typeID]); - - unchecked { - tokenID = _typeID + ++maxIndex[_typeID]; //1 based indexing, 0 holds type data - } - - tokenValues[tokenID] = _units; - - _mint(_account, tokenID, 1, ""); - emit ValueTransfer(_typeID, 0, tokenID, _units); - } - - /// @dev Mint new tokens for existing types - /// @notice Enables batch claiming from multiple allowlists - function _batchMintTokens( - address _account, - uint256[] calldata _typeIDs, - uint256[] calldata _units - ) internal returns (uint256[] memory tokenIDs) { - uint256 len = _typeIDs.length; - - tokenIDs = new uint256[](len); - uint256[] memory amounts = new uint256[](len); - uint256[] memory zeroes = new uint256[](len); - - for (uint256 i; i < len; ) { - uint256 _typeID = _typeIDs[i]; - if (!isBaseType(_typeID)) revert Errors.NotAllowed(); - _notMaxItem(maxIndex[_typeID]); - - unchecked { - uint256 tokenID = _typeID + ++maxIndex[_typeID]; //1 based indexing, 0 holds type data - tokenValues[tokenID] = _units[i]; - tokenIDs[i] = tokenID; - amounts[i] = 1; - ++i; - } - } - - _mintBatch(_account, tokenIDs, amounts, ""); - emit BatchValueTransfer(_typeIDs, zeroes, tokenIDs, _units); - } - - /// @dev Split the units of `_tokenID` owned by `account` across `_values` - /// @dev `_values` must sum to total `units` held at `_tokenID` - function _splitTokenUnits(address _account, uint256 _tokenID, uint256[] calldata _values) internal { - if (_values.length > FRACTION_LIMIT || _values.length < 2) revert Errors.ArraySize(); - if (tokenValues[_tokenID] != _getSum(_values)) revert Errors.NotAllowed(); - - // Current token - uint256 _typeID = getBaseType(_tokenID); - uint256 valueLeft = tokenValues[_tokenID]; - - // Prepare batch processing, we want to skip the first entry - uint256 len = _values.length - 1; - - uint256[] memory typeIDs = new uint256[](len); - uint256[] memory fromIDs = new uint256[](len); - uint256[] memory toIDs = new uint256[](len); - uint256[] memory amounts = new uint256[](len); - uint256[] memory values = new uint256[](len); - - { - uint256[] memory _valuesCache = _values; - uint256 swapValue = _valuesCache[len]; - _valuesCache[len] = _valuesCache[0]; - _valuesCache[0] = swapValue; - - for (uint256 i; i < len; ) { - _notMaxItem(maxIndex[_typeID]); - - typeIDs[i] = _typeID; - fromIDs[i] = _tokenID; - toIDs[i] = _typeID + ++maxIndex[_typeID]; - amounts[i] = 1; - values[i] = _valuesCache[i]; - - unchecked { - ++i; - } - } - } - - _beforeUnitTransfer(_msgSender(), _account, fromIDs, toIDs, values, ""); - - for (uint256 i; i < len; ) { - valueLeft -= values[i]; - - tokenValues[toIDs[i]] = values[i]; - - unchecked { - ++i; - } - } - - tokenValues[_tokenID] = valueLeft; - - _mintBatch(_account, toIDs, amounts, ""); - - emit BatchValueTransfer(typeIDs, fromIDs, toIDs, values); - } - - /// @dev Merge the units of `_fractionIDs`. - /// @dev Base type of `_fractionIDs` must be identical for all tokens. - function _mergeTokensUnits(address _account, uint256[] memory _fractionIDs) internal { - if (_fractionIDs.length > FRACTION_LIMIT || _fractionIDs.length < 2) { - revert Errors.ArraySize(); - } - uint256 len = _fractionIDs.length - 1; - - uint256 target = _fractionIDs[len]; - - uint256 _totalValue; - uint256[] memory fromIDs = new uint256[](len); - uint256[] memory toIDs = new uint256[](len); - uint256[] memory values = new uint256[](len); - uint256[] memory amounts = new uint256[](len); - - { - for (uint256 i; i < len; ) { - uint256 _fractionID = _fractionIDs[i]; - fromIDs[i] = _fractionID; - toIDs[i] = target; - amounts[i] = 1; - values[i] = tokenValues[_fractionID]; - - unchecked { - ++i; - } - } - } - - _beforeUnitTransfer(_msgSender(), _account, fromIDs, toIDs, values, ""); - - for (uint256 i; i < len; ) { - _totalValue += values[i]; - - delete tokenValues[fromIDs[i]]; - unchecked { - ++i; - } - } - - tokenValues[target] += _totalValue; - - _burnBatch(_account, fromIDs, amounts); - } - - /// @dev Burn the token at `_tokenID` owned by `_account` - /// @dev Not allowed to burn base type. - /// @dev `_tokenID` must hold all value declared at base type - function _burnToken(address _account, uint256 _tokenID) internal { - if (_account != _msgSender() && !isApprovedForAll(_account, _msgSender())) revert Errors.NotApprovedOrOwner(); - - uint256 value = tokenValues[_tokenID]; - - delete tokenValues[_tokenID]; - - _burn(_account, _tokenID, 1); - emit ValueTransfer(getBaseType(_tokenID), _tokenID, 0, value); - } - - /// TRANSFERS - - // The following functions are overrides required by Solidity. - function _afterTokenTransfer( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual override { - super._afterTokenTransfer(operator, from, to, ids, amounts, data); - - uint256 len = ids.length; - - for (uint256 i; i < len; ) { - owners[ids[i]] = to; - unchecked { - ++i; - } - } - } - - function _beforeUnitTransfer( - address operator, - address from, - uint256[] memory fromIDs, - uint256[] memory toIDs, - uint256[] memory values, - bytes memory data - ) internal virtual { - uint256 len = fromIDs.length; - - for (uint256 i; i < len; ) { - uint256 _from = fromIDs[i]; - uint256 _to = toIDs[i]; - - if (isBaseType(_from)) revert Errors.NotAllowed(); - if (getBaseType(_from) != getBaseType(_to)) revert Errors.TypeMismatch(); - if (from != _msgSender() && !isApprovedForAll(from, _msgSender())) revert Errors.NotApprovedOrOwner(); - unchecked { - ++i; - } - } - } - - /// METADATA - - /// @dev see { openzeppelin-contracts-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol } - /// @dev Always returns the URI for the basetype so that it's managed in one place. - function uri( - uint256 tokenID - ) public view virtual override(ERC1155Upgradeable, ERC1155URIStorageUpgradeable) returns (string memory _uri) { - // All tokens share the same metadata at the moment - _uri = ERC1155URIStorageUpgradeable.uri(getBaseType(tokenID)); - } - - /// UTILS - - /** - * @dev Check if value is below max item index - */ - function _notMaxItem(uint256 tokenID) private pure { - uint128 _count = uint128(tokenID); - ++_count; - } - - /** - * @dev Check if value is below max type index - */ - function _notMaxType(uint256 tokenID) private pure { - uint128 _count = uint128(tokenID >> 128); - ++_count; - } - - /** - * @dev calculate the sum of the elements of an array - */ - function _getSum(uint256[] memory array) internal pure returns (uint256 sum) { - uint256 len = array.length; - for (uint256 i; i < len; ) { - if (array[i] == 0) revert Errors.NotAllowed(); - sum += array[i]; - unchecked { - ++i; - } - } - } - - function _getSingletonArray(uint256 element) private pure returns (uint256[] memory) { - uint256[] memory array = new uint256[](1); - array[0] = element; - - return array; - } - - // UUPS PROXY - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol } - function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { - // solhint-disable-previous-line no-empty-blocks - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - * Assuming 30 available slots (slots cost space, cost gas) - * 1. typeCounter - * 2. owners - * 3. creators - * 4. tokenValues - * 5. maxIndex - */ - uint256[25] private __gap; -} diff --git a/contracts/contracts/interfaces/IHypercertToken.sol b/contracts/contracts/interfaces/IHypercertToken.sol deleted file mode 100644 index 1ed1e34e..00000000 --- a/contracts/contracts/interfaces/IHypercertToken.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -/// @title Interface for hypercert token interactions -/// @author bitbeckers -/// @notice This interface declares the required functionality for a hypercert token -/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) -interface IHypercertToken { - /** - * AllowAll = Unrestricted - * DisallowAll = Transfers disabled after minting - * FromCreatorOnly = Only the original creator can transfer - */ - /// @dev Transfer restriction policies on hypercerts - enum TransferRestrictions { - AllowAll, - DisallowAll, - FromCreatorOnly - } - - /// @dev Emitted when token with tokenID `claimID` is stored, with external data reference via `uri`. - event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits); - - /// @dev Function called to store a claim referenced via `uri` with a maximum number of fractions `units`. - function mintClaim(address account, uint256 units, string memory uri, TransferRestrictions restrictions) external; - - /// @dev Function called to store a claim referenced via `uri` with a set of `fractions`. - /// @dev Fractions are internally summed to total units. - function mintClaimWithFractions( - address account, - uint256 units, - uint256[] memory fractions, - string memory uri, - TransferRestrictions restrictions - ) external; - - /// @dev Function called to split `tokenID` owned by `account` into units declared in `values`. - /// @notice The sum of `values` must equal the current value of `_tokenID`. - function splitFraction(address account, uint256 tokenID, uint256[] memory _values) external; - - /// @dev Function called to merge tokens within `tokenIDs`. - /// @notice Tokens that have been merged are burned. - function mergeFractions(address account, uint256[] memory tokenIDs) external; - - /// @dev Function to burn the token at `tokenID` for `account` - /// @notice Operator must be allowed by `creator` and the token must represent the total amount of available units. - function burnFraction(address account, uint256 tokenID) external; - - /// @dev Returns the `units` held by a (fractional) token at `claimID` - /// @dev If `tokenID` is a base type, the total amount of `units` for the claim is returned. - /// @dev If `tokenID` is a fractional token, the `units` held by the token is returned - function unitsOf(uint256 tokenID) external view returns (uint256 units); - - /// @dev Returns the `units` held by `account` of a (fractional) token at `claimID` - /// @dev If `tokenID` is a base type, the total amount of `units` held by `account` for the claim is returned. - /// @dev If `tokenID` is a fractional token, the `units` held by `account` the token is returned - function unitsOf(address account, uint256 tokenID) external view returns (uint256 units); - - /// @dev Returns the `uri` for metadata of the claim represented by `tokenID` - /// @dev Metadata must conform to { Hypercert Metadata } spec (based on ERC1155 Metadata) - function uri(uint256 tokenID) external view returns (string memory metadata); -} diff --git a/contracts/remappings.txt b/contracts/remappings.txt index bb8f23eb..778ca0f0 100644 --- a/contracts/remappings.txt +++ b/contracts/remappings.txt @@ -4,3 +4,4 @@ murky/=lib/murky/src/ oz-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/ oz-contracts/=lib/murky/lib/openzeppelin-contracts/ prb-test/=lib/prb-test/src/ +@hypercerts/protocol/=src/protocol/ diff --git a/contracts/src/AllowlistMinter.sol b/contracts/src/AllowlistMinter.sol deleted file mode 100644 index 576b45ee..00000000 --- a/contracts/src/AllowlistMinter.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import { MerkleProofUpgradeable } from "oz-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol"; -import { IAllowlist } from "./interfaces/IAllowlist.sol"; - -import { Errors } from "./libs/Errors.sol"; - -/// @title Interface for hypercert token interactions -/// @author bitbeckers -/// @notice This interface declares the required functionality for a hypercert token -/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) -contract AllowlistMinter is IAllowlist { - event AllowlistCreated(uint256 tokenID, bytes32 root); - event LeafClaimed(uint256 tokenID, bytes32 leaf); - - mapping(uint256 => bytes32) internal merkleRoots; - mapping(uint256 => mapping(bytes32 => bool)) public hasBeenClaimed; - mapping(uint256 => uint256) internal maxUnits; - mapping(uint256 => uint256) internal minted; - - function isAllowedToClaim( - bytes32[] calldata proof, - uint256 claimID, - bytes32 leaf - ) external view returns (bool isAllowed) { - if (merkleRoots[claimID].length == 0) revert Errors.DoesNotExist(); - isAllowed = MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf); - } - - function _createAllowlist(uint256 claimID, bytes32 merkleRoot, uint256 units) internal { - if (merkleRoot == "" || units == 0) revert Errors.Invalid(); - if (merkleRoots[claimID] != "") revert Errors.DuplicateEntry(); - - merkleRoots[claimID] = merkleRoot; - maxUnits[claimID] = units; - emit AllowlistCreated(claimID, merkleRoot); - } - - function _processClaim(bytes32[] calldata proof, uint256 claimID, uint256 amount) internal { - if (merkleRoots[claimID].length == 0) revert Errors.DoesNotExist(); - - bytes32 leaf = _calculateLeaf(msg.sender, amount); - - if (hasBeenClaimed[claimID][leaf]) revert Errors.AlreadyClaimed(); - if ( - !MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf) || - (minted[claimID] + amount) > maxUnits[claimID] - ) revert Errors.Invalid(); - hasBeenClaimed[claimID][leaf] = true; - - emit LeafClaimed(claimID, leaf); - } - - function _calculateLeaf(address account, uint256 amount) internal pure returns (bytes32 leaf) { - leaf = keccak256(bytes.concat(keccak256(abi.encode(account, amount)))); - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - * Assuming 30 available slots (slots cost space, cost gas) - * 1. merkleRoots - * 2. hasBeenClaimed - * 3. maxUnits - * 4. minted - */ - uint256[26] private __gap; -} diff --git a/contracts/src/interfaces/IAllowlist.sol b/contracts/src/interfaces/IAllowlist.sol deleted file mode 100644 index fe4a9ec4..00000000 --- a/contracts/src/interfaces/IAllowlist.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -/// @title Interface for allowlist -/// @author bitbeckers -/// @notice This interface declares the required functionality for a hypercert token -/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) -interface IAllowlist { - function isAllowedToClaim( - bytes32[] calldata proof, - uint256 tokenID, - bytes32 leaf - ) external view returns (bool isAllowed); -} diff --git a/contracts/src/libs/Errors.sol b/contracts/src/libs/Errors.sol deleted file mode 100644 index e19d6b5c..00000000 --- a/contracts/src/libs/Errors.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -/// @author bitbeckers -library Errors { - error AlreadyClaimed(); - error ArraySize(); - error DoesNotExist(); - error DuplicateEntry(); - error Invalid(); - error NotAllowed(); - error NotApprovedOrOwner(); - error TransfersNotAllowed(); - error TypeMismatch(); -} diff --git a/contracts/contracts/AllowlistMinter.sol b/contracts/src/protocol/AllowlistMinter.sol similarity index 100% rename from contracts/contracts/AllowlistMinter.sol rename to contracts/src/protocol/AllowlistMinter.sol diff --git a/contracts/src/HypercertMinter.sol b/contracts/src/protocol/HypercertMinter.sol similarity index 100% rename from contracts/src/HypercertMinter.sol rename to contracts/src/protocol/HypercertMinter.sol diff --git a/contracts/src/HypercertTrader.sol b/contracts/src/protocol/HypercertTrader.sol similarity index 100% rename from contracts/src/HypercertTrader.sol rename to contracts/src/protocol/HypercertTrader.sol diff --git a/contracts/src/SemiFungible1155.sol b/contracts/src/protocol/SemiFungible1155.sol similarity index 100% rename from contracts/src/SemiFungible1155.sol rename to contracts/src/protocol/SemiFungible1155.sol diff --git a/contracts/contracts/interfaces/IAllowlist.sol b/contracts/src/protocol/interfaces/IAllowlist.sol similarity index 100% rename from contracts/contracts/interfaces/IAllowlist.sol rename to contracts/src/protocol/interfaces/IAllowlist.sol diff --git a/contracts/src/interfaces/IHypercertToken.sol b/contracts/src/protocol/interfaces/IHypercertToken.sol similarity index 100% rename from contracts/src/interfaces/IHypercertToken.sol rename to contracts/src/protocol/interfaces/IHypercertToken.sol diff --git a/contracts/src/interfaces/IHypercertTrader.sol b/contracts/src/protocol/interfaces/IHypercertTrader.sol similarity index 100% rename from contracts/src/interfaces/IHypercertTrader.sol rename to contracts/src/protocol/interfaces/IHypercertTrader.sol diff --git a/contracts/contracts/libs/Errors.sol b/contracts/src/protocol/libs/Errors.sol similarity index 100% rename from contracts/contracts/libs/Errors.sol rename to contracts/src/protocol/libs/Errors.sol diff --git a/contracts/test/foundry/AllowlistMinter.t.sol b/contracts/test/foundry/AllowlistMinter.t.sol index 7ccb3aa9..8aecd6e7 100644 --- a/contracts/test/foundry/AllowlistMinter.t.sol +++ b/contracts/test/foundry/AllowlistMinter.t.sol @@ -5,8 +5,8 @@ import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; -import { AllowlistMinter } from "../../src/AllowlistMinter.sol"; -import { Errors } from "../../src/libs/Errors.sol"; +import { AllowlistMinter } from "@hypercerts/protocol/AllowlistMinter.sol"; +import { Errors } from "@hypercerts/protocol/libs/Errors.sol"; import { Merkle } from "murky/Merkle.sol"; diff --git a/contracts/test/foundry/HypercertMinter.batchminting.t.sol b/contracts/test/foundry/HypercertMinter.batchminting.t.sol index b5349919..d58f0276 100644 --- a/contracts/test/foundry/HypercertMinter.batchminting.t.sol +++ b/contracts/test/foundry/HypercertMinter.batchminting.t.sol @@ -4,11 +4,11 @@ pragma solidity ^0.8.16; import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; //solhint-disable-next-line max-line-length import { ERC1155HolderUpgradeable } from "openzeppelin-contracts-upgradeable/contracts/token/ERC1155/utils/ERC1155HolderUpgradeable.sol"; import { Merkle } from "murky/Merkle.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; contract BatchMintingHelper is Merkle, ERC1155HolderUpgradeable { event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values); diff --git a/contracts/test/foundry/HypercertMinter.pausable.t.sol b/contracts/test/foundry/HypercertMinter.pausable.t.sol index 716c8c5f..ae849161 100644 --- a/contracts/test/foundry/HypercertMinter.pausable.t.sol +++ b/contracts/test/foundry/HypercertMinter.pausable.t.sol @@ -4,8 +4,8 @@ pragma solidity ^0.8.16; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; contract PausableTestHelper { /** diff --git a/contracts/test/foundry/HypercertMinter.t.sol b/contracts/test/foundry/HypercertMinter.t.sol index ad15aada..6647ffc0 100644 --- a/contracts/test/foundry/HypercertMinter.t.sol +++ b/contracts/test/foundry/HypercertMinter.t.sol @@ -5,8 +5,8 @@ import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; import { Merkle } from "murky/Merkle.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; contract MinterTestHelper { event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits); diff --git a/contracts/test/foundry/HypercertMinter.transfers.t.sol b/contracts/test/foundry/HypercertMinter.transfers.t.sol index 7c74edb1..f4b3ff9b 100644 --- a/contracts/test/foundry/HypercertMinter.transfers.t.sol +++ b/contracts/test/foundry/HypercertMinter.transfers.t.sol @@ -4,9 +4,9 @@ pragma solidity ^0.8.16; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; -import { Errors } from "../../src/libs/Errors.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { Errors } from "@hypercerts/protocol/libs/Errors.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; /// @dev Testing transfer restrictions on hypercerts contract HypercertMinterTransferTest is PRBTest, StdCheats, StdUtils { diff --git a/contracts/test/foundry/HypercertTrader.admin.t.sol b/contracts/test/foundry/HypercertTrader.admin.t.sol index 3b7ee0eb..817a6bb9 100644 --- a/contracts/test/foundry/HypercertTrader.admin.t.sol +++ b/contracts/test/foundry/HypercertTrader.admin.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { HypercertTrader } from "../../src/HypercertTrader.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { HypercertTrader } from "@hypercerts/protocol/HypercertTrader.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; diff --git a/contracts/test/foundry/HypercertTrader.offers.t.sol b/contracts/test/foundry/HypercertTrader.offers.t.sol index 6901b314..a348e9ed 100644 --- a/contracts/test/foundry/HypercertTrader.offers.t.sol +++ b/contracts/test/foundry/HypercertTrader.offers.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { HypercertTrader } from "../../src/HypercertTrader.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { HypercertTrader } from "@hypercerts/protocol/HypercertTrader.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; diff --git a/contracts/test/foundry/HypercertTrader.sales.t.sol b/contracts/test/foundry/HypercertTrader.sales.t.sol index 07c0216a..48f65355 100644 --- a/contracts/test/foundry/HypercertTrader.sales.t.sol +++ b/contracts/test/foundry/HypercertTrader.sales.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { HypercertTrader } from "../../src/HypercertTrader.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { HypercertTrader } from "@hypercerts/protocol/HypercertTrader.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; diff --git a/contracts/test/foundry/PerformanceTesting.t.sol b/contracts/test/foundry/PerformanceTesting.t.sol index 7ed5b2df..7b2a71d3 100644 --- a/contracts/test/foundry/PerformanceTesting.t.sol +++ b/contracts/test/foundry/PerformanceTesting.t.sol @@ -4,9 +4,9 @@ pragma solidity ^0.8.16; import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; import { Merkle } from "murky/Merkle.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; // forge test -vv --match-path test/foundry/PerformanceTesting.t.sol diff --git a/contracts/test/foundry/SemiFungibleHelper.sol b/contracts/test/foundry/SemiFungibleHelper.sol index 3a702e8b..7555bc9d 100644 --- a/contracts/test/foundry/SemiFungibleHelper.sol +++ b/contracts/test/foundry/SemiFungibleHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { SemiFungible1155 } from "../../src/SemiFungible1155.sol"; +import { SemiFungible1155 } from "@hypercerts/protocol/SemiFungible1155.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; From 850036e7124ada07937a09a6371df78a4926fdbf Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Wed, 25 Oct 2023 16:55:30 +0200 Subject: [PATCH 12/49] chore(prep): tests to protocol dir and remappings --- contracts/remappings.txt | 1 + contracts/test/foundry/{ => protocol}/AllowlistMinter.t.sol | 0 contracts/test/foundry/{ => protocol}/Bitshifting.t.sol | 0 .../foundry/{ => protocol}/HypercertMinter.batchminting.t.sol | 0 .../test/foundry/{ => protocol}/HypercertMinter.pausable.t.sol | 0 contracts/test/foundry/{ => protocol}/HypercertMinter.t.sol | 0 .../test/foundry/{ => protocol}/HypercertMinter.transfers.t.sol | 0 .../test/foundry/{ => protocol}/HypercertTrader.admin.t.sol | 0 .../test/foundry/{ => protocol}/HypercertTrader.offers.t.sol | 0 .../test/foundry/{ => protocol}/HypercertTrader.sales.t.sol | 0 contracts/test/foundry/{ => protocol}/PerformanceTesting.t.sol | 0 .../foundry/{ => protocol}/SemiFungible1155.allowances.t.sol | 0 .../test/foundry/{ => protocol}/SemiFungible1155.burning.t.sol | 0 .../test/foundry/{ => protocol}/SemiFungible1155.minting.t.sol | 0 contracts/test/foundry/{ => protocol}/SemiFungible1155.t.sol | 0 .../test/foundry/{ => protocol}/SemiFungible1155.transfers.t.sol | 0 contracts/test/foundry/{ => protocol}/SemiFungible1155.units.sol | 0 contracts/test/foundry/{ => protocol}/SemiFungibleHelper.sol | 0 18 files changed, 1 insertion(+) rename contracts/test/foundry/{ => protocol}/AllowlistMinter.t.sol (100%) rename contracts/test/foundry/{ => protocol}/Bitshifting.t.sol (100%) rename contracts/test/foundry/{ => protocol}/HypercertMinter.batchminting.t.sol (100%) rename contracts/test/foundry/{ => protocol}/HypercertMinter.pausable.t.sol (100%) rename contracts/test/foundry/{ => protocol}/HypercertMinter.t.sol (100%) rename contracts/test/foundry/{ => protocol}/HypercertMinter.transfers.t.sol (100%) rename contracts/test/foundry/{ => protocol}/HypercertTrader.admin.t.sol (100%) rename contracts/test/foundry/{ => protocol}/HypercertTrader.offers.t.sol (100%) rename contracts/test/foundry/{ => protocol}/HypercertTrader.sales.t.sol (100%) rename contracts/test/foundry/{ => protocol}/PerformanceTesting.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.allowances.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.burning.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.minting.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.transfers.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.units.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungibleHelper.sol (100%) diff --git a/contracts/remappings.txt b/contracts/remappings.txt index 778ca0f0..2d7e0dcb 100644 --- a/contracts/remappings.txt +++ b/contracts/remappings.txt @@ -5,3 +5,4 @@ oz-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/ oz-contracts/=lib/murky/lib/openzeppelin-contracts/ prb-test/=lib/prb-test/src/ @hypercerts/protocol/=src/protocol/ +@hypercerts/marketplace/=src/marketplace/ \ No newline at end of file diff --git a/contracts/test/foundry/AllowlistMinter.t.sol b/contracts/test/foundry/protocol/AllowlistMinter.t.sol similarity index 100% rename from contracts/test/foundry/AllowlistMinter.t.sol rename to contracts/test/foundry/protocol/AllowlistMinter.t.sol diff --git a/contracts/test/foundry/Bitshifting.t.sol b/contracts/test/foundry/protocol/Bitshifting.t.sol similarity index 100% rename from contracts/test/foundry/Bitshifting.t.sol rename to contracts/test/foundry/protocol/Bitshifting.t.sol diff --git a/contracts/test/foundry/HypercertMinter.batchminting.t.sol b/contracts/test/foundry/protocol/HypercertMinter.batchminting.t.sol similarity index 100% rename from contracts/test/foundry/HypercertMinter.batchminting.t.sol rename to contracts/test/foundry/protocol/HypercertMinter.batchminting.t.sol diff --git a/contracts/test/foundry/HypercertMinter.pausable.t.sol b/contracts/test/foundry/protocol/HypercertMinter.pausable.t.sol similarity index 100% rename from contracts/test/foundry/HypercertMinter.pausable.t.sol rename to contracts/test/foundry/protocol/HypercertMinter.pausable.t.sol diff --git a/contracts/test/foundry/HypercertMinter.t.sol b/contracts/test/foundry/protocol/HypercertMinter.t.sol similarity index 100% rename from contracts/test/foundry/HypercertMinter.t.sol rename to contracts/test/foundry/protocol/HypercertMinter.t.sol diff --git a/contracts/test/foundry/HypercertMinter.transfers.t.sol b/contracts/test/foundry/protocol/HypercertMinter.transfers.t.sol similarity index 100% rename from contracts/test/foundry/HypercertMinter.transfers.t.sol rename to contracts/test/foundry/protocol/HypercertMinter.transfers.t.sol diff --git a/contracts/test/foundry/HypercertTrader.admin.t.sol b/contracts/test/foundry/protocol/HypercertTrader.admin.t.sol similarity index 100% rename from contracts/test/foundry/HypercertTrader.admin.t.sol rename to contracts/test/foundry/protocol/HypercertTrader.admin.t.sol diff --git a/contracts/test/foundry/HypercertTrader.offers.t.sol b/contracts/test/foundry/protocol/HypercertTrader.offers.t.sol similarity index 100% rename from contracts/test/foundry/HypercertTrader.offers.t.sol rename to contracts/test/foundry/protocol/HypercertTrader.offers.t.sol diff --git a/contracts/test/foundry/HypercertTrader.sales.t.sol b/contracts/test/foundry/protocol/HypercertTrader.sales.t.sol similarity index 100% rename from contracts/test/foundry/HypercertTrader.sales.t.sol rename to contracts/test/foundry/protocol/HypercertTrader.sales.t.sol diff --git a/contracts/test/foundry/PerformanceTesting.t.sol b/contracts/test/foundry/protocol/PerformanceTesting.t.sol similarity index 100% rename from contracts/test/foundry/PerformanceTesting.t.sol rename to contracts/test/foundry/protocol/PerformanceTesting.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.allowances.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.allowances.t.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.allowances.t.sol rename to contracts/test/foundry/protocol/SemiFungible1155.allowances.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.burning.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.burning.t.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.burning.t.sol rename to contracts/test/foundry/protocol/SemiFungible1155.burning.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.minting.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.minting.t.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.minting.t.sol rename to contracts/test/foundry/protocol/SemiFungible1155.minting.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.t.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.t.sol rename to contracts/test/foundry/protocol/SemiFungible1155.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.transfers.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.transfers.t.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.transfers.t.sol rename to contracts/test/foundry/protocol/SemiFungible1155.transfers.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.units.sol b/contracts/test/foundry/protocol/SemiFungible1155.units.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.units.sol rename to contracts/test/foundry/protocol/SemiFungible1155.units.sol diff --git a/contracts/test/foundry/SemiFungibleHelper.sol b/contracts/test/foundry/protocol/SemiFungibleHelper.sol similarity index 100% rename from contracts/test/foundry/SemiFungibleHelper.sol rename to contracts/test/foundry/protocol/SemiFungibleHelper.sol From b893aef52705faf4f129b4fcb26720a7a26a6ab5 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Wed, 25 Oct 2023 17:03:20 +0200 Subject: [PATCH 13/49] chore(license): MIT license --- contracts/LICENSE.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/contracts/LICENSE.md b/contracts/LICENSE.md index 054bdbe3..1234b4cf 100644 --- a/contracts/LICENSE.md +++ b/contracts/LICENSE.md @@ -1,6 +1,11 @@ MIT License -Copyright (c) 2022 Paul Razvan Berg +Copyright (c) 2022 Paul Razvan Berg for inital template: /~https://github.com/paulrberg/foundry-template + +Copyright (c) 2022 LooksRare for portions of marketplace: /~https://github.com/LooksRare/contracts-exchange-v2 commit: +7fca565 + +Copyright (c) 2022 Hypercerts Foundation: Hypercerts protocol and marketplace. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the From 70a4bbd3e23b6d372c69dfe1399be36140033d17 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Fri, 27 Oct 2023 18:20:54 +0200 Subject: [PATCH 14/49] Feat/init marketplace (#1139) * chore(prep): protocol contracts to protocol dir * chore(prep): tests to protocol dir and remappings * chore(license): MIT license * feat(marketplace): inject, build, refactor, test * chore(gha): run gha on push and develop-branches * fix(build): build and lint errors * chore(pnpm): refresh lock file * chore(build): reduce turbo concurrency * fix(build): whac a mole * chore(build): restore prettier in solhint * chore(build): env.template vars * chore(dist): clean and remap output contracts * chore(clean): last tests * fix(build): ignore cors-proxy type errors * chore(gha): add rpc env vars for fork testing --------- Co-authored-by: jipstavenuiter --- .github/workflows/ci-default.yml | 8 +- contracts/.env.example | 6 +- contracts/.solhint.json | 6 +- contracts/LICENSE.md | 7 +- contracts/contracts/HypercertMinter.sol | 229 --- contracts/contracts/SemiFungible1155.sol | 433 ----- .../contracts/interfaces/IHypercertToken.sol | 62 - contracts/foundry.toml | 15 +- contracts/hardhat.config.ts | 6 +- .../.eslintrc | 31 +- contracts/package.json | 8 +- contracts/remappings.txt | 5 + contracts/src/AllowlistMinter.sol | 70 - contracts/src/HypercertTrader.sol | 405 ---- contracts/src/index.ts | 10 +- contracts/src/interfaces/IAllowlist.sol | 14 - contracts/src/interfaces/IHypercertTrader.sol | 128 -- contracts/src/libs/Errors.sol | 15 - .../BatchOrderTypehashRegistry.sol | 54 + .../CreatorFeeManagerWithRebates.sol | 94 + .../CreatorFeeManagerWithRoyalties.sol | 96 + contracts/src/marketplace/CurrencyManager.sol | 37 + .../src/marketplace/ExecutionManager.sol | 305 +++ .../src/marketplace/InheritedStrategy.sol | 88 + .../src/marketplace/LooksRareProtocol.sol | 626 +++++++ contracts/src/marketplace/NonceManager.sol | 115 ++ .../src/marketplace/ProtocolFeeRecipient.sol | 54 + contracts/src/marketplace/StrategyManager.sol | 126 ++ contracts/src/marketplace/TransferManager.sol | 376 ++++ .../src/marketplace/TransferSelectorNFT.sol | 69 + .../constants/AssemblyConstants.sol | 42 + .../constants/NumericConstants.sol | 14 + .../constants/ValidationCodeConstants.sol | 313 ++++ .../src/marketplace/enums/CollectionType.sol | 13 + contracts/src/marketplace/enums/QuoteType.sol | 10 + .../marketplace/errors/ChainlinkErrors.sol | 41 + .../src/marketplace/errors/SharedErrors.sol | 65 + .../executionStrategies/BaseStrategy.sol | 46 + .../BaseStrategyChainlinkPriceLatency.sol | 33 + .../StrategyChainlinkUSDDynamicAsk.sol | 159 ++ .../StrategyCollectionOffer.sol | 138 ++ .../StrategyDutchAuction.sol | 104 ++ .../StrategyItemIdsRange.sol | 116 ++ .../marketplace/helpers/OrderValidatorV2A.sol | 865 +++++++++ .../marketplace/helpers/ProtocolHelpers.sol | 89 + .../interfaces/ICreatorFeeManager.sol | 36 + .../interfaces/ICurrencyManager.sol | 15 + .../interfaces/IExecutionManager.sol | 53 + .../interfaces/IImmutableCreate2Factory.sol | 9 + .../interfaces/ILooksRareProtocol.sol | 180 ++ .../marketplace/interfaces/INonceManager.sol | 40 + .../interfaces/IRoyaltyFeeRegistry.sol | 20 + .../src/marketplace/interfaces/IStrategy.sol | 30 + .../interfaces/IStrategyManager.sol | 80 + .../interfaces/ITransferManager.sol | 84 + .../libraries/CurrencyValidator.sol | 34 + .../MerkleProofCalldataWithNodes.sol | 60 + .../OpenZeppelin/MerkleProofMemory.sol | 51 + .../marketplace/libraries/OrderStructs.sol | 167 ++ .../protocol}/AllowlistMinter.sol | 0 .../src/{ => protocol}/HypercertMinter.sol | 0 .../src/{ => protocol}/SemiFungible1155.sol | 0 .../protocol}/interfaces/IAllowlist.sol | 0 .../interfaces/IHypercertToken.sol | 0 .../protocol}/libs/Errors.sol | 0 .../test/foundry/HypercertTrader.admin.t.sol | 88 - .../test/foundry/HypercertTrader.offers.t.sol | 204 -- .../test/foundry/HypercertTrader.sales.t.sol | 241 --- .../BatchMakerCollectionOrders.t.sol | 114 ++ .../marketplace/BatchMakerOrders.t.sol | 413 ++++ .../BatchOrderTypehashRegistry.t.sol | 143 ++ .../marketplace/BundleTransactions.t.sol | 290 +++ .../CreatorFeeManagerWithRebates.t.sol | 260 +++ .../CreatorFeeManagerWithRoyalties.t.sol | 402 ++++ .../foundry/marketplace/CurrencyManager.t.sol | 42 + .../DelegationRecipientsTaker.t.sol | 181 ++ .../marketplace/DomainSeparatorUpdates.t.sol | 111 ++ .../marketplace/ExecutionManager.t.sol | 296 +++ .../foundry/marketplace/GasGriefing.t.sol | 147 ++ .../foundry/marketplace/InitialStates.t.sol | 55 + .../marketplace/LooksRareProtocol.t.sol | 292 +++ .../marketplace/NonceInvalidation.t.sol | 374 ++++ .../marketplace/OrderValidatorV2A.t.sol | 412 ++++ .../foundry/marketplace/ProtocolBase.t.sol | 274 +++ .../marketplace/ProtocolFeeRecipient.t.sol | 111 ++ .../test/foundry/marketplace/Sandbox.t.sol | 154 ++ .../marketplace/SignaturesEIP2098.t.sol | 66 + .../SignaturesERC1271WalletForERC1155.t.sol | 481 +++++ .../SignaturesERC1271WalletForERC721.t.sol | 313 ++++ .../marketplace/SignaturesRevertions.t.sol | 192 ++ .../marketplace/StandardTransactions.t.sol | 555 ++++++ .../foundry/marketplace/StrategyManager.t.sol | 239 +++ .../foundry/marketplace/TransferManager.t.sol | 535 ++++++ ...ifyOrderTimestampValidityEquivalence.t.sol | 87 + .../Chainlink/USDDynamicAskOrders.t.sol | 483 +++++ .../CollectionOffers.t.sol | 458 +++++ .../DutchAuctionOrders.t.sol | 436 +++++ .../ItemIdsRangeOrders.t.sol | 482 +++++ .../MultiFillCollectionOrders.t.sol | 194 ++ .../foundry/marketplace/utils/BytesLib.sol | 73 + .../marketplace/utils/EIP712MerkleTree.sol | 121 ++ .../marketplace/utils/ERC1271Wallet.sol | 22 + .../foundry/marketplace/utils/GasGriefer.sol | 15 + .../utils/MaliciousERC1271Wallet.sol | 68 + ...MaliciousIsValidSignatureERC1271Wallet.sol | 20 + ...aliciousOnERC1155ReceivedERC1271Wallet.sol | 38 + ...C1155ReceivedTheThirdTimeERC1271Wallet.sol | 24 + .../foundry/marketplace/utils/MathLib.sol | 50 + .../marketplace/utils/MerkleWithPosition.sol | 156 ++ .../marketplace/utils/MockOrderGenerator.sol | 147 ++ .../marketplace/utils/ProtocolHelpers.sol | 109 ++ .../StrategyTestMultiFillCollectionOrder.sol | 77 + .../foundry/marketplace/utils/TestHelpers.sol | 26 + .../marketplace/utils/TestParameters.sol | 58 + .../{ => protocol}/AllowlistMinter.t.sol | 4 +- .../foundry/{ => protocol}/Bitshifting.t.sol | 0 .../HypercertMinter.batchminting.t.sol | 4 +- .../HypercertMinter.pausable.t.sol | 4 +- .../{ => protocol}/HypercertMinter.t.sol | 8 +- .../HypercertMinter.transfers.t.sol | 6 +- .../{ => protocol}/PerformanceTesting.t.sol | 4 +- .../SemiFungible1155.allowances.t.sol | 0 .../SemiFungible1155.burning.t.sol | 0 .../SemiFungible1155.minting.t.sol | 0 .../{ => protocol}/SemiFungible1155.t.sol | 0 .../SemiFungible1155.transfers.t.sol | 0 .../{ => protocol}/SemiFungible1155.units.sol | 0 .../{ => protocol}/SemiFungibleHelper.sol | 2 +- .../test/mock/MockChainlinkAggregator.sol | 31 + contracts/test/mock/MockERC1155.sol | 29 + .../mock/MockERC1155SupportsNoInterface.sol | 10 + .../mock/MockERC1155WithoutAnyBalanceOf.sol | 21 + .../mock/MockERC1155WithoutBalanceOfBatch.sol | 10 + .../MockERC1155WithoutIsApprovedForAll.sol | 21 + contracts/test/mock/MockERC20.sol | 10 + contracts/test/mock/MockERC721.sol | 31 + .../mock/MockERC721SupportsNoInterface.sol | 10 + .../test/mock/MockERC721WithRoyalties.sol | 53 + .../test/mock/MockRoyaltyFeeRegistry.sol | 97 + contracts/test/mock/MockSmartWallet.sol | 65 + contracts/tsconfig.build.json | 10 +- contracts/tsconfig.json | 10 +- cors-proxy/src/index.ts | 3 + defender/package.json | 8 +- .../api/contracts/AllowlistMinter.md | 75 +- .../api/contracts/HypercertMinter.md | 728 +++++--- .../api/contracts/SemiFungible1155.md | 393 ++-- .../api/contracts/interfaces/IAllowlist.md | 28 +- .../contracts/interfaces/IHypercertToken.md | 149 +- .../developer/api/contracts/libs/Errors.md | 57 +- graph/abis/HypercertTrader.json | 656 ------- .../HypercertTrader/HypercertTrader.ts | 954 ---------- graph/networks.json | 4 - graph/src/hypercert-trader.ts | 73 - graph/src/utils.ts | 1 - graph/subgraph.yaml | 24 - graph/tests/.latest.json | 2 +- graph/tests/hypercert-trader-utils.ts | 261 --- graph/tests/hypercert-trader.test.ts | 80 - pnpm-lock.yaml | 1654 ++++++++++------- 160 files changed, 16901 insertions(+), 5223 deletions(-) delete mode 100644 contracts/contracts/HypercertMinter.sol delete mode 100644 contracts/contracts/SemiFungible1155.sol delete mode 100644 contracts/contracts/interfaces/IHypercertToken.sol delete mode 100644 contracts/src/AllowlistMinter.sol delete mode 100644 contracts/src/HypercertTrader.sol delete mode 100644 contracts/src/interfaces/IAllowlist.sol delete mode 100644 contracts/src/interfaces/IHypercertTrader.sol delete mode 100644 contracts/src/libs/Errors.sol create mode 100644 contracts/src/marketplace/BatchOrderTypehashRegistry.sol create mode 100644 contracts/src/marketplace/CreatorFeeManagerWithRebates.sol create mode 100644 contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol create mode 100644 contracts/src/marketplace/CurrencyManager.sol create mode 100644 contracts/src/marketplace/ExecutionManager.sol create mode 100644 contracts/src/marketplace/InheritedStrategy.sol create mode 100644 contracts/src/marketplace/LooksRareProtocol.sol create mode 100644 contracts/src/marketplace/NonceManager.sol create mode 100644 contracts/src/marketplace/ProtocolFeeRecipient.sol create mode 100644 contracts/src/marketplace/StrategyManager.sol create mode 100644 contracts/src/marketplace/TransferManager.sol create mode 100644 contracts/src/marketplace/TransferSelectorNFT.sol create mode 100644 contracts/src/marketplace/constants/AssemblyConstants.sol create mode 100644 contracts/src/marketplace/constants/NumericConstants.sol create mode 100644 contracts/src/marketplace/constants/ValidationCodeConstants.sol create mode 100644 contracts/src/marketplace/enums/CollectionType.sol create mode 100644 contracts/src/marketplace/enums/QuoteType.sol create mode 100644 contracts/src/marketplace/errors/ChainlinkErrors.sol create mode 100644 contracts/src/marketplace/errors/SharedErrors.sol create mode 100644 contracts/src/marketplace/executionStrategies/BaseStrategy.sol create mode 100644 contracts/src/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.sol create mode 100644 contracts/src/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol create mode 100644 contracts/src/marketplace/executionStrategies/StrategyCollectionOffer.sol create mode 100644 contracts/src/marketplace/executionStrategies/StrategyDutchAuction.sol create mode 100644 contracts/src/marketplace/executionStrategies/StrategyItemIdsRange.sol create mode 100644 contracts/src/marketplace/helpers/OrderValidatorV2A.sol create mode 100644 contracts/src/marketplace/helpers/ProtocolHelpers.sol create mode 100644 contracts/src/marketplace/interfaces/ICreatorFeeManager.sol create mode 100644 contracts/src/marketplace/interfaces/ICurrencyManager.sol create mode 100644 contracts/src/marketplace/interfaces/IExecutionManager.sol create mode 100644 contracts/src/marketplace/interfaces/IImmutableCreate2Factory.sol create mode 100644 contracts/src/marketplace/interfaces/ILooksRareProtocol.sol create mode 100644 contracts/src/marketplace/interfaces/INonceManager.sol create mode 100644 contracts/src/marketplace/interfaces/IRoyaltyFeeRegistry.sol create mode 100644 contracts/src/marketplace/interfaces/IStrategy.sol create mode 100644 contracts/src/marketplace/interfaces/IStrategyManager.sol create mode 100644 contracts/src/marketplace/interfaces/ITransferManager.sol create mode 100644 contracts/src/marketplace/libraries/CurrencyValidator.sol create mode 100644 contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol create mode 100644 contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofMemory.sol create mode 100644 contracts/src/marketplace/libraries/OrderStructs.sol rename contracts/{contracts => src/protocol}/AllowlistMinter.sol (100%) rename contracts/src/{ => protocol}/HypercertMinter.sol (100%) rename contracts/src/{ => protocol}/SemiFungible1155.sol (100%) rename contracts/{contracts => src/protocol}/interfaces/IAllowlist.sol (100%) rename contracts/src/{ => protocol}/interfaces/IHypercertToken.sol (100%) rename contracts/{contracts => src/protocol}/libs/Errors.sol (100%) delete mode 100644 contracts/test/foundry/HypercertTrader.admin.t.sol delete mode 100644 contracts/test/foundry/HypercertTrader.offers.t.sol delete mode 100644 contracts/test/foundry/HypercertTrader.sales.t.sol create mode 100644 contracts/test/foundry/marketplace/BatchMakerCollectionOrders.t.sol create mode 100644 contracts/test/foundry/marketplace/BatchMakerOrders.t.sol create mode 100644 contracts/test/foundry/marketplace/BatchOrderTypehashRegistry.t.sol create mode 100644 contracts/test/foundry/marketplace/BundleTransactions.t.sol create mode 100644 contracts/test/foundry/marketplace/CreatorFeeManagerWithRebates.t.sol create mode 100644 contracts/test/foundry/marketplace/CreatorFeeManagerWithRoyalties.t.sol create mode 100644 contracts/test/foundry/marketplace/CurrencyManager.t.sol create mode 100644 contracts/test/foundry/marketplace/DelegationRecipientsTaker.t.sol create mode 100644 contracts/test/foundry/marketplace/DomainSeparatorUpdates.t.sol create mode 100644 contracts/test/foundry/marketplace/ExecutionManager.t.sol create mode 100644 contracts/test/foundry/marketplace/GasGriefing.t.sol create mode 100644 contracts/test/foundry/marketplace/InitialStates.t.sol create mode 100644 contracts/test/foundry/marketplace/LooksRareProtocol.t.sol create mode 100644 contracts/test/foundry/marketplace/NonceInvalidation.t.sol create mode 100644 contracts/test/foundry/marketplace/OrderValidatorV2A.t.sol create mode 100644 contracts/test/foundry/marketplace/ProtocolBase.t.sol create mode 100644 contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol create mode 100644 contracts/test/foundry/marketplace/Sandbox.t.sol create mode 100644 contracts/test/foundry/marketplace/SignaturesEIP2098.t.sol create mode 100644 contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC1155.t.sol create mode 100644 contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC721.t.sol create mode 100644 contracts/test/foundry/marketplace/SignaturesRevertions.t.sol create mode 100644 contracts/test/foundry/marketplace/StandardTransactions.t.sol create mode 100644 contracts/test/foundry/marketplace/StrategyManager.t.sol create mode 100644 contracts/test/foundry/marketplace/TransferManager.t.sol create mode 100644 contracts/test/foundry/marketplace/assembly/VerifyOrderTimestampValidityEquivalence.t.sol create mode 100644 contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol create mode 100644 contracts/test/foundry/marketplace/executionStrategies/CollectionOffers.t.sol create mode 100644 contracts/test/foundry/marketplace/executionStrategies/DutchAuctionOrders.t.sol create mode 100644 contracts/test/foundry/marketplace/executionStrategies/ItemIdsRangeOrders.t.sol create mode 100644 contracts/test/foundry/marketplace/executionStrategies/MultiFillCollectionOrders.t.sol create mode 100644 contracts/test/foundry/marketplace/utils/BytesLib.sol create mode 100644 contracts/test/foundry/marketplace/utils/EIP712MerkleTree.sol create mode 100644 contracts/test/foundry/marketplace/utils/ERC1271Wallet.sol create mode 100644 contracts/test/foundry/marketplace/utils/GasGriefer.sol create mode 100644 contracts/test/foundry/marketplace/utils/MaliciousERC1271Wallet.sol create mode 100644 contracts/test/foundry/marketplace/utils/MaliciousIsValidSignatureERC1271Wallet.sol create mode 100644 contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol create mode 100644 contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol create mode 100644 contracts/test/foundry/marketplace/utils/MathLib.sol create mode 100644 contracts/test/foundry/marketplace/utils/MerkleWithPosition.sol create mode 100644 contracts/test/foundry/marketplace/utils/MockOrderGenerator.sol create mode 100644 contracts/test/foundry/marketplace/utils/ProtocolHelpers.sol create mode 100644 contracts/test/foundry/marketplace/utils/StrategyTestMultiFillCollectionOrder.sol create mode 100644 contracts/test/foundry/marketplace/utils/TestHelpers.sol create mode 100644 contracts/test/foundry/marketplace/utils/TestParameters.sol rename contracts/test/foundry/{ => protocol}/AllowlistMinter.t.sol (97%) rename contracts/test/foundry/{ => protocol}/Bitshifting.t.sol (100%) rename contracts/test/foundry/{ => protocol}/HypercertMinter.batchminting.t.sol (98%) rename contracts/test/foundry/{ => protocol}/HypercertMinter.pausable.t.sol (96%) rename contracts/test/foundry/{ => protocol}/HypercertMinter.t.sol (94%) rename contracts/test/foundry/{ => protocol}/HypercertMinter.transfers.t.sol (95%) rename contracts/test/foundry/{ => protocol}/PerformanceTesting.t.sol (97%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.allowances.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.burning.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.minting.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.transfers.t.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungible1155.units.sol (100%) rename contracts/test/foundry/{ => protocol}/SemiFungibleHelper.sol (98%) create mode 100644 contracts/test/mock/MockChainlinkAggregator.sol create mode 100644 contracts/test/mock/MockERC1155.sol create mode 100644 contracts/test/mock/MockERC1155SupportsNoInterface.sol create mode 100644 contracts/test/mock/MockERC1155WithoutAnyBalanceOf.sol create mode 100644 contracts/test/mock/MockERC1155WithoutBalanceOfBatch.sol create mode 100644 contracts/test/mock/MockERC1155WithoutIsApprovedForAll.sol create mode 100644 contracts/test/mock/MockERC20.sol create mode 100644 contracts/test/mock/MockERC721.sol create mode 100644 contracts/test/mock/MockERC721SupportsNoInterface.sol create mode 100644 contracts/test/mock/MockERC721WithRoyalties.sol create mode 100644 contracts/test/mock/MockRoyaltyFeeRegistry.sol create mode 100644 contracts/test/mock/MockSmartWallet.sol delete mode 100644 graph/abis/HypercertTrader.json delete mode 100644 graph/generated/HypercertTrader/HypercertTrader.ts delete mode 100644 graph/src/hypercert-trader.ts delete mode 100644 graph/tests/hypercert-trader-utils.ts delete mode 100644 graph/tests/hypercert-trader.test.ts diff --git a/.github/workflows/ci-default.yml b/.github/workflows/ci-default.yml index a7242d72..c25b49e0 100644 --- a/.github/workflows/ci-default.yml +++ b/.github/workflows/ci-default.yml @@ -13,21 +13,19 @@ env: NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }} NEXT_PUBLIC_SUPABASE_TABLE: ${{ vars.NEXT_PUBLIC_SUPABASE_TABLE }} NEXT_PUBLIC_WALLETCONNECT_ID: ${{ secrets.NEXT_PUBLIC_WALLETCONNECT_ID }} + GOERLI_RPC_URL: ${{ vars.GOERLI_RPC_URL }} + MAINNET_RPC_URL: ${{ vars.MAINNET_RPC_URL }} DOCKER_PLATFORM: "amd64" # Trigger the workflow when: on: # A push occurs to one of the matched branches. push: - branches: - - main - - develop - # Or when a pull request event occurs for a pull request against one of the - # matched branches. pull_request: branches: - main - develop + - develop-contracts # Allows you to run this workflow manually from the Actions tab workflow_dispatch: diff --git a/contracts/.env.example b/contracts/.env.example index b7c57fac..8cef70d1 100644 --- a/contracts/.env.example +++ b/contracts/.env.example @@ -2,7 +2,11 @@ MNEMONIC="test test test test test test test test test test test junk" MNEMONIC_CELO=="test test test test test test test test test test test junk" INFURA_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -ALCHEMY_OPTIMISM_URL="https://opt-mainnet.g.alchemy.com/v2/zzzzzzzzzzzzzzzzzzz" + +# RPCs +MAINNET_RPC_URL="" +OPTIMISM_RPC_URL="" +GOERLI_RPC_URL="" # OpenZeppelin OPENZEPPELIN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" diff --git a/contracts/.solhint.json b/contracts/.solhint.json index d60b535e..c7aea11c 100644 --- a/contracts/.solhint.json +++ b/contracts/.solhint.json @@ -2,10 +2,10 @@ "plugins": ["prettier"], "extends": "solhint:recommended", "rules": { - "code-complexity": ["error", 8], - "compiler-version": ["error", "0.8.16"], + "code-complexity": ["error", 12], + "compiler-version": ["error", ">=0.8.16"], "func-visibility": ["error", { "ignoreConstructors": true }], - "max-line-length": ["warn", 120], + "max-line-length": ["warn", 200], "no-console": "off", "not-rely-on-time": "off", "reason-string": ["warn", { "maxLength": 64 }], diff --git a/contracts/LICENSE.md b/contracts/LICENSE.md index 054bdbe3..1234b4cf 100644 --- a/contracts/LICENSE.md +++ b/contracts/LICENSE.md @@ -1,6 +1,11 @@ MIT License -Copyright (c) 2022 Paul Razvan Berg +Copyright (c) 2022 Paul Razvan Berg for inital template: /~https://github.com/paulrberg/foundry-template + +Copyright (c) 2022 LooksRare for portions of marketplace: /~https://github.com/LooksRare/contracts-exchange-v2 commit: +7fca565 + +Copyright (c) 2022 Hypercerts Foundation: Hypercerts protocol and marketplace. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the diff --git a/contracts/contracts/HypercertMinter.sol b/contracts/contracts/HypercertMinter.sol deleted file mode 100644 index 917c02c5..00000000 --- a/contracts/contracts/HypercertMinter.sol +++ /dev/null @@ -1,229 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import { IHypercertToken } from "./interfaces/IHypercertToken.sol"; -import { SemiFungible1155 } from "./SemiFungible1155.sol"; -import { AllowlistMinter } from "./AllowlistMinter.sol"; -import { PausableUpgradeable } from "oz-upgradeable/security/PausableUpgradeable.sol"; - -import { Errors } from "./libs/Errors.sol"; - -/// @title Contract for managing hypercert claims and whitelists -/// @author bitbeckers -/// @notice Implementation of the HypercertTokenInterface using { SemiFungible1155 } as underlying token. -/// @notice This contract supports whitelisted minting via { AllowlistMinter }. -/// @dev Wrapper contract to expose and chain functions. -contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, PausableUpgradeable { - // solhint-disable-next-line const-name-snakecase - string public constant name = "HypercertMinter"; - /// @dev from typeID to a transfer policy - mapping(uint256 => TransferRestrictions) internal typeRestrictions; - - /// INIT - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - function initialize() public virtual initializer { - __SemiFungible1155_init(); - __Pausable_init(); - } - - /// EXTERNAL - - /// @notice Mint a semi-fungible token for the impact claim referenced via `uri` - /// @dev see {IHypercertToken} - function mintClaim( - address account, - uint256 units, - string memory _uri, - TransferRestrictions restrictions - ) external override whenNotPaused { - // This enables us to release this restriction in the future - if (msg.sender != account) revert Errors.NotAllowed(); - uint256 claimID = _mintNewTypeWithToken(account, units, _uri); - typeRestrictions[claimID] = restrictions; - emit ClaimStored(claimID, _uri, units); - } - - /// @notice Mint semi-fungible tokens for the impact claim referenced via `uri` - /// @dev see {IHypercertToken} - function mintClaimWithFractions( - address account, - uint256 units, - uint256[] calldata fractions, - string memory _uri, - TransferRestrictions restrictions - ) external override whenNotPaused { - // This enables us to release this restriction in the future - if (msg.sender != account) revert Errors.NotAllowed(); - //Using sum to compare units and fractions (sanity check) - if (_getSum(fractions) != units) revert Errors.Invalid(); - - uint256 claimID = _mintNewTypeWithTokens(account, fractions, _uri); - typeRestrictions[claimID] = restrictions; - emit ClaimStored(claimID, _uri, units); - } - - /// @notice Mint a semi-fungible token representing a fraction of the claim - /// @dev Calls AllowlistMinter to verify `proof`. - /// @dev Mints the `amount` of units for the hypercert stored under `claimID` - function mintClaimFromAllowlist( - address account, - bytes32[] calldata proof, - uint256 claimID, - uint256 units - ) external whenNotPaused { - _processClaim(proof, claimID, units); - _mintToken(account, claimID, units); - } - - /// @notice Mint semi-fungible tokens representing a fraction of the claims in `claimIDs` - /// @dev Calls AllowlistMinter to verify `proofs`. - /// @dev Mints the `amount` of units for the hypercert stored under `claimIDs` - function batchMintClaimsFromAllowlists( - address account, - bytes32[][] calldata proofs, - uint256[] calldata claimIDs, - uint256[] calldata units - ) external whenNotPaused { - uint256 len = claimIDs.length; - for (uint256 i; i < len; ) { - _processClaim(proofs[i], claimIDs[i], units[i]); - unchecked { - ++i; - } - } - _batchMintTokens(account, claimIDs, units); - } - - /// @notice Register a claim and the whitelist for minting token(s) belonging to that claim - /// @dev Calls SemiFungible1155 to store the claim referenced in `uri` with amount of `units` - /// @dev Calls AllowlistMinter to store the `merkleRoot` as proof to authorize claims - function createAllowlist( - address account, - uint256 units, - bytes32 merkleRoot, - string memory _uri, - TransferRestrictions restrictions - ) external whenNotPaused { - uint256 claimID = _createTokenType(account, units, _uri); - _createAllowlist(claimID, merkleRoot, units); - typeRestrictions[claimID] = restrictions; - emit ClaimStored(claimID, _uri, units); - } - - /// @notice Split a claimtokens value into parts with summed value equal to the original - /// @dev see {IHypercertToken} - function splitFraction( - address _account, - uint256 _tokenID, - uint256[] calldata _newFractions - ) external whenNotPaused { - _splitTokenUnits(_account, _tokenID, _newFractions); - } - - /// @notice Merge the value of tokens belonging to the same claim - /// @dev see {IHypercertToken} - function mergeFractions(address _account, uint256[] calldata _fractionIDs) external whenNotPaused { - _mergeTokensUnits(_account, _fractionIDs); - } - - /// @notice Burn a claimtoken - /// @dev see {IHypercertToken} - function burnFraction(address _account, uint256 _tokenID) external whenNotPaused { - _burnToken(_account, _tokenID); - } - - /// @dev see {IHypercertToken} - function unitsOf(uint256 tokenID) external view override returns (uint256 units) { - units = _unitsOf(tokenID); - } - - /// @dev see {IHypercertToken} - function unitsOf(address account, uint256 tokenID) external view override returns (uint256 units) { - units = _unitsOf(account, tokenID); - } - - /// PAUSABLE - - function pause() external onlyOwner { - _pause(); - } - - function unpause() external onlyOwner { - _unpause(); - } - - /// METADATA - - /// @dev see { IHypercertMetadata} - function uri(uint256 tokenID) public view override(IHypercertToken, SemiFungible1155) returns (string memory _uri) { - _uri = SemiFungible1155.uri(tokenID); - } - - /// TRANSFER RESTRICTIONS - - function readTransferRestriction(uint256 tokenID) external view returns (string memory) { - TransferRestrictions temp = typeRestrictions[getBaseType(tokenID)]; - if (temp == TransferRestrictions.AllowAll) return "AllowAll"; - if (temp == TransferRestrictions.DisallowAll) return "DisallowAll"; - if (temp == TransferRestrictions.FromCreatorOnly) return "FromCreatorOnly"; - return ""; - } - - /// INTERNAL - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol } - function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { - // solhint-disable-previous-line no-empty-blocks - } - - function _beforeTokenTransfer( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual override { - super._beforeTokenTransfer(operator, from, to, ids, amounts, data); - - // By-pass transfer restrictions for minting and burning - if (from == address(0)) { - // Minting - return; - } else if (to == address(0)) { - // Burning - return; - } - - // Transfer case, where to and from are non-zero - uint256 len = ids.length; - for (uint256 i; i < len; ) { - uint256 typeID = getBaseType(ids[i]); - TransferRestrictions policy = typeRestrictions[typeID]; - if (policy == TransferRestrictions.DisallowAll) { - revert Errors.TransfersNotAllowed(); - } else if (policy == TransferRestrictions.FromCreatorOnly && from != creators[typeID]) { - revert Errors.TransfersNotAllowed(); - } - unchecked { - ++i; - } - } - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - * Assuming 30 available slots (slots cost space, cost gas) - * 1. typeRestrictions - */ - uint256[29] private __gap; -} diff --git a/contracts/contracts/SemiFungible1155.sol b/contracts/contracts/SemiFungible1155.sol deleted file mode 100644 index cd88714a..00000000 --- a/contracts/contracts/SemiFungible1155.sol +++ /dev/null @@ -1,433 +0,0 @@ -// SPDX-License-Identifier: MIT -// Used components of Enjin example implementation for mixed fungibility -// /~https://github.com/enjin/erc-1155/blob/master/contracts/ERC1155MixedFungibleMintable.sol -pragma solidity 0.8.16; - -import { ERC1155Upgradeable } from "oz-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; -import { ERC1155BurnableUpgradeable } from "oz-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol"; -import { ERC1155URIStorageUpgradeable } from "oz-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol"; -import { OwnableUpgradeable } from "oz-upgradeable/access/OwnableUpgradeable.sol"; -import { Initializable } from "oz-upgradeable/proxy/utils/Initializable.sol"; -import { UUPSUpgradeable } from "oz-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { Errors } from "./libs/Errors.sol"; - -/// @title Contract for minting semi-fungible EIP1155 tokens -/// @author bitbeckers -/// @notice Extends { Upgradeable1155 } token with semi-fungible properties and the concept of `units` -/// @dev Adds split bit strategy as described in [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155#non-fungible-tokens) -contract SemiFungible1155 is - Initializable, - ERC1155Upgradeable, - ERC1155BurnableUpgradeable, - ERC1155URIStorageUpgradeable, - OwnableUpgradeable, - UUPSUpgradeable -{ - /// @dev Counter used to generate next typeID. - uint256 internal typeCounter; - - /// @dev Bitmask used to expose only upper 128 bits of uint256 - uint256 internal constant TYPE_MASK = type(uint256).max << 128; - - /// @dev Bitmask used to expose only lower 128 bits of uint256 - uint256 internal constant NF_INDEX_MASK = type(uint256).max >> 128; - - uint256 internal constant FRACTION_LIMIT = 253; - - /// @dev Mapping of `tokenID` to address of `owner` - mapping(uint256 => address) internal owners; - - /// @dev Mapping of `tokenID` to address of `creator` - mapping(uint256 => address) internal creators; - - /// @dev Used to determine amount of `units` stored in token at `tokenID` - mapping(uint256 => uint256) internal tokenValues; - - /// @dev Used to find highest index of token belonging to token at `typeID` - mapping(uint256 => uint256) internal maxIndex; - - /// @dev Emitted on transfer of `value` between `fromTokenID` to `toTokenID` of the same `claimID` - event ValueTransfer(uint256 claimID, uint256 fromTokenID, uint256 toTokenID, uint256 value); - - /// @dev Emitted on transfer of `values` between `fromTokenIDs` to `toTokenIDs` of `claimIDs` - event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values); - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - // solhint-disable-next-line func-name-mixedcase - function __SemiFungible1155_init() public virtual onlyInitializing { - __ERC1155_init(""); - __ERC1155Burnable_init(); - __ERC1155URIStorage_init(); - __Ownable_init(); - __UUPSUpgradeable_init(); - } - - /// @dev Get index of fractional token at `_id` by returning lower 128 bit values - /// @dev Returns 0 if `_id` is a baseType - function getItemIndex(uint256 tokenID) internal pure returns (uint256) { - return tokenID & NF_INDEX_MASK; - } - - /// @dev Get base type ID for token at `_id` by returning upper 128 bit values - function getBaseType(uint256 tokenID) internal pure returns (uint256) { - return tokenID & TYPE_MASK; - } - - /// @dev Identify that token at `_id` is base type. - /// @dev Upper 128 bits identify base type ID, lower bits should be 0 - function isBaseType(uint256 tokenID) internal pure returns (bool) { - return (tokenID & TYPE_MASK == tokenID) && (tokenID & NF_INDEX_MASK == 0); - } - - /// @dev Identify that token at `_id` is fraction of a claim. - /// @dev Upper 128 bits identify base type ID, lower bits should be > 0 - function isTypedItem(uint256 tokenID) internal pure returns (bool) { - return (tokenID & TYPE_MASK != 0) && (tokenID & NF_INDEX_MASK != 0); - } - - /// READ - function ownerOf(uint256 tokenID) public view returns (address _owner) { - _owner = owners[tokenID]; - } - - /// @dev see {IHypercertToken} - function _unitsOf(uint256 tokenID) internal view returns (uint256 units) { - units = tokenValues[tokenID]; - } - - /// @dev see {IHypercertToken} - function _unitsOf(address account, uint256 tokenID) internal view returns (uint256 units) { - // Check if fraction token and accounts owns it - if (ownerOf(tokenID) == account) { - units = tokenValues[tokenID]; - } - } - - /// MUTATE - - /// @dev create token type ID based of token counter - - function _createTokenType(address _account, uint256 units, string memory _uri) internal returns (uint256 typeID) { - _notMaxType(typeCounter); - typeID = ++typeCounter << 128; - - creators[typeID] = _account; - tokenValues[typeID] = units; - - _setURI(typeID, _uri); - - //Event emitted for indexing purposes - emit TransferSingle(_account, address(0), address(0), typeID, 0); - } - - /// @dev Mint a new token type and the initial units - function _mintNewTypeWithToken( - address _account, - uint256 _units, - string memory _uri - ) internal returns (uint256 typeID) { - if (_units == 0) { - revert Errors.NotAllowed(); - } - typeID = _createTokenType(_account, _units, _uri); - - uint256 tokenID = typeID + ++maxIndex[typeID]; //1 based indexing, 0 holds type data - - tokenValues[tokenID] = _units; - - _mint(_account, tokenID, 1, ""); - emit ValueTransfer(typeID, 0, tokenID, _units); - } - - /// @dev Mint a new token type and the initial fractions - function _mintNewTypeWithTokens( - address _account, - uint256[] calldata _fractions, - string memory _uri - ) internal returns (uint256 typeID) { - typeID = _mintNewTypeWithToken(_account, _getSum(_fractions), _uri); - _splitTokenUnits(_account, typeID + maxIndex[typeID], _fractions); - } - - /// @dev Mint a new token for an existing type - function _mintToken(address _account, uint256 _typeID, uint256 _units) internal returns (uint256 tokenID) { - if (!isBaseType(_typeID)) revert Errors.NotAllowed(); - - _notMaxItem(maxIndex[_typeID]); - - unchecked { - tokenID = _typeID + ++maxIndex[_typeID]; //1 based indexing, 0 holds type data - } - - tokenValues[tokenID] = _units; - - _mint(_account, tokenID, 1, ""); - emit ValueTransfer(_typeID, 0, tokenID, _units); - } - - /// @dev Mint new tokens for existing types - /// @notice Enables batch claiming from multiple allowlists - function _batchMintTokens( - address _account, - uint256[] calldata _typeIDs, - uint256[] calldata _units - ) internal returns (uint256[] memory tokenIDs) { - uint256 len = _typeIDs.length; - - tokenIDs = new uint256[](len); - uint256[] memory amounts = new uint256[](len); - uint256[] memory zeroes = new uint256[](len); - - for (uint256 i; i < len; ) { - uint256 _typeID = _typeIDs[i]; - if (!isBaseType(_typeID)) revert Errors.NotAllowed(); - _notMaxItem(maxIndex[_typeID]); - - unchecked { - uint256 tokenID = _typeID + ++maxIndex[_typeID]; //1 based indexing, 0 holds type data - tokenValues[tokenID] = _units[i]; - tokenIDs[i] = tokenID; - amounts[i] = 1; - ++i; - } - } - - _mintBatch(_account, tokenIDs, amounts, ""); - emit BatchValueTransfer(_typeIDs, zeroes, tokenIDs, _units); - } - - /// @dev Split the units of `_tokenID` owned by `account` across `_values` - /// @dev `_values` must sum to total `units` held at `_tokenID` - function _splitTokenUnits(address _account, uint256 _tokenID, uint256[] calldata _values) internal { - if (_values.length > FRACTION_LIMIT || _values.length < 2) revert Errors.ArraySize(); - if (tokenValues[_tokenID] != _getSum(_values)) revert Errors.NotAllowed(); - - // Current token - uint256 _typeID = getBaseType(_tokenID); - uint256 valueLeft = tokenValues[_tokenID]; - - // Prepare batch processing, we want to skip the first entry - uint256 len = _values.length - 1; - - uint256[] memory typeIDs = new uint256[](len); - uint256[] memory fromIDs = new uint256[](len); - uint256[] memory toIDs = new uint256[](len); - uint256[] memory amounts = new uint256[](len); - uint256[] memory values = new uint256[](len); - - { - uint256[] memory _valuesCache = _values; - uint256 swapValue = _valuesCache[len]; - _valuesCache[len] = _valuesCache[0]; - _valuesCache[0] = swapValue; - - for (uint256 i; i < len; ) { - _notMaxItem(maxIndex[_typeID]); - - typeIDs[i] = _typeID; - fromIDs[i] = _tokenID; - toIDs[i] = _typeID + ++maxIndex[_typeID]; - amounts[i] = 1; - values[i] = _valuesCache[i]; - - unchecked { - ++i; - } - } - } - - _beforeUnitTransfer(_msgSender(), _account, fromIDs, toIDs, values, ""); - - for (uint256 i; i < len; ) { - valueLeft -= values[i]; - - tokenValues[toIDs[i]] = values[i]; - - unchecked { - ++i; - } - } - - tokenValues[_tokenID] = valueLeft; - - _mintBatch(_account, toIDs, amounts, ""); - - emit BatchValueTransfer(typeIDs, fromIDs, toIDs, values); - } - - /// @dev Merge the units of `_fractionIDs`. - /// @dev Base type of `_fractionIDs` must be identical for all tokens. - function _mergeTokensUnits(address _account, uint256[] memory _fractionIDs) internal { - if (_fractionIDs.length > FRACTION_LIMIT || _fractionIDs.length < 2) { - revert Errors.ArraySize(); - } - uint256 len = _fractionIDs.length - 1; - - uint256 target = _fractionIDs[len]; - - uint256 _totalValue; - uint256[] memory fromIDs = new uint256[](len); - uint256[] memory toIDs = new uint256[](len); - uint256[] memory values = new uint256[](len); - uint256[] memory amounts = new uint256[](len); - - { - for (uint256 i; i < len; ) { - uint256 _fractionID = _fractionIDs[i]; - fromIDs[i] = _fractionID; - toIDs[i] = target; - amounts[i] = 1; - values[i] = tokenValues[_fractionID]; - - unchecked { - ++i; - } - } - } - - _beforeUnitTransfer(_msgSender(), _account, fromIDs, toIDs, values, ""); - - for (uint256 i; i < len; ) { - _totalValue += values[i]; - - delete tokenValues[fromIDs[i]]; - unchecked { - ++i; - } - } - - tokenValues[target] += _totalValue; - - _burnBatch(_account, fromIDs, amounts); - } - - /// @dev Burn the token at `_tokenID` owned by `_account` - /// @dev Not allowed to burn base type. - /// @dev `_tokenID` must hold all value declared at base type - function _burnToken(address _account, uint256 _tokenID) internal { - if (_account != _msgSender() && !isApprovedForAll(_account, _msgSender())) revert Errors.NotApprovedOrOwner(); - - uint256 value = tokenValues[_tokenID]; - - delete tokenValues[_tokenID]; - - _burn(_account, _tokenID, 1); - emit ValueTransfer(getBaseType(_tokenID), _tokenID, 0, value); - } - - /// TRANSFERS - - // The following functions are overrides required by Solidity. - function _afterTokenTransfer( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual override { - super._afterTokenTransfer(operator, from, to, ids, amounts, data); - - uint256 len = ids.length; - - for (uint256 i; i < len; ) { - owners[ids[i]] = to; - unchecked { - ++i; - } - } - } - - function _beforeUnitTransfer( - address operator, - address from, - uint256[] memory fromIDs, - uint256[] memory toIDs, - uint256[] memory values, - bytes memory data - ) internal virtual { - uint256 len = fromIDs.length; - - for (uint256 i; i < len; ) { - uint256 _from = fromIDs[i]; - uint256 _to = toIDs[i]; - - if (isBaseType(_from)) revert Errors.NotAllowed(); - if (getBaseType(_from) != getBaseType(_to)) revert Errors.TypeMismatch(); - if (from != _msgSender() && !isApprovedForAll(from, _msgSender())) revert Errors.NotApprovedOrOwner(); - unchecked { - ++i; - } - } - } - - /// METADATA - - /// @dev see { openzeppelin-contracts-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol } - /// @dev Always returns the URI for the basetype so that it's managed in one place. - function uri( - uint256 tokenID - ) public view virtual override(ERC1155Upgradeable, ERC1155URIStorageUpgradeable) returns (string memory _uri) { - // All tokens share the same metadata at the moment - _uri = ERC1155URIStorageUpgradeable.uri(getBaseType(tokenID)); - } - - /// UTILS - - /** - * @dev Check if value is below max item index - */ - function _notMaxItem(uint256 tokenID) private pure { - uint128 _count = uint128(tokenID); - ++_count; - } - - /** - * @dev Check if value is below max type index - */ - function _notMaxType(uint256 tokenID) private pure { - uint128 _count = uint128(tokenID >> 128); - ++_count; - } - - /** - * @dev calculate the sum of the elements of an array - */ - function _getSum(uint256[] memory array) internal pure returns (uint256 sum) { - uint256 len = array.length; - for (uint256 i; i < len; ) { - if (array[i] == 0) revert Errors.NotAllowed(); - sum += array[i]; - unchecked { - ++i; - } - } - } - - function _getSingletonArray(uint256 element) private pure returns (uint256[] memory) { - uint256[] memory array = new uint256[](1); - array[0] = element; - - return array; - } - - // UUPS PROXY - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol } - function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { - // solhint-disable-previous-line no-empty-blocks - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - * Assuming 30 available slots (slots cost space, cost gas) - * 1. typeCounter - * 2. owners - * 3. creators - * 4. tokenValues - * 5. maxIndex - */ - uint256[25] private __gap; -} diff --git a/contracts/contracts/interfaces/IHypercertToken.sol b/contracts/contracts/interfaces/IHypercertToken.sol deleted file mode 100644 index 1ed1e34e..00000000 --- a/contracts/contracts/interfaces/IHypercertToken.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -/// @title Interface for hypercert token interactions -/// @author bitbeckers -/// @notice This interface declares the required functionality for a hypercert token -/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) -interface IHypercertToken { - /** - * AllowAll = Unrestricted - * DisallowAll = Transfers disabled after minting - * FromCreatorOnly = Only the original creator can transfer - */ - /// @dev Transfer restriction policies on hypercerts - enum TransferRestrictions { - AllowAll, - DisallowAll, - FromCreatorOnly - } - - /// @dev Emitted when token with tokenID `claimID` is stored, with external data reference via `uri`. - event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits); - - /// @dev Function called to store a claim referenced via `uri` with a maximum number of fractions `units`. - function mintClaim(address account, uint256 units, string memory uri, TransferRestrictions restrictions) external; - - /// @dev Function called to store a claim referenced via `uri` with a set of `fractions`. - /// @dev Fractions are internally summed to total units. - function mintClaimWithFractions( - address account, - uint256 units, - uint256[] memory fractions, - string memory uri, - TransferRestrictions restrictions - ) external; - - /// @dev Function called to split `tokenID` owned by `account` into units declared in `values`. - /// @notice The sum of `values` must equal the current value of `_tokenID`. - function splitFraction(address account, uint256 tokenID, uint256[] memory _values) external; - - /// @dev Function called to merge tokens within `tokenIDs`. - /// @notice Tokens that have been merged are burned. - function mergeFractions(address account, uint256[] memory tokenIDs) external; - - /// @dev Function to burn the token at `tokenID` for `account` - /// @notice Operator must be allowed by `creator` and the token must represent the total amount of available units. - function burnFraction(address account, uint256 tokenID) external; - - /// @dev Returns the `units` held by a (fractional) token at `claimID` - /// @dev If `tokenID` is a base type, the total amount of `units` for the claim is returned. - /// @dev If `tokenID` is a fractional token, the `units` held by the token is returned - function unitsOf(uint256 tokenID) external view returns (uint256 units); - - /// @dev Returns the `units` held by `account` of a (fractional) token at `claimID` - /// @dev If `tokenID` is a base type, the total amount of `units` held by `account` for the claim is returned. - /// @dev If `tokenID` is a fractional token, the `units` held by `account` the token is returned - function unitsOf(address account, uint256 tokenID) external view returns (uint256 units); - - /// @dev Returns the `uri` for metadata of the claim represented by `tokenID` - /// @dev Metadata must conform to { Hypercert Metadata } spec (based on ERC1155 Metadata) - function uri(uint256 tokenID) external view returns (string memory metadata); -} diff --git a/contracts/foundry.toml b/contracts/foundry.toml index bf1b6bfc..4b146c01 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -1,19 +1,26 @@ # Full reference /~https://github.com/foundry-rs/foundry/tree/master/config [profile.default] -auto_detect_solc = false +auto_detect_solc = true +allow_paths = ["../node_modules", "lib"] bytecode_hash = "none" +force = false fuzz = { runs = 1025 } gas_reports = ["*"] -libs = ["lib"] +libraries = [] +libs = ["node_modules", "lib"] optimizer = true optimizer_runs = 5_000 out = "out" -solc = "0.8.16" src = "src" test = "test/foundry" - +no_match_test = "testCannotExecuteOrderIfInvalidUserGlobal" [profile.ci] fuzz = { runs = 1024 } verbosity = 1 + +[rpc_endpoints] +mainnet = "${MAINNET_RPC_URL}" +goerli = "${GOERLI_RPC_URL}" +optimism = "${OPTIMISM_RPC_URL}" \ No newline at end of file diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index a8ec0a3c..87cd1dc7 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -37,7 +37,7 @@ dotenvConfig({ path: resolve(__dirname, dotenvConfigPath) }); const mnemonic = requireEnv(process.env.MNEMONIC, "MNEMONIC"); const mnemonic_celo = requireEnv(process.env.MNEMONIC_CELO, "MNEMONIC_CELO"); const infuraApiKey = requireEnv(process.env.INFURA_API_KEY, "INFURA_API_KEY"); -const alchemyOptimismUrl = requireEnv(process.env.ALCHEMY_OPTIMISM_URL, "ALCHEMY_OPTIMISM_URL"); +const optimismRpcUrl = requireEnv(process.env.OPTIMISM_RPC_URL, "OPTIMISM_RPC_URL"); const etherscanApiKey = requireEnv(process.env.ETHERSCAN_API_KEY, "ETHERSCAN_API_KEY"); const optimisticEtherscanApiKey = requireEnv(process.env.OPTIMISTIC_ETHERSCAN_API_KEY, "OPTIMISTIC_ETHERSCAN_API_KEY"); @@ -147,12 +147,12 @@ const config = { "optimism-goerli": getChainConfig("optimism-goerli"), "optimism-mainnet": { ...getChainConfig("optimism-mainnet"), - url: alchemyOptimismUrl, + url: optimismRpcUrl, }, }, paths: { cache: "./cache_hardhat", // Use a different cache for Hardhat than Foundry - sources: "./src", + sources: "./src/protocol", tests: "./test", }, preprocess: { diff --git a/contracts/lib/openzeppelin-contracts-upgradeable/.eslintrc b/contracts/lib/openzeppelin-contracts-upgradeable/.eslintrc index 095d2754..22fb715f 100644 --- a/contracts/lib/openzeppelin-contracts-upgradeable/.eslintrc +++ b/contracts/lib/openzeppelin-contracts-upgradeable/.eslintrc @@ -1,35 +1,30 @@ { - "extends" : [ - "standard" - ], - "plugins": [ - "mocha" - ], + "extends": ["standard"], + "plugins": ["mocha"], "env": { - "browser" : true, - "node" : true, - "mocha" : true, - "jest" : true, + "browser": true, + "node": true, + "mocha": true, + "jest": true }, - "globals" : { + "globals": { "artifacts": false, "contract": false, "assert": false, "web3": false, "usePlugin": false, - "extendEnvironment": false, + "extendEnvironment": false }, "rules": { - // Strict mode "strict": ["error", "global"], // Code style "array-bracket-spacing": ["off"], - "camelcase": ["error", {"properties": "always"}], + "camelcase": ["error", { "properties": "always" }], "comma-dangle": ["error", "always-multiline"], - "comma-spacing": ["error", {"before": false, "after": true}], - "dot-notation": ["error", {"allowKeywords": true, "allowPattern": ""}], + "comma-spacing": ["error", { "before": false, "after": true }], + "dot-notation": ["error", { "allowKeywords": true, "allowPattern": "" }], "eol-last": ["error", "always"], "eqeqeq": ["error", "smart"], "generator-star-spacing": ["error", "before"], @@ -40,7 +35,7 @@ "no-dupe-args": "error", "no-dupe-keys": "error", "no-mixed-spaces-and-tabs": ["error", "smart-tabs"], - "no-redeclare": ["error", {"builtinGlobals": true}], + "no-redeclare": ["error", { "builtinGlobals": true }], "no-trailing-spaces": ["error", { "skipBlankLines": false }], "no-undef": "error", "no-use-before-define": "off", @@ -54,7 +49,7 @@ "mocha/no-exclusive-tests": ["error"], "promise/always-return": "off", - "promise/avoid-new": "off", + "promise/avoid-new": "off" }, "parserOptions": { "ecmaVersion": 2020 diff --git a/contracts/package.json b/contracts/package.json index a54becd4..36d2c440 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -30,17 +30,20 @@ "contracts" ], "devDependencies": { + "@chainlink/contracts": "^0.8.0", "@commitlint/cli": "^17.1.2", "@commitlint/config-conventional": "^17.1.0", "@dlsl/hardhat-markup": "^1.0.0-rc.7", "@ethersproject/abi": "^5.7.0", "@ethersproject/bytes": "^5.7.0", "@ethersproject/providers": "^5.7.2", + "@looksrare/contracts-libs": "^3.4.0", "@nomicfoundation/hardhat-chai-matchers": "^1.0.5", "@nomicfoundation/hardhat-network-helpers": "^1.0.7", "@nomicfoundation/hardhat-toolbox": "^2.0.0", "@nomiclabs/hardhat-ethers": "^2.2.1", "@nomiclabs/hardhat-etherscan": "^3.1.3", + "@openzeppelin/contracts": "<5.0.0", "@openzeppelin/hardhat-defender": "^1.8.2", "@openzeppelin/hardhat-upgrades": "^1.28", "@primitivefi/hardhat-dodoc": "^0.2.3", @@ -82,6 +85,7 @@ "solhint": "^3.6.2", "solhint-plugin-prettier": "^0.0.5", "solidity-coverage": "^0.8.2", + "solmate": "^6.2.0", "ts-node": "^10.9.1", "typechain": "^8.3.1", "typescript": "^4.9.4" @@ -99,11 +103,11 @@ "scripts": { "build": "hardhat compile && pnpm tsc -p tsconfig.build.json && rollup -c && pnpm copy:contracts", "build:forge": "forge build", - "clean": "rimraf cache out dist typechain abi", + "clean": "rimraf cache out dist src/typechain src/abi", "copy:contracts": "copyfiles -u 1 ./src/**/*.sol ./src/*.sol ./contracts", "docs": "hardhat dodoc", "lint": "pnpm lint:sol && pnpm prettier:check", - "lint:sol": "solhint -w 5 \"./{src,test}/**/*.sol\"", + "lint:sol": "solhint -w 60 \"./{src,test/protocol,test/marketplace}/**/*.sol\"", "prebuild": "pnpm clean", "prepublish": "pnpm build", "prettier": "prettier --config \"./.prettierrc.yml\" --write \"**/*.{json,md,sol,yml}\"", diff --git a/contracts/remappings.txt b/contracts/remappings.txt index bb8f23eb..cd70bc53 100644 --- a/contracts/remappings.txt +++ b/contracts/remappings.txt @@ -4,3 +4,8 @@ murky/=lib/murky/src/ oz-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/ oz-contracts/=lib/murky/lib/openzeppelin-contracts/ prb-test/=lib/prb-test/src/ +@hypercerts/protocol/=src/protocol/ +@hypercerts/marketplace/=src/marketplace/ +@looksrare/=node_modules/@looksrare/ +hardhat/=node_modules/hardhat/ +solmate/=node_modules/solmate/ \ No newline at end of file diff --git a/contracts/src/AllowlistMinter.sol b/contracts/src/AllowlistMinter.sol deleted file mode 100644 index 576b45ee..00000000 --- a/contracts/src/AllowlistMinter.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import { MerkleProofUpgradeable } from "oz-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol"; -import { IAllowlist } from "./interfaces/IAllowlist.sol"; - -import { Errors } from "./libs/Errors.sol"; - -/// @title Interface for hypercert token interactions -/// @author bitbeckers -/// @notice This interface declares the required functionality for a hypercert token -/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) -contract AllowlistMinter is IAllowlist { - event AllowlistCreated(uint256 tokenID, bytes32 root); - event LeafClaimed(uint256 tokenID, bytes32 leaf); - - mapping(uint256 => bytes32) internal merkleRoots; - mapping(uint256 => mapping(bytes32 => bool)) public hasBeenClaimed; - mapping(uint256 => uint256) internal maxUnits; - mapping(uint256 => uint256) internal minted; - - function isAllowedToClaim( - bytes32[] calldata proof, - uint256 claimID, - bytes32 leaf - ) external view returns (bool isAllowed) { - if (merkleRoots[claimID].length == 0) revert Errors.DoesNotExist(); - isAllowed = MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf); - } - - function _createAllowlist(uint256 claimID, bytes32 merkleRoot, uint256 units) internal { - if (merkleRoot == "" || units == 0) revert Errors.Invalid(); - if (merkleRoots[claimID] != "") revert Errors.DuplicateEntry(); - - merkleRoots[claimID] = merkleRoot; - maxUnits[claimID] = units; - emit AllowlistCreated(claimID, merkleRoot); - } - - function _processClaim(bytes32[] calldata proof, uint256 claimID, uint256 amount) internal { - if (merkleRoots[claimID].length == 0) revert Errors.DoesNotExist(); - - bytes32 leaf = _calculateLeaf(msg.sender, amount); - - if (hasBeenClaimed[claimID][leaf]) revert Errors.AlreadyClaimed(); - if ( - !MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf) || - (minted[claimID] + amount) > maxUnits[claimID] - ) revert Errors.Invalid(); - hasBeenClaimed[claimID][leaf] = true; - - emit LeafClaimed(claimID, leaf); - } - - function _calculateLeaf(address account, uint256 amount) internal pure returns (bytes32 leaf) { - leaf = keccak256(bytes.concat(keccak256(abi.encode(account, amount)))); - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - * Assuming 30 available slots (slots cost space, cost gas) - * 1. merkleRoots - * 2. hasBeenClaimed - * 3. maxUnits - * 4. minted - */ - uint256[26] private __gap; -} diff --git a/contracts/src/HypercertTrader.sol b/contracts/src/HypercertTrader.sol deleted file mode 100644 index 7f9aae3f..00000000 --- a/contracts/src/HypercertTrader.sol +++ /dev/null @@ -1,405 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import { IHypercertTrader } from "./interfaces/IHypercertTrader.sol"; -import { IHypercertToken } from "./interfaces/IHypercertToken.sol"; -import { PausableUpgradeable } from "oz-upgradeable/security/PausableUpgradeable.sol"; -import { IERC1155Upgradeable } from "oz-upgradeable/token/ERC1155/IERC1155Upgradeable.sol"; -import { OwnableUpgradeable } from "oz-upgradeable/access/OwnableUpgradeable.sol"; -import { Initializable } from "oz-upgradeable/proxy/utils/Initializable.sol"; -import { UUPSUpgradeable } from "oz-upgradeable/proxy/utils/UUPSUpgradeable.sol"; - -import { Errors } from "./libs/Errors.sol"; - -error NotAllowed(); -error InvalidOffer(string); -error InvalidBuy(string); - -interface IHypercertMinter { - function ownerOf(uint256 id) external view returns (address); - - function unitsOf(uint256 id) external view returns (uint256); -} - -/** - * @title Contract for managing hypercert trades - * @notice Implementation of the HypercertTrader Interface - * @author bitbeckers - */ -contract HypercertTrader is IHypercertTrader, Initializable, OwnableUpgradeable, PausableUpgradeable, UUPSUpgradeable { - mapping(address => mapping(uint256 => uint256)) public totalUnitsForSale; - mapping(uint256 => Offer) public offers; - uint256 internal _offerCounter; - - /// INIT - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - function initialize() public virtual initializer { - __Pausable_init(); - __Ownable_init(); - __UUPSUpgradeable_init(); - } - - function getOffer(uint256 offerID) external view returns (Offer memory) { - return offers[offerID]; - } - - /** - * @dev Creates a new offer to sell Hypercert tokens. - * @param hypercertContract The address of the Hypercert token contract. - * @param fractionID The ID of the fraction to sell. - * @param unitsForSale The number of units available for sale. - * @param minUnitsPerTrade The minimum number of units that can be bought in a single trade. - * @param maxUnitsPerTrade The maximum number of units that can be bought in a single trade. - * @param acceptedTokens The list of tokens that are accepted for payment. - * @notice This function creates a new offer to sell Hypercert tokens. The offer specifies the Hypercert token contract, - * the fraction to sell, the number of units available for sale, the minimum and maximum number of units that can be bought - * in a single trade, and the list of tokens that are accepted for payment. The offer is added to the list of existing offers - * and can be bought by other users using the `buyUnits` function. - */ - //TODO remove payable from offer - function createOffer( - address hypercertContract, - uint256 fractionID, - uint256 unitsForSale, - uint256 minUnitsPerTrade, - uint256 maxUnitsPerTrade, - AcceptedToken[] memory acceptedTokens - ) external payable whenNotPaused returns (uint256 offerID) { - // This checks is the contract is approved to trade on behalf of the owner at the time of offering. - // However, the owner can revoke this approval at any time. - if (!IERC1155Upgradeable(hypercertContract).isApprovedForAll(msg.sender, address(this))) revert NotAllowed(); - - _validateOffer( - msg.sender, - hypercertContract, - fractionID, - unitsForSale, - minUnitsPerTrade, - maxUnitsPerTrade, - acceptedTokens - ); - - offerID = _offerCounter; - offers[offerID] = _createOffer( - msg.sender, - hypercertContract, - fractionID, - unitsForSale, - minUnitsPerTrade, - maxUnitsPerTrade, - acceptedTokens - ); - - _offerCounter += 1; - totalUnitsForSale[hypercertContract][fractionID] += unitsForSale; - - emit OfferCreated(msg.sender, hypercertContract, fractionID, offerID); - } - - /** - * @dev Buys Hypercert tokens from an existing offer. - * @param recipient The address that will receive the Hypercert tokens. - * @param offerID The ID of the offer to buy from. - * @param unitAmount The number of units to buy. - * @param buyToken The address of the token used for payment. - * @param tokenAmountPerUnit The amount of tokens to pay per unit. - * @notice This function buys Hypercert tokens from an existing offer. The function verifies that the offer is valid and that - * the buyer has provided enough payment in the specified token. If the offer is for a fraction of a Hypercert token, the function - * splits the fraction and transfers the appropriate number of units to the buyer. If the offer is for a fixed number of units, - * the function transfers the units to the buyer. The function also transfers the payment to the offerer and emits a `Trade` event. - */ - function buyUnits( - address recipient, - uint256 offerID, - uint256 unitAmount, - address buyToken, - uint256 tokenAmountPerUnit - ) public payable whenNotPaused { - // Get the offer and validate that it is open and has enough units available - Offer storage offer = offers[offerID]; - _validateBuyOffer(offer, unitAmount, buyToken, tokenAmountPerUnit); - - offer.unitsAvailable -= unitAmount; - totalUnitsForSale[offer.hypercertContract][offer.fractionID] -= unitAmount; - - if (offer.unitsAvailable == 0) { - offer.status = OfferStatus.Fulfilled; - } - - uint256 unitsInFraction = IHypercertMinter(offer.hypercertContract).unitsOf(offer.fractionID); - - // Check if full fraction is being bought - if (unitsInFraction == unitAmount) { - IERC1155Upgradeable(offer.hypercertContract).safeTransferFrom( - offer.offerer, - recipient, - offer.fractionID, - 1, - "" - ); - } else { - // Create uint256[] for the split with the remaining units and units to transfer - uint256[] memory units = new uint256[](2); - units[0] = unitsInFraction - unitAmount; - units[1] = unitAmount; - - IHypercertToken(offer.hypercertContract).splitFraction(recipient, offer.fractionID, units); - } - (bool success, ) = payable(offer.offerer).call{ value: msg.value }(""); - if (!success) revert InvalidBuy("Payment failed"); - - emit Trade( - offer.offerer, - recipient, - offer.hypercertContract, - offer.fractionID, - unitAmount, - buyToken, - tokenAmountPerUnit, - offerID - ); - } - - /** - * @dev Buys Hypercert tokens from multiple existing offers in a single transaction. - * @param recipient The address that will receive the Hypercert tokens. - * @param offerIDs The list of IDs of the offers to buy from. - * @param unitAmounts The list of numbers of units to buy for each offer. - * @param buyTokens The list of addresses of the tokens used for payment for each offer. - * @param tokenAmountsPerUnit The list of amounts of tokens to pay per unit for each offer. - * @notice This function allows a user to buy Hypercert tokens from multiple existing offers in a single transaction. - * The function takes in several arrays of parameters, including the IDs of the offers to buy from, - * the number of units to buy for each offer, the tokens used for payment for each offer, - * and the amounts of tokens to pay per unit for each offer. - * The function then executes the trades and transfers the Hypercert tokens to the specified recipient. - */ - function batchBuyUnits( - address recipient, - uint256[] calldata offerIDs, - uint256[] calldata unitAmounts, - address[] calldata buyTokens, - uint256[] calldata tokenAmountsPerUnit - ) external payable whenNotPaused { - uint256 len = offerIDs.length; - for (uint256 i; i < len; ) { - buyUnits(recipient, offerIDs[i], unitAmounts[i], buyTokens[i], tokenAmountsPerUnit[i]); - unchecked { - ++i; - } - } - } - - /** - * @dev Cancels an existing offer. - * @param offerID The ID of the offer to cancel. - * @notice This function cancels an existing offer. The function verifies that the offer exists and that the caller is the offerer. - * The function sets the offer status to `Cancelled` and emits an `OfferCancelled` event. - */ - function cancelOffer(uint256 offerID) external whenNotPaused { - // Get the offer and validate that the caller is the offerer - Offer storage offer = offers[offerID]; - if (offer.hypercertContract == address(0)) revert InvalidOffer("No contract address found"); - if (offer.offerer != msg.sender) revert NotAllowed(); - if (offer.status != OfferStatus.Open) revert InvalidOffer("status"); - - // Update the offer and emit an OfferCancelled event - offer.status = OfferStatus.Cancelled; - totalUnitsForSale[offer.hypercertContract][offer.fractionID] -= offer.unitsAvailable; - emit OfferCancelled(msg.sender, offer.hypercertContract, offer.fractionID, offerID); - } - - /// PAUSABLE - - function pause() external onlyOwner { - _pause(); - } - - function unpause() external onlyOwner { - _unpause(); - } - - /// INTERNAL - - /** - * @dev Internal function to create a new offer to sell Hypercert tokens. - * @param offerer The address of the offerer. - * @param hypercertContract The address of the Hypercert token contract. - * @param fractionID The ID of the fraction to sell. - * @param unitsAvailable The number of units available for sale. - * @param minUnitsPerTrade The minimum number of units that can be bought in a single trade. - * @param maxUnitsPerTrade The maximum number of units that can be bought in a single trade. - * @param acceptedTokens The list of tokens that are accepted for payment. - * @return The storage reference to the newly created offer. - */ - function _createOffer( - address offerer, - address hypercertContract, - uint256 fractionID, - uint256 unitsAvailable, - uint256 minUnitsPerTrade, - uint256 maxUnitsPerTrade, - AcceptedToken[] memory acceptedTokens - ) internal returns (Offer storage) { - // TODO optimise init and adding accepted tokens - Offer storage offer = offers[_offerCounter]; - offer.offerer = offerer; - offer.hypercertContract = hypercertContract; - offer.fractionID = fractionID; - offer.unitsAvailable = unitsAvailable; - offer.minUnitsPerTrade = minUnitsPerTrade; - offer.maxUnitsPerTrade = maxUnitsPerTrade; - offer.status = OfferStatus.Open; - - if (minUnitsPerTrade == maxUnitsPerTrade) { - offer.offerType = OfferType.Fraction; - } else { - offer.offerType = OfferType.Units; - } - - uint256 len = acceptedTokens.length; - for (uint256 i; i < len; ) { - offer.acceptedTokens.push(AcceptedToken(acceptedTokens[i].token, acceptedTokens[i].minimumAmountPerUnit)); - - unchecked { - ++i; - } - } - - return offer; - } - - /** - * @dev Validates the parameters for a new offer. - * @param hypercertContract The address of the Hypercert token contract. - * @param fractionID The ID of the fraction to sell. - * @param unitsForSale The number of units available for sale. - * @param minUnitsPerTrade The minimum number of units that can be bought in a single trade. - * @param maxUnitsPerTrade The maximum number of units that can be bought in a single trade. - * @param acceptedTokens The list of tokens that are accepted for payment. - * @notice This internal function validates the parameters for a new offer. The function verifies that the Hypercert token contract - * exists and that the fraction ID is valid. The function also verifies that the units available, minimum units per trade, and maximum - * units per trade are valid and that the accepted tokens list is not empty. - */ - function _validateOffer( - address offerer, - address hypercertContract, - uint256 fractionID, - uint256 unitsForSale, - uint256 minUnitsPerTrade, - uint256 maxUnitsPerTrade, - AcceptedToken[] memory acceptedTokens - ) internal view returns (bool) { - if (IHypercertMinter(hypercertContract).ownerOf(fractionID) != offerer) revert InvalidOffer("Not owner"); - - // Validate units exist and are available - uint256 totalUnits = IHypercertMinter(hypercertContract).unitsOf(fractionID); - if ( - unitsForSale == 0 || - totalUnits < unitsForSale || - totalUnits < totalUnitsForSale[hypercertContract][fractionID] + unitsForSale - ) { - revert InvalidOffer("Insufficient units"); - } - - // Validate min/max units per trade - if (maxUnitsPerTrade > unitsForSale || minUnitsPerTrade > maxUnitsPerTrade) { - revert InvalidOffer("Min/Max units"); - } - - // If sale is for a fraction, the units must be a multiple of the minimum units per trade - if (minUnitsPerTrade == maxUnitsPerTrade && unitsForSale % minUnitsPerTrade != 0) { - revert InvalidOffer("Units indivisible by fractions"); - } - - // Minimum amount per unit must be greater than 0 - if (acceptedTokens.length == 0 || acceptedTokens[0].minimumAmountPerUnit == 0) { - revert InvalidOffer("No accepted tokens"); - } - - // for now only accept the native token, ZERO_ADDRESS - if (acceptedTokens.length != 1 || acceptedTokens[0].token != address(0)) { - revert InvalidOffer("Only zero token"); - } - } - - /** - * @dev Validates an existing offer for a buy operation. - * @param offer The offer to validate. - * @param unitAmountsToBuy The number of units to buy. - * @param buyToken The address of the token used for payment. - * @param tokenAmountPerUnit The amount of tokens to pay per unit. - * @notice This internal function validates an existing offer for a buy operation. The function verifies that the offer exists, - * is open, and has enough units available for sale. The function also verifies that the specified token is accepted for payment - * and that the buyer has provided enough payment in the specified token. - */ - function _validateBuyOffer( - Offer memory offer, - uint256 unitAmountsToBuy, - address buyToken, - uint256 tokenAmountPerUnit - ) internal { - if (offer.status != OfferStatus.Open || offer.offerType != OfferType.Units) { - revert InvalidOffer("Wrong status"); - } - - if ( - offer.unitsAvailable < unitAmountsToBuy || - offer.minUnitsPerTrade > unitAmountsToBuy || - offer.maxUnitsPerTrade < unitAmountsToBuy - ) revert InvalidOffer("Min/Max units"); - - // Check for sufficient funds; currently only native token - if (buyToken != address(0) || (unitAmountsToBuy * tokenAmountPerUnit) > msg.value) { - revert InvalidOffer("Wrong token/value"); - } - - // TODO check on overpayment??? - - //TODO optimize array search or use mapping - // Check for accepted tokens - uint256 len = offer.acceptedTokens.length; - bool tokenAccepted = false; - for (uint256 i; i < len; ) { - if (!tokenAccepted) { - tokenAccepted = offer.acceptedTokens[i].token == buyToken; - } - - if ( - offer.acceptedTokens[i].token == buyToken && - offer.acceptedTokens[i].minimumAmountPerUnit > tokenAmountPerUnit - ) { - revert InvalidOffer("Wrong token/value"); - } - - unchecked { - ++i; - } - } - if (!tokenAccepted) revert InvalidOffer("Wrong token/value"); - } - - /// INTERNAL - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol } - function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { - // solhint-disable-previous-line no-empty-blocks - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - * Assuming 30 available slots (slots cost space, cost gas) - * 1. totalUnitsForSale - * 2. offers - * 3. _offerCounter - */ - uint256[27] private __gap; -} diff --git a/contracts/src/index.ts b/contracts/src/index.ts index 486b728b..641f675b 100644 --- a/contracts/src/index.ts +++ b/contracts/src/index.ts @@ -1,10 +1,10 @@ import HypercertMinterAbi from "./abi/HypercertMinter.json"; // import { HypercertMinter__factory } from "./types/factories/src/HypercertMinter__factory"; -import type { AllowlistMinter } from "./types/src/AllowlistMinter"; -import type { HypercertMinter } from "./types/src/HypercertMinter"; -import type { IAllowlist } from "./types/src/interfaces/IAllowlist"; -import type { IHypercertToken } from "./types/src/interfaces/IHypercertToken"; -import type { Errors } from "./types/src/libs/Errors"; +import type { AllowlistMinter } from "./types/src/protocol/AllowlistMinter"; +import type { HypercertMinter } from "./types/src/protocol/HypercertMinter"; +import type { IAllowlist } from "./types/src/protocol/interfaces/IAllowlist"; +import type { IHypercertToken } from "./types/src/protocol/interfaces/IHypercertToken"; +import type { Errors } from "./types/src/protocol/libs/Errors"; /* in order to adjust the build folder: 1) import any files here you want in the final build package. diff --git a/contracts/src/interfaces/IAllowlist.sol b/contracts/src/interfaces/IAllowlist.sol deleted file mode 100644 index fe4a9ec4..00000000 --- a/contracts/src/interfaces/IAllowlist.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -/// @title Interface for allowlist -/// @author bitbeckers -/// @notice This interface declares the required functionality for a hypercert token -/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) -interface IAllowlist { - function isAllowedToClaim( - bytes32[] calldata proof, - uint256 tokenID, - bytes32 leaf - ) external view returns (bool isAllowed); -} diff --git a/contracts/src/interfaces/IHypercertTrader.sol b/contracts/src/interfaces/IHypercertTrader.sol deleted file mode 100644 index a8ee04f6..00000000 --- a/contracts/src/interfaces/IHypercertTrader.sol +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -/// @title Interface for hypercert token trading -/// @author bitbeckers -/// @notice This interface declares the required functionality to interact with the hypercert marketplace -interface IHypercertTrader { - /** - * @dev Struct for an offer to sell Hypercert tokens. - */ - struct Offer { - address offerer; - address hypercertContract; - uint256 fractionID; - uint256 unitsAvailable; - uint256 minUnitsPerTrade; - uint256 maxUnitsPerTrade; - OfferType offerType; - OfferStatus status; - AcceptedToken[] acceptedTokens; - } - - /** - * @dev Enum for the type of offer (Units or Fraction). - */ - enum OfferType { - Units, - Fraction - } - - /** - * @dev Enum for the status of an offer (Open, Fulfilled, or Cancelled). - */ - enum OfferStatus { - Open, - Fulfilled, - Cancelled - } - - /** - * @dev Struct for a token that is accepted for payment. - */ - struct AcceptedToken { - address token; - uint256 minimumAmountPerUnit; - } - - event OfferCreated( - address indexed offerer, - address indexed hypercertContract, - uint256 indexed fractionID, - uint256 offerID - ); - - event Trade( - address indexed seller, - address indexed buyer, - address indexed hypercertContract, - uint256 fractionID, - uint256 unitsBought, - address buyToken, - uint256 tokenAmountPerUnit, - uint256 offerID - ); - - event OfferCancelled( - address indexed creator, - address indexed hypercertContract, - uint256 indexed fractionID, - uint256 offerID - ); - - /** - * @dev Creates a new offer to sell Hypercert tokens. - * @param hypercertContract The address of the Hypercert token contract. - * @param fractionID The ID of the fraction to sell. - * @param units The number of units available for sale. - * @param minUnitsPerTrade The minimum number of units that can be bought in a single trade. - * @param maxUnitsPerTrade The maximum number of units that can be bought in a single trade. - * @param acceptedTokens The list of tokens that are accepted for payment. - */ - function createOffer( - address hypercertContract, - uint256 fractionID, - uint256 units, - uint256 minUnitsPerTrade, - uint256 maxUnitsPerTrade, - AcceptedToken[] memory acceptedTokens - ) external payable returns (uint256 offerID); - - /** - * @dev Buys Hypercert tokens from an existing offer. - * @param recipient The address that will receive the Hypercert tokens. - * @param offerID The ID of the offer to buy from. - * @param unitAmount The number of units to buy. - * @param buyToken The address of the token used for payment. - * @param tokenAmountPerUnit The amount of tokens to pay per unit. - */ - function buyUnits( - address recipient, - uint256 offerID, - uint256 unitAmount, - address buyToken, - uint256 tokenAmountPerUnit - ) external payable; - - /** - * @dev Buys Hypercert tokens from multiple existing offers in a single transaction. - * @param recipient The address that will receive the Hypercert tokens. - * @param offerIDs The list of IDs of the offers to buy from. - * @param unitAmounts The list of numbers of units to buy for each offer. - * @param buyTokens The list of addresses of the tokens used for payment for each offer. - * @param tokenAmountsPerUnit The list of amounts of tokens to pay per unit for each offer. - */ - function batchBuyUnits( - address recipient, - uint256[] calldata offerIDs, - uint256[] calldata unitAmounts, - address[] calldata buyTokens, - uint256[] calldata tokenAmountsPerUnit - ) external payable; - - /** - * @dev Cancels an existing offer. - * @param offerID The ID of the offer to cancel. - */ - function cancelOffer(uint256 offerID) external; -} diff --git a/contracts/src/libs/Errors.sol b/contracts/src/libs/Errors.sol deleted file mode 100644 index e19d6b5c..00000000 --- a/contracts/src/libs/Errors.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -/// @author bitbeckers -library Errors { - error AlreadyClaimed(); - error ArraySize(); - error DoesNotExist(); - error DuplicateEntry(); - error Invalid(); - error NotAllowed(); - error NotApprovedOrOwner(); - error TransfersNotAllowed(); - error TypeMismatch(); -} diff --git a/contracts/src/marketplace/BatchOrderTypehashRegistry.sol b/contracts/src/marketplace/BatchOrderTypehashRegistry.sol new file mode 100644 index 00000000..13851212 --- /dev/null +++ b/contracts/src/marketplace/BatchOrderTypehashRegistry.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Shared errors +import { MerkleProofTooLarge } from "./errors/SharedErrors.sol"; + +/** + * @title BatchOrderTypehashRegistry + * @notice The contract generates the batch order hash that is used to compute the digest for signature verification. + * @author LooksRare protocol team (👀,💎) + */ +contract BatchOrderTypehashRegistry { + /** + * @notice This function returns the hash of the concatenation of batch order type hash and merkle root. + * @param root Merkle root + * @param proofLength Merkle proof length + * @return batchOrderHash The batch order hash + */ + function hashBatchOrder(bytes32 root, uint256 proofLength) public pure returns (bytes32 batchOrderHash) { + batchOrderHash = keccak256(abi.encode(_getBatchOrderTypehash(proofLength), root)); + } + + /** + * @dev It looks like this for each height + * height == 1: BatchOrder(Maker[2] tree)Maker(uint8 quoteType,uint256 globalNonce,uint256 subsetNonce,uint256 orderNonce,uint256 strategyId,uint8 collectionType,address collection,address currency,address signer,uint256 startTime,uint256 endTime,uint256 price,uint256[] itemIds,uint256[] amounts,bytes additionalParameters) + * height == 2: BatchOrder(Maker[2][2] tree)Maker(uint8 quoteType,uint256 globalNonce,uint256 subsetNonce,uint256 orderNonce,uint256 strategyId,uint8 collectionType,address collection,address currency,address signer,uint256 startTime,uint256 endTime,uint256 price,uint256[] itemIds,uint256[] amounts,bytes additionalParameters) + * height == n: BatchOrder(Maker[2]...[2] tree)Maker(uint8 quoteType,uint256 globalNonce,uint256 subsetNonce,uint256 orderNonce,uint256 strategyId,uint8 collectionType,address collection,address currency,address signer,uint256 startTime,uint256 endTime,uint256 price,uint256[] itemIds,uint256[] amounts,bytes additionalParameters) + */ + function _getBatchOrderTypehash(uint256 height) internal pure returns (bytes32 typehash) { + if (height == 1) { + typehash = hex"9661287f7a4aa4867db46a2453ee15bebac4e8fc25667a58718da658f15de643"; + } else if (height == 2) { + typehash = hex"a54ab330ea9e1dfccee2b86f3666989e7fbd479704416c757c8de8e820142a08"; + } else if (height == 3) { + typehash = hex"93390f5d45ede9dea305f16aec86b2472af4f823851637f1b7019ad0775cea49"; + } else if (height == 4) { + typehash = hex"9dda2c8358da895e43d574bb15954ce5727b22e923a2d8f28261f297bce42f0b"; + } else if (height == 5) { + typehash = hex"92dc717124e161262f9d10c7079e7d54dc51271893fba54aa4a0f270fecdcc98"; + } else if (height == 6) { + typehash = hex"ce02aee5a7a35d40d974463c4c6e5534954fb07a7e7bc966fee268a15337bfd8"; + } else if (height == 7) { + typehash = hex"f7a65efd167a18f7091b2bb929d687dd94503cf0a43620487055ed7d6b727559"; + } else if (height == 8) { + typehash = hex"def24acacad1318b664520f7c10e8bc6d1e7f6f6f7c8b031e70624ceb42266a6"; + } else if (height == 9) { + typehash = hex"4cb4080dc4e7bae88b4dc4307ad5117fa4f26195998a1b5f40368809d7f4c7f2"; + } else if (height == 10) { + typehash = hex"f8b1f864164d8d6e0b45f1399bd711223117a4ab0b057a9c2d7779e86a7c88db"; + } else { + revert MerkleProofTooLarge(height); + } + } +} diff --git a/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol b/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol new file mode 100644 index 00000000..4b5e6ef7 --- /dev/null +++ b/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IERC2981 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC2981.sol"; + +// Interfaces +import { ICreatorFeeManager } from "./interfaces/ICreatorFeeManager.sol"; +import { IRoyaltyFeeRegistry } from "./interfaces/IRoyaltyFeeRegistry.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "./constants/NumericConstants.sol"; + +/** + * @title CreatorFeeManagerWithRebates + * @notice This contract returns the creator fee address and the creator rebate amount. + * @author LooksRare protocol team (👀,💎) + */ +contract CreatorFeeManagerWithRebates is ICreatorFeeManager { + /** + * @notice Standard royalty fee (in basis point). + */ + uint256 public constant STANDARD_ROYALTY_FEE_BP = 50; + + /** + * @notice Royalty fee registry interface. + */ + IRoyaltyFeeRegistry public immutable royaltyFeeRegistry; + + /** + * @notice Constructor + * @param _royaltyFeeRegistry Royalty fee registry address. + */ + constructor(address _royaltyFeeRegistry) { + royaltyFeeRegistry = IRoyaltyFeeRegistry(_royaltyFeeRegistry); + } + + /** + * @inheritdoc ICreatorFeeManager + */ + function viewCreatorFeeInfo( + address collection, + uint256 price, + uint256[] memory itemIds + ) external view returns (address creator, uint256 creatorFeeAmount) { + // Check if there is a royalty info in the system + (creator, ) = royaltyFeeRegistry.royaltyInfo(collection, price); + + if (creator == address(0)) { + if (IERC2981(collection).supportsInterface(IERC2981.royaltyInfo.selector)) { + uint256 length = itemIds.length; + + for (uint256 i; i < length; ) { + try IERC2981(collection).royaltyInfo(itemIds[i], price) returns ( + address newCreator, + uint256 /* newCreatorFeeAmount */ + ) { + if (i == 0) { + creator = newCreator; + + unchecked { + ++i; + } + continue; + } + + if (newCreator != creator) { + revert BundleEIP2981NotAllowed(collection); + } + } catch { + // If creator address is not 0, that means there was at least 1 + // successful call. If all royaltyInfo calls fail, it should assume + // 0 royalty. + // If the first call reverts, even if creator is address(0), subsequent + // successful calls will still revert above with BundleEIP2981NotAllowed + // because newCreator will be different from creator. + if (creator != address(0)) { + revert BundleEIP2981NotAllowed(collection); + } + } + + unchecked { + ++i; + } + } + } + } + + // A fixed royalty fee is applied + if (creator != address(0)) { + creatorFeeAmount = (STANDARD_ROYALTY_FEE_BP * price) / ONE_HUNDRED_PERCENT_IN_BP; + } + } +} diff --git a/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol b/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol new file mode 100644 index 00000000..ac72682d --- /dev/null +++ b/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IERC2981 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC2981.sol"; + +// Interfaces +import { ICreatorFeeManager } from "./interfaces/ICreatorFeeManager.sol"; +import { IRoyaltyFeeRegistry } from "./interfaces/IRoyaltyFeeRegistry.sol"; + +/** + * @title CreatorFeeManagerWithRoyalties + * @notice This contract returns the creator fee address and the creator fee amount. + * @author LooksRare protocol team (👀,💎) + */ +contract CreatorFeeManagerWithRoyalties is ICreatorFeeManager { + /** + * @notice Royalty fee registry interface. + */ + IRoyaltyFeeRegistry public immutable royaltyFeeRegistry; + + /** + * @notice Constructor + * @param _royaltyFeeRegistry Royalty fee registry address. + */ + constructor(address _royaltyFeeRegistry) { + royaltyFeeRegistry = IRoyaltyFeeRegistry(_royaltyFeeRegistry); + } + + /** + * @inheritdoc ICreatorFeeManager + * @dev There are two on-chain sources for the royalty fee to distribute. + * 1. RoyaltyFeeRegistry: It is an on-chain registry where creator fee is defined + * for all items of a collection. + * 2. ERC2981: The NFT Royalty Standard where royalty fee is defined at a itemId level in a collection. + * The on-chain logic looks up the registry first. If it does not find anything, + * it checks if a collection is ERC2981. If so, it fetches the proper royalty information for the itemId. + * For a bundle that contains multiple itemIds (for a collection using ERC2981), if the royalty fee/recipient + * differ among the itemIds part of the bundle, the trade reverts. + * This contract DOES NOT enforce any restriction for extremely high creator fee, + * nor verifies the creator fee fetched is inferior to the total price. + * If any contract relies on it to build an on-chain royalty logic, + * it should implement protection against: + * (1) high royalties + * (2) potential unexpected royalty changes that can occur after the creation of the order. + */ + function viewCreatorFeeInfo( + address collection, + uint256 price, + uint256[] memory itemIds + ) external view returns (address creator, uint256 creatorFeeAmount) { + // Check if there is a royalty info in the system + (creator, creatorFeeAmount) = royaltyFeeRegistry.royaltyInfo(collection, price); + + if (creator == address(0)) { + if (IERC2981(collection).supportsInterface(IERC2981.royaltyInfo.selector)) { + uint256 length = itemIds.length; + + for (uint256 i; i < length; ) { + try IERC2981(collection).royaltyInfo(itemIds[i], price) returns ( + address newCreator, + uint256 newCreatorFeeAmount + ) { + if (i == 0) { + creator = newCreator; + creatorFeeAmount = newCreatorFeeAmount; + + unchecked { + ++i; + } + continue; + } + + if (newCreator != creator || newCreatorFeeAmount != creatorFeeAmount) { + revert BundleEIP2981NotAllowed(collection); + } + } catch { + // If creator address is not 0, that means there was at least 1 + // successful call. If all royaltyInfo calls fail, it should assume + // 0 royalty. + // If the first call reverts, even if creator is address(0), subsequent + // successful calls will still revert above with BundleEIP2981NotAllowed + // because newCreator/newCreatorFeeAmount will be different from creator/creatorFeeAmount. + if (creator != address(0)) { + revert BundleEIP2981NotAllowed(collection); + } + } + + unchecked { + ++i; + } + } + } + } + } +} diff --git a/contracts/src/marketplace/CurrencyManager.sol b/contracts/src/marketplace/CurrencyManager.sol new file mode 100644 index 00000000..103d0789 --- /dev/null +++ b/contracts/src/marketplace/CurrencyManager.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { OwnableTwoSteps } from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol"; + +// Interfaces +import { ICurrencyManager } from "./interfaces/ICurrencyManager.sol"; + +/** + * @title CurrencyManager + * @notice This contract manages the list of valid fungible currencies. + * @author LooksRare protocol team (👀,💎) + */ +contract CurrencyManager is ICurrencyManager, OwnableTwoSteps { + /** + * @notice It checks whether the currency is allowed for transacting. + */ + mapping(address => bool) public isCurrencyAllowed; + + /** + * @notice Constructor + * @param _owner Owner address + */ + constructor(address _owner) OwnableTwoSteps(_owner) {} + + /** + * @notice This function allows the owner to update the status of a currency. + * @param currency Currency address (address(0) for ETH) + * @param isAllowed Whether the currency should be allowed for trading + * @dev Only callable by owner. + */ + function updateCurrencyStatus(address currency, bool isAllowed) external onlyOwner { + isCurrencyAllowed[currency] = isAllowed; + emit CurrencyStatusUpdated(currency, isAllowed); + } +} diff --git a/contracts/src/marketplace/ExecutionManager.sol b/contracts/src/marketplace/ExecutionManager.sol new file mode 100644 index 00000000..06de37c1 --- /dev/null +++ b/contracts/src/marketplace/ExecutionManager.sol @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "./libraries/OrderStructs.sol"; + +// Interfaces +import { IExecutionManager } from "./interfaces/IExecutionManager.sol"; +import { ICreatorFeeManager } from "./interfaces/ICreatorFeeManager.sol"; + +// Direct dependencies +import { InheritedStrategy } from "./InheritedStrategy.sol"; +import { NonceManager } from "./NonceManager.sol"; +import { StrategyManager } from "./StrategyManager.sol"; + +// Assembly +import { NoSelectorForStrategy_error_selector, NoSelectorForStrategy_error_length, OutsideOfTimeRange_error_selector, OutsideOfTimeRange_error_length, Error_selector_offset } from "./constants/AssemblyConstants.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "./constants/NumericConstants.sol"; + +// Enums +import { QuoteType } from "./enums/QuoteType.sol"; + +/** + * @title ExecutionManager + * @notice This contract handles the execution and resolution of transactions. A transaction is executed on-chain + * when an off-chain maker order is matched by on-chain taker order of a different kind. + * For instance, a taker ask is executed against a maker bid (or a taker bid against a maker ask). + * @author LooksRare protocol team (👀,💎) + */ +contract ExecutionManager is InheritedStrategy, NonceManager, StrategyManager, IExecutionManager { + /** + * @notice Protocol fee recipient. + */ + address public protocolFeeRecipient; + + /** + * @notice Maximum creator fee (in basis point). + */ + // TODO do we need a max? Is 1% max fair? + uint16 public maxCreatorFeeBp = 1_000; + + /** + * @notice Creator fee manager. + */ + ICreatorFeeManager public creatorFeeManager; + + /** + * @notice Constructor + * @param _owner Owner address + * @param _protocolFeeRecipient Protocol fee recipient address + */ + constructor(address _owner, address _protocolFeeRecipient) StrategyManager(_owner) { + _updateProtocolFeeRecipient(_protocolFeeRecipient); + } + + /** + * @notice This function allows the owner to update the creator fee manager address. + * @param newCreatorFeeManager Address of the creator fee manager + * @dev Only callable by owner. + */ + function updateCreatorFeeManager(address newCreatorFeeManager) external onlyOwner { + creatorFeeManager = ICreatorFeeManager(newCreatorFeeManager); + emit NewCreatorFeeManager(newCreatorFeeManager); + } + + /** + * @notice This function allows the owner to update the maximum creator fee (in basis point). + * @param newMaxCreatorFeeBp New maximum creator fee (in basis point) + * @dev The maximum value that can be set is 25%. + * Only callable by owner. + */ + function updateMaxCreatorFeeBp(uint16 newMaxCreatorFeeBp) external onlyOwner { + if (newMaxCreatorFeeBp > 2_500) { + revert CreatorFeeBpTooHigh(); + } + + maxCreatorFeeBp = newMaxCreatorFeeBp; + + emit NewMaxCreatorFeeBp(newMaxCreatorFeeBp); + } + + /** + * @notice This function allows the owner to update the protocol fee recipient. + * @param newProtocolFeeRecipient New protocol fee recipient address + * @dev Only callable by owner. + */ + function updateProtocolFeeRecipient(address newProtocolFeeRecipient) external onlyOwner { + _updateProtocolFeeRecipient(newProtocolFeeRecipient); + } + + /** + * @notice This function is internal and is used to execute a transaction initiated by a taker order. + * @param takerOrder Taker order struct (taker specific parameters for the execution) + * @param makerOrder Maker order struct (maker specific parameter for the execution) + * @param sender The address that sent the transaction + * @return itemIds Array of item ids to be traded + * @return amounts Array of amounts for each item id + * @return recipients Array of recipient addresses + * @return feeAmounts Array of fee amounts + * @return isNonceInvalidated Whether the order's nonce will be invalidated after executing the order + */ + function _executeStrategyForTakerOrder( + OrderStructs.Taker calldata takerOrder, + OrderStructs.Maker calldata makerOrder, + address sender + ) + internal + returns ( + uint256[] memory itemIds, + uint256[] memory amounts, + address[2] memory recipients, + uint256[3] memory feeAmounts, + bool isNonceInvalidated + ) + { + uint256 price; + + // Verify the order validity for timestamps + _verifyOrderTimestampValidity(makerOrder.startTime, makerOrder.endTime); + + if (makerOrder.strategyId == 0) { + _verifyItemIdsAndAmountsEqualLengthsAndValidAmounts(makerOrder.amounts, makerOrder.itemIds); + (price, itemIds, amounts) = (makerOrder.price, makerOrder.itemIds, makerOrder.amounts); + isNonceInvalidated = true; + } else { + if (strategyInfo[makerOrder.strategyId].isActive) { + /** + * @dev This is equivalent to + * + * if (makerOrder.quoteType == QuoteType.Bid) { + * if (!strategyInfo[makerOrder.strategyId].isMakerBid) { + * revert NoSelectorForStrategy(); + * } + * } else { + * if (strategyInfo[makerOrder.strategyId].isMakerBid) { + * revert NoSelectorForStrategy(); + * } + * } + * + * because one must be 0 and another must be 1 for the function + * to not revert. + * + * Both quoteType (an enum with 2 values) and isMakerBid (a bool) + * can only be 0 or 1. + */ + QuoteType quoteType = makerOrder.quoteType; + bool isMakerBid = strategyInfo[makerOrder.strategyId].isMakerBid; + assembly { + if eq(quoteType, isMakerBid) { + mstore(0x00, NoSelectorForStrategy_error_selector) + revert(Error_selector_offset, NoSelectorForStrategy_error_length) + } + } + + (bool status, bytes memory data) = strategyInfo[makerOrder.strategyId].implementation.call( + abi.encodeWithSelector(strategyInfo[makerOrder.strategyId].selector, takerOrder, makerOrder) + ); + + if (!status) { + // @dev It forwards the revertion message from the low-level call + assembly { + revert(add(data, 32), mload(data)) + } + } + + (price, itemIds, amounts, isNonceInvalidated) = abi.decode(data, (uint256, uint256[], uint256[], bool)); + } else { + revert StrategyNotAvailable(makerOrder.strategyId); + } + } + + // Creator fee and adjustment of protocol fee + (recipients[1], feeAmounts[1]) = _getCreatorRecipientAndCalculateFeeAmount( + makerOrder.collection, + price, + itemIds + ); + if (makerOrder.quoteType == QuoteType.Bid) { + _setTheRestOfFeeAmountsAndRecipients( + makerOrder.strategyId, + price, + takerOrder.recipient == address(0) ? sender : takerOrder.recipient, + feeAmounts, + recipients + ); + } else { + _setTheRestOfFeeAmountsAndRecipients( + makerOrder.strategyId, + price, + makerOrder.signer, + feeAmounts, + recipients + ); + } + } + + /** + * @notice This private function updates the protocol fee recipient. + * @param newProtocolFeeRecipient New protocol fee recipient address + */ + function _updateProtocolFeeRecipient(address newProtocolFeeRecipient) private { + if (newProtocolFeeRecipient == address(0)) { + revert NewProtocolFeeRecipientCannotBeNullAddress(); + } + + protocolFeeRecipient = newProtocolFeeRecipient; + emit NewProtocolFeeRecipient(newProtocolFeeRecipient); + } + + /** + * @notice This function is internal and is used to calculate + * the protocol fee amount for a set of fee amounts. + * @param price Transaction price + * @param strategyId Strategy id + * @param creatorFeeAmount Creator fee amount + * @param minTotalFeeAmount Min total fee amount + * @return protocolFeeAmount Protocol fee amount + */ + function _calculateProtocolFeeAmount( + uint256 price, + uint256 strategyId, + uint256 creatorFeeAmount, + uint256 minTotalFeeAmount + ) private view returns (uint256 protocolFeeAmount) { + protocolFeeAmount = (price * strategyInfo[strategyId].standardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; + + if (protocolFeeAmount + creatorFeeAmount < minTotalFeeAmount) { + protocolFeeAmount = minTotalFeeAmount - creatorFeeAmount; + } + } + + /** + * @notice This function is internal and is used to get the creator fee address + * and calculate the creator fee amount. + * @param collection Collection address + * @param price Transaction price + * @param itemIds Array of item ids + * @return creator Creator recipient + * @return creatorFeeAmount Creator fee amount + */ + function _getCreatorRecipientAndCalculateFeeAmount( + address collection, + uint256 price, + uint256[] memory itemIds + ) private view returns (address creator, uint256 creatorFeeAmount) { + if (address(creatorFeeManager) != address(0)) { + (creator, creatorFeeAmount) = creatorFeeManager.viewCreatorFeeInfo(collection, price, itemIds); + + if (creator == address(0)) { + // If recipient is null address, creator fee is set to 0 + creatorFeeAmount = 0; + } else if (creatorFeeAmount * ONE_HUNDRED_PERCENT_IN_BP > (price * uint256(maxCreatorFeeBp))) { + // If creator fee is higher than tolerated, it reverts + revert CreatorFeeBpTooHigh(); + } + } + } + + /** + * @dev This function does not need to return feeAmounts and recipients as they are modified + * in memory. + */ + function _setTheRestOfFeeAmountsAndRecipients( + uint256 strategyId, + uint256 price, + address askRecipient, + uint256[3] memory feeAmounts, + address[2] memory recipients + ) private view { + // Compute minimum total fee amount + uint256 minTotalFeeAmount = (price * strategyInfo[strategyId].minTotalFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; + + if (feeAmounts[1] == 0) { + // If creator fee is null, protocol fee is set as the minimum total fee amount + feeAmounts[2] = minTotalFeeAmount; + // Net fee amount for seller + feeAmounts[0] = price - feeAmounts[2]; + } else { + // If there is a creator fee information, the protocol fee amount can be calculated + feeAmounts[2] = _calculateProtocolFeeAmount(price, strategyId, feeAmounts[1], minTotalFeeAmount); + // Net fee amount for seller + feeAmounts[0] = price - feeAmounts[1] - feeAmounts[2]; + } + + recipients[0] = askRecipient; + } + + /** + * @notice This function is internal and is used to verify the validity of an order + * in the context of the current block timestamps. + * @param startTime Start timestamp + * @param endTime End timestamp + */ + function _verifyOrderTimestampValidity(uint256 startTime, uint256 endTime) private view { + // if (startTime > block.timestamp || endTime < block.timestamp) revert OutsideOfTimeRange(); + assembly { + if or(gt(startTime, timestamp()), lt(endTime, timestamp())) { + mstore(0x00, OutsideOfTimeRange_error_selector) + revert(Error_selector_offset, OutsideOfTimeRange_error_length) + } + } + } +} diff --git a/contracts/src/marketplace/InheritedStrategy.sol b/contracts/src/marketplace/InheritedStrategy.sol new file mode 100644 index 00000000..9f84b5a1 --- /dev/null +++ b/contracts/src/marketplace/InheritedStrategy.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "./libraries/OrderStructs.sol"; + +// Shared errors +import { OrderInvalid } from "./errors/SharedErrors.sol"; + +// Assembly +import { OrderInvalid_error_selector, OrderInvalid_error_length, Error_selector_offset, OneWord } from "./constants/AssemblyConstants.sol"; + +/** + * @title InheritedStrategy + * @notice This contract handles the verification of parameters for standard transactions. + * It does not verify the taker struct's itemIds and amounts array as well as + * minPrice (taker ask) / maxPrice (taker bid) because before the taker executes the + * transaction and the maker itemIds/amounts/price should have already been confirmed off-chain. + * @dev A standard transaction (bid or ask) is mapped to strategyId = 0. + * @author LooksRare protocol team (👀,💎) + */ +contract InheritedStrategy { + /** + * @notice This function is internal and is used to validate the parameters for a standard sale strategy + * when the standard transaction is initiated by a taker bid. + * @param amounts Array of amounts + * @param itemIds Array of item ids + */ + function _verifyItemIdsAndAmountsEqualLengthsAndValidAmounts( + uint256[] calldata amounts, + uint256[] calldata itemIds + ) internal pure { + assembly { + let end + { + /* + * @dev If A == B, then A XOR B == 0. + * + * if (amountsLength == 0 || amountsLength != itemIdsLength) { + * revert OrderInvalid(); + * } + */ + let amountsLength := amounts.length + let itemIdsLength := itemIds.length + + if or(iszero(amountsLength), xor(amountsLength, itemIdsLength)) { + mstore(0x00, OrderInvalid_error_selector) + revert(Error_selector_offset, OrderInvalid_error_length) + } + + /** + * @dev Shifting left 5 times is equivalent to amountsLength * 32 bytes + */ + end := shl(5, amountsLength) + } + + let amountsOffset := amounts.offset + + for { + + } end { + + } { + /** + * @dev Starting from the end of the array minus 32 bytes to load the last item, + * ending with `end` equal to 0 to load the first item + * + * uint256 end = amountsLength; + * + * for (uint256 i = end - 1; i >= 0; i--) { + * uint256 amount = amounts[i]; + * if (amount == 0) { + * revert OrderInvalid(); + * } + * } + */ + end := sub(end, OneWord) + + let amount := calldataload(add(amountsOffset, end)) + + if iszero(amount) { + mstore(0x00, OrderInvalid_error_selector) + revert(Error_selector_offset, OrderInvalid_error_length) + } + } + } + } +} diff --git a/contracts/src/marketplace/LooksRareProtocol.sol b/contracts/src/marketplace/LooksRareProtocol.sol new file mode 100644 index 00000000..45c6331f --- /dev/null +++ b/contracts/src/marketplace/LooksRareProtocol.sol @@ -0,0 +1,626 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { SignatureCheckerCalldata } from "@looksrare/contracts-libs/contracts/SignatureCheckerCalldata.sol"; +import { LowLevelETHReturnETHIfAnyExceptOneWei } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelETHReturnETHIfAnyExceptOneWei.sol"; +import { LowLevelWETH } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelWETH.sol"; +import { LowLevelERC20Transfer } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC20Transfer.sol"; + +// OpenZeppelin's library (adjusted) for verifying Merkle proofs +import { MerkleProofCalldataWithNodes } from "./libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol"; + +// Libraries +import { OrderStructs } from "./libraries/OrderStructs.sol"; + +// Interfaces +import { ILooksRareProtocol } from "./interfaces/ILooksRareProtocol.sol"; + +// Shared errors +import { CallerInvalid, CurrencyInvalid, LengthsInvalid, MerkleProofInvalid, MerkleProofTooLarge, QuoteTypeInvalid } from "./errors/SharedErrors.sol"; + +// Direct dependencies +import { TransferSelectorNFT } from "./TransferSelectorNFT.sol"; +import { BatchOrderTypehashRegistry } from "./BatchOrderTypehashRegistry.sol"; + +// Constants +import { MAX_CALLDATA_PROOF_LENGTH, ONE_HUNDRED_PERCENT_IN_BP } from "./constants/NumericConstants.sol"; + +// Enums +import { QuoteType } from "./enums/QuoteType.sol"; + +/** + * @title LooksRareProtocol + * @notice This contract is the core smart contract of the LooksRare protocol ("v2"). + * It is the main entry point for users to initiate transactions with taker orders + * and manage the cancellation of maker orders, which exist off-chain. + * ~~~~~~ + * ~~~~ ~~~~ + * ~~~ ~~~ + * ~~~ ~~~ + * ~~~ ~~~ + * ~~~~~~~~~ ~~~ ~~~ ~~~~~~~~~ + * ~~~ ~~~~~~~~~ ~~~~ ~~~~ ~~~~~~~~~ ~~~ + * ~~~ ~~~~~~~ ~~~~~~~ ~~~ + * ~~~- ~~~~~~~~ ~~~~ + * ~~~ ~~~~ ~~~~ ~~~ + * ~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~ + * ~~~ ~~~~~~~~~~~ ~~~~~~~~~~~ ~~~ + * ~~~ ~~~ ~~~ ~~~ + * ~~~ ~~~ ~~~~~~~~~~ ~~~ ~~~ + * ~~~~~ ~~~ ~~~~~~ ~~~~~~ ~~~ ~~~~~ + * ~~~~~~~ ~~~ ~~~ ~~~ ~~~ ~~~~~~~ + * ~~~~~~ ~~~~ ~~~ ~~~ ~~~~ ~~~~~~ + * ~~~~ ~~~ ~~~ ~~~ ~~~ ~~~~ + * ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ + * ~~~~ ~~~ ~~~ ~~~ ~~~ ~~~~ + * ~~~~~~ ~~~~ ~~~ ~~~ ~~~~~ ~~~~~~ + * ~~~~~~~ ~~~ ~~~ ~~~ ~~~ ~~~~~~~ + * ~~~~~ ~~~ ~~~~~~ ~~~~~~ ~~~ ~~~~~ + * ~~~ ~~~ ~~~~~~~~~~ ~~~ ~~~ + * ~~ ~~~ ~~~ ~~~ + * ~~~ ~~~~~~~~~~~ ~~~~~~~~~~~ ~~~ + * ~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~ + * ~~~ ~~~~ ~~~~ ~~~ + * ~~~~ ~~~~~~~~ ~~~~ + * ~~~ ~~~~~~~ ~~~~~~~ ~~~ + * ~~~ ~~~~~~~~ ~~~~ ~~~~ ~~~~~~~~ ~~~ + * ~~~~~~~~~ ~~~ ~~~ ~~~~~~~~~ + * ~~~ ~~~ + * ~~~ ~~~ + * ~~~ ~~~ + * ~~~~ ~~~~ + * ~~~~~~ + * @author LooksRare protocol team (👀,💎) + */ +contract LooksRareProtocol is + ILooksRareProtocol, + TransferSelectorNFT, + LowLevelETHReturnETHIfAnyExceptOneWei, + LowLevelWETH, + LowLevelERC20Transfer, + BatchOrderTypehashRegistry +{ + using OrderStructs for OrderStructs.Maker; + + /** + * @notice Wrapped ETH. + */ + address public immutable WETH; + + /** + * @notice Current chainId. + */ + uint256 public chainId; + + /** + * @notice Current domain separator. + */ + bytes32 public domainSeparator; + + /** + * @notice This variable is used as the gas limit for a ETH transfer. + * If a standard ETH transfer fails within this gas limit, ETH will get wrapped to WETH + * and transferred to the initial recipient. + */ + uint256 private _gasLimitETHTransfer = 2_300; + + /** + * @notice Constructor + * @param _owner Owner address + * @param _protocolFeeRecipient Protocol fee recipient address + * @param _transferManager Transfer manager address + * @param _weth Wrapped ETH address + */ + constructor( + address _owner, + address _protocolFeeRecipient, + address _transferManager, + address _weth + ) TransferSelectorNFT(_owner, _protocolFeeRecipient, _transferManager) { + _updateDomainSeparator(); + WETH = _weth; + } + + /** + * @inheritdoc ILooksRareProtocol + */ + function executeTakerAsk( + OrderStructs.Taker calldata takerAsk, + OrderStructs.Maker calldata makerBid, + bytes calldata makerSignature, + OrderStructs.MerkleTree calldata merkleTree, + address affiliate + ) external nonReentrant { + address currency = makerBid.currency; + + // Verify whether the currency is allowed and is not ETH (address(0)) + if (!isCurrencyAllowed[currency] || currency == address(0)) { + revert CurrencyInvalid(); + } + + address signer = makerBid.signer; + bytes32 orderHash = makerBid.hash(); + _verifyMerkleProofOrOrderHash(merkleTree, orderHash, makerSignature, signer); + + // Execute the transaction and fetch protocol fee amount + uint256 totalProtocolFeeAmount = _executeTakerAsk(takerAsk, makerBid, orderHash); + + // Pay protocol fee (and affiliate fee if any) + _payProtocolFeeAndAffiliateFee(currency, signer, affiliate, totalProtocolFeeAmount); + } + + /** + * @inheritdoc ILooksRareProtocol + */ + function executeTakerBid( + OrderStructs.Taker calldata takerBid, + OrderStructs.Maker calldata makerAsk, + bytes calldata makerSignature, + OrderStructs.MerkleTree calldata merkleTree, + address affiliate + ) external payable nonReentrant { + address currency = makerAsk.currency; + + // Verify whether the currency is allowed for trading. + if (!isCurrencyAllowed[currency]) { + revert CurrencyInvalid(); + } + + bytes32 orderHash = makerAsk.hash(); + _verifyMerkleProofOrOrderHash(merkleTree, orderHash, makerSignature, makerAsk.signer); + + // Execute the transaction and fetch protocol fee amount + uint256 totalProtocolFeeAmount = _executeTakerBid(takerBid, makerAsk, msg.sender, orderHash); + + // Pay protocol fee amount (and affiliate fee if any) + _payProtocolFeeAndAffiliateFee(currency, msg.sender, affiliate, totalProtocolFeeAmount); + + // Return ETH if any + _returnETHIfAnyWithOneWeiLeft(); + } + + /** + * @inheritdoc ILooksRareProtocol + */ + function executeMultipleTakerBids( + OrderStructs.Taker[] calldata takerBids, + OrderStructs.Maker[] calldata makerAsks, + bytes[] calldata makerSignatures, + OrderStructs.MerkleTree[] calldata merkleTrees, + address affiliate, + bool isAtomic + ) external payable nonReentrant { + uint256 length = takerBids.length; + if ( + length == 0 || + (makerAsks.length ^ length) | (makerSignatures.length ^ length) | (merkleTrees.length ^ length) != 0 + ) { + revert LengthsInvalid(); + } + + // Verify whether the currency at index = 0 is allowed for trading + address currency = makerAsks[0].currency; + if (!isCurrencyAllowed[currency]) { + revert CurrencyInvalid(); + } + + { + // Initialize protocol fee amount + uint256 totalProtocolFeeAmount; + + // If atomic, it uses the executeTakerBid function. + // If not atomic, it uses a catch/revert pattern with external function. + if (isAtomic) { + for (uint256 i; i < length; ) { + OrderStructs.Maker calldata makerAsk = makerAsks[i]; + + // Verify the currency is the same + if (i != 0) { + if (makerAsk.currency != currency) { + revert CurrencyInvalid(); + } + } + + OrderStructs.Taker calldata takerBid = takerBids[i]; + bytes32 orderHash = makerAsk.hash(); + + { + _verifyMerkleProofOrOrderHash(merkleTrees[i], orderHash, makerSignatures[i], makerAsk.signer); + + // Execute the transaction and add protocol fee + totalProtocolFeeAmount += _executeTakerBid(takerBid, makerAsk, msg.sender, orderHash); + + unchecked { + ++i; + } + } + } + } else { + for (uint256 i; i < length; ) { + OrderStructs.Maker calldata makerAsk = makerAsks[i]; + + // Verify the currency is the same + if (i != 0) { + if (makerAsk.currency != currency) { + revert CurrencyInvalid(); + } + } + + OrderStructs.Taker calldata takerBid = takerBids[i]; + bytes32 orderHash = makerAsk.hash(); + + { + _verifyMerkleProofOrOrderHash(merkleTrees[i], orderHash, makerSignatures[i], makerAsk.signer); + + try this.restrictedExecuteTakerBid(takerBid, makerAsk, msg.sender, orderHash) returns ( + uint256 protocolFeeAmount + ) { + totalProtocolFeeAmount += protocolFeeAmount; + } catch {} + + unchecked { + ++i; + } + } + } + } + + // Pay protocol fee (and affiliate fee if any) + _payProtocolFeeAndAffiliateFee(currency, msg.sender, affiliate, totalProtocolFeeAmount); + } + + // Return ETH if any + _returnETHIfAnyWithOneWeiLeft(); + } + + /** + * @notice This function is used to do a non-atomic matching in the context of a batch taker bid. + * @param takerBid Taker bid struct + * @param makerAsk Maker ask struct + * @param sender Sender address (i.e. the initial msg sender) + * @param orderHash Hash of the maker ask order + * @return protocolFeeAmount Protocol fee amount + * @dev This function is only callable by this contract. It is used for non-atomic batch order matching. + */ + function restrictedExecuteTakerBid( + OrderStructs.Taker calldata takerBid, + OrderStructs.Maker calldata makerAsk, + address sender, + bytes32 orderHash + ) external returns (uint256 protocolFeeAmount) { + if (msg.sender != address(this)) { + revert CallerInvalid(); + } + + protocolFeeAmount = _executeTakerBid(takerBid, makerAsk, sender, orderHash); + } + + /** + * @notice This function allows the owner to update the domain separator (if possible). + * @dev Only callable by owner. If there is a fork of the network with a new chainId, + * it allows the owner to reset the domain separator for the new chain id. + */ + function updateDomainSeparator() external onlyOwner { + if (block.chainid != chainId) { + _updateDomainSeparator(); + emit NewDomainSeparator(); + } else { + revert SameDomainSeparator(); + } + } + + /** + * @notice This function allows the owner to update the maximum ETH gas limit for a standard transfer. + * @param newGasLimitETHTransfer New gas limit for ETH transfer + * @dev Only callable by owner. + */ + function updateETHGasLimitForTransfer(uint256 newGasLimitETHTransfer) external onlyOwner { + if (newGasLimitETHTransfer < 2_300) { + revert NewGasLimitETHTransferTooLow(); + } + + _gasLimitETHTransfer = newGasLimitETHTransfer; + + emit NewGasLimitETHTransfer(newGasLimitETHTransfer); + } + + /** + * @notice This function is internal and is used to execute a taker ask (against a maker bid). + * @param takerAsk Taker ask order struct + * @param makerBid Maker bid order struct + * @param orderHash Hash of the maker bid order + * @return protocolFeeAmount Protocol fee amount + */ + function _executeTakerAsk( + OrderStructs.Taker calldata takerAsk, + OrderStructs.Maker calldata makerBid, + bytes32 orderHash + ) internal returns (uint256) { + if (makerBid.quoteType != QuoteType.Bid) { + revert QuoteTypeInvalid(); + } + + address signer = makerBid.signer; + { + bytes32 userOrderNonceStatus = userOrderNonce[signer][makerBid.orderNonce]; + // Verify nonces + if ( + userBidAskNonces[signer].bidNonce != makerBid.globalNonce || + userSubsetNonce[signer][makerBid.subsetNonce] || + (userOrderNonceStatus != bytes32(0) && userOrderNonceStatus != orderHash) + ) { + revert NoncesInvalid(); + } + } + + ( + uint256[] memory itemIds, + uint256[] memory amounts, + address[2] memory recipients, + uint256[3] memory feeAmounts, + bool isNonceInvalidated + ) = _executeStrategyForTakerOrder(takerAsk, makerBid, msg.sender); + + // Order nonce status is updated + _updateUserOrderNonce(isNonceInvalidated, signer, makerBid.orderNonce, orderHash); + + // Taker action goes first + _transferNFT(makerBid.collection, makerBid.collectionType, msg.sender, signer, itemIds, amounts); + + // Maker action goes second + _transferToAskRecipientAndCreatorIfAny(recipients, feeAmounts, makerBid.currency, signer); + + emit TakerAsk( + NonceInvalidationParameters({ + orderHash: orderHash, + orderNonce: makerBid.orderNonce, + isNonceInvalidated: isNonceInvalidated + }), + msg.sender, + signer, + makerBid.strategyId, + makerBid.currency, + makerBid.collection, + itemIds, + amounts, + recipients, + feeAmounts + ); + + // It returns the protocol fee amount + return feeAmounts[2]; + } + + /** + * @notice This function is internal and is used to execute a taker bid (against a maker ask). + * @param takerBid Taker bid order struct + * @param makerAsk Maker ask order struct + * @param sender Sender of the transaction (i.e. msg.sender) + * @param orderHash Hash of the maker ask order + * @return protocolFeeAmount Protocol fee amount + */ + function _executeTakerBid( + OrderStructs.Taker calldata takerBid, + OrderStructs.Maker calldata makerAsk, + address sender, + bytes32 orderHash + ) internal returns (uint256) { + if (makerAsk.quoteType != QuoteType.Ask) { + revert QuoteTypeInvalid(); + } + + address signer = makerAsk.signer; + { + // Verify nonces + bytes32 userOrderNonceStatus = userOrderNonce[signer][makerAsk.orderNonce]; + + if ( + userBidAskNonces[signer].askNonce != makerAsk.globalNonce || + userSubsetNonce[signer][makerAsk.subsetNonce] || + (userOrderNonceStatus != bytes32(0) && userOrderNonceStatus != orderHash) + ) { + revert NoncesInvalid(); + } + } + + ( + uint256[] memory itemIds, + uint256[] memory amounts, + address[2] memory recipients, + uint256[3] memory feeAmounts, + bool isNonceInvalidated + ) = _executeStrategyForTakerOrder(takerBid, makerAsk, msg.sender); + + // Order nonce status is updated + _updateUserOrderNonce(isNonceInvalidated, signer, makerAsk.orderNonce, orderHash); + + // Taker action goes first + _transferToAskRecipientAndCreatorIfAny(recipients, feeAmounts, makerAsk.currency, sender); + + // Maker action goes second + _transferNFT( + makerAsk.collection, + makerAsk.collectionType, + signer, + takerBid.recipient == address(0) ? sender : takerBid.recipient, + itemIds, + amounts + ); + + emit TakerBid( + NonceInvalidationParameters({ + orderHash: orderHash, + orderNonce: makerAsk.orderNonce, + isNonceInvalidated: isNonceInvalidated + }), + sender, + takerBid.recipient == address(0) ? sender : takerBid.recipient, + makerAsk.strategyId, + makerAsk.currency, + makerAsk.collection, + itemIds, + amounts, + recipients, + feeAmounts + ); + + // It returns the protocol fee amount + return feeAmounts[2]; + } + + /** + * @notice This function is internal and is used to pay the protocol fee and affiliate fee (if any). + * @param currency Currency address to transfer (address(0) is ETH) + * @param bidUser Bid user address + * @param affiliate Affiliate address (address(0) if none) + * @param totalProtocolFeeAmount Total protocol fee amount (denominated in the currency) + */ + function _payProtocolFeeAndAffiliateFee( + address currency, + address bidUser, + address affiliate, + uint256 totalProtocolFeeAmount + ) internal { + if (totalProtocolFeeAmount != 0) { + // Transfer remaining protocol fee to the protocol fee recipient + _transferFungibleTokens(currency, bidUser, protocolFeeRecipient, totalProtocolFeeAmount); + } + } + + /** + * @notice This function is internal and is used to transfer fungible tokens. + * @param currency Currency address + * @param sender Sender address + * @param recipient Recipient address + * @param amount Amount (in fungible tokens) + */ + function _transferFungibleTokens(address currency, address sender, address recipient, uint256 amount) internal { + if (currency == address(0)) { + _transferETHAndWrapIfFailWithGasLimit(WETH, recipient, amount, _gasLimitETHTransfer); + } else { + _executeERC20TransferFrom(currency, sender, recipient, amount); + } + } + + /** + * @notice This function is private and used to transfer funds to + * (1) creator recipient (if any) + * (2) ask recipient. + * @param recipients Recipient addresses + * @param feeAmounts Fees + * @param currency Currency address + * @param bidUser Bid user address + * @dev It does not send to the 0-th element in the array since it is the protocol fee, + * which is paid later in the execution flow. + */ + function _transferToAskRecipientAndCreatorIfAny( + address[2] memory recipients, + uint256[3] memory feeAmounts, + address currency, + address bidUser + ) private { + // @dev There is no check for address(0) since the ask recipient can never be address(0) + // If ask recipient is the maker --> the signer cannot be the null address + // If ask is the taker --> either it is the sender address or + // if the recipient (in TakerAsk) is set to address(0), it is adjusted to the original taker address + uint256 sellerProceed = feeAmounts[0]; + if (sellerProceed != 0) { + _transferFungibleTokens(currency, bidUser, recipients[0], sellerProceed); + } + + // @dev There is no check for address(0), if the creator recipient is address(0), the fee is set to 0 + uint256 creatorFeeAmount = feeAmounts[1]; + if (creatorFeeAmount != 0) { + _transferFungibleTokens(currency, bidUser, recipients[1], creatorFeeAmount); + } + } + + /** + * @notice This function is private and used to compute the domain separator and store the current chain id. + */ + function _updateDomainSeparator() private { + domainSeparator = keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256("LooksRareProtocol"), + keccak256(bytes("2")), + block.chainid, + address(this) + ) + ); + chainId = block.chainid; + } + + /** + * @notice This function is internal and is called during the execution of a transaction to decide + * how to map the user's order nonce. + * @param isNonceInvalidated Whether the nonce is being invalidated + * @param signer Signer address + * @param orderNonce Maker user order nonce + * @param orderHash Hash of the order struct + * @dev If isNonceInvalidated is true, this function invalidates the user order nonce for future execution. + * If it is equal to false, this function maps the order hash for this user order nonce + * to prevent other order structs sharing the same order nonce to be executed. + */ + function _updateUserOrderNonce( + bool isNonceInvalidated, + address signer, + uint256 orderNonce, + bytes32 orderHash + ) private { + userOrderNonce[signer][orderNonce] = (isNonceInvalidated ? MAGIC_VALUE_ORDER_NONCE_EXECUTED : orderHash); + } + + /** + * @notice This function is private and used to verify the chain id, compute the digest, and verify the signature. + * @dev If chainId is not equal to the cached chain id, it would revert. + * @param computedHash Hash of order (maker bid or maker ask) or merkle root + * @param makerSignature Signature of the maker + * @param signer Signer address + */ + function _computeDigestAndVerify(bytes32 computedHash, bytes calldata makerSignature, address signer) private view { + if (chainId == block.chainid) { + // \x19\x01 is the standard encoding prefix + SignatureCheckerCalldata.verify( + keccak256(abi.encodePacked("\x19\x01", domainSeparator, computedHash)), + signer, + makerSignature + ); + } else { + revert ChainIdInvalid(); + } + } + + /** + * @notice This function is private and called to verify whether the merkle proofs provided for the order hash + * are correct or verify the order hash if the order is not part of a merkle tree. + * @param merkleTree Merkle tree + * @param orderHash Order hash (can be maker bid hash or maker ask hash) + * @param signature Maker order signature + * @param signer Maker address + * @dev It verifies (1) merkle proof (if necessary) (2) signature is from the expected signer + */ + function _verifyMerkleProofOrOrderHash( + OrderStructs.MerkleTree calldata merkleTree, + bytes32 orderHash, + bytes calldata signature, + address signer + ) private view { + uint256 proofLength = merkleTree.proof.length; + + if (proofLength != 0) { + if (proofLength > MAX_CALLDATA_PROOF_LENGTH) { + revert MerkleProofTooLarge(proofLength); + } + + if (!MerkleProofCalldataWithNodes.verifyCalldata(merkleTree.proof, merkleTree.root, orderHash)) { + revert MerkleProofInvalid(); + } + + orderHash = hashBatchOrder(merkleTree.root, proofLength); + } + + _computeDigestAndVerify(orderHash, signature, signer); + } +} diff --git a/contracts/src/marketplace/NonceManager.sol b/contracts/src/marketplace/NonceManager.sol new file mode 100644 index 00000000..bc3dda7a --- /dev/null +++ b/contracts/src/marketplace/NonceManager.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Interfaces and errors +import { INonceManager } from "./interfaces/INonceManager.sol"; +import { LengthsInvalid } from "./errors/SharedErrors.sol"; + +/** + * @title NonceManager + * @notice This contract handles the nonce logic that is used for invalidating maker orders that exist off-chain. + * The nonce logic revolves around three parts at the user level: + * - order nonce (orders sharing an order nonce are conditional, OCO-like) + * - subset (orders can be grouped under a same subset) + * - bid/ask (all orders can be executed only if the bid/ask nonce matches the user's one on-chain) + * Only the order nonce is invalidated at the time of the execution of a maker order that contains it. + * @author LooksRare protocol team (👀,💎) + */ +contract NonceManager is INonceManager { + /** + * @notice Magic value nonce returned if executed (or cancelled). + */ + bytes32 public constant MAGIC_VALUE_ORDER_NONCE_EXECUTED = keccak256("ORDER_NONCE_EXECUTED"); + + /** + * @notice This tracks the bid and ask nonces for a user address. + */ + mapping(address => UserBidAskNonces) public userBidAskNonces; + + /** + * @notice This checks whether the order nonce for a user was executed or cancelled. + */ + mapping(address => mapping(uint256 => bytes32)) public userOrderNonce; + + /** + * @notice This checks whether the subset nonce for a user was cancelled. + */ + mapping(address => mapping(uint256 => bool)) public userSubsetNonce; + + /** + * @notice This function allows a user to cancel an array of order nonces. + * @param orderNonces Array of order nonces + * @dev It does not check the status of the nonces to save gas + * and to prevent revertion if one of the orders is filled in the same + * block. + */ + function cancelOrderNonces(uint256[] calldata orderNonces) external { + uint256 length = orderNonces.length; + if (length == 0) { + revert LengthsInvalid(); + } + + for (uint256 i; i < length; ) { + userOrderNonce[msg.sender][orderNonces[i]] = MAGIC_VALUE_ORDER_NONCE_EXECUTED; + unchecked { + ++i; + } + } + + emit OrderNoncesCancelled(msg.sender, orderNonces); + } + + /** + * @notice This function allows a user to cancel an array of subset nonces. + * @param subsetNonces Array of subset nonces + * @dev It does not check the status of the nonces to save gas. + */ + function cancelSubsetNonces(uint256[] calldata subsetNonces) external { + uint256 length = subsetNonces.length; + + if (length == 0) { + revert LengthsInvalid(); + } + + for (uint256 i; i < length; ) { + userSubsetNonce[msg.sender][subsetNonces[i]] = true; + unchecked { + ++i; + } + } + + emit SubsetNoncesCancelled(msg.sender, subsetNonces); + } + + /** + * @notice This function increments a user's bid/ask nonces. + * @param bid Whether to increment the user bid nonce + * @param ask Whether to increment the user ask nonce + * @dev The logic for computing the quasi-random number is inspired by Seaport v1.2. + * The pseudo-randomness allows non-deterministic computation of the next ask/bid nonce. + * A deterministic increment would make the cancel-all process non-effective in certain cases + * (orders signed with a greater ask/bid nonce). + * The same quasi-random number is used for incrementing both the bid and ask nonces if both values + * are incremented in the same transaction. + * If this function is used twice in the same block, it will return the same quasiRandomNumber + * but this will not impact the overall business logic. + */ + function incrementBidAskNonces(bool bid, bool ask) external { + // Use second half of the previous block hash as a quasi-random number + uint256 quasiRandomNumber = uint256(blockhash(block.number - 1) >> 128); + uint256 newBidNonce = userBidAskNonces[msg.sender].bidNonce; + uint256 newAskNonce = userBidAskNonces[msg.sender].askNonce; + + if (bid) { + newBidNonce += quasiRandomNumber; + userBidAskNonces[msg.sender].bidNonce = newBidNonce; + } + + if (ask) { + newAskNonce += quasiRandomNumber; + userBidAskNonces[msg.sender].askNonce = newAskNonce; + } + + emit NewBidAskNonces(msg.sender, newBidNonce, newAskNonce); + } +} diff --git a/contracts/src/marketplace/ProtocolFeeRecipient.sol b/contracts/src/marketplace/ProtocolFeeRecipient.sol new file mode 100644 index 00000000..2d3d2c73 --- /dev/null +++ b/contracts/src/marketplace/ProtocolFeeRecipient.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { LowLevelERC20Transfer } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC20Transfer.sol"; +import { IWETH } from "@looksrare/contracts-libs/contracts/interfaces/generic/IWETH.sol"; +import { IERC20 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC20.sol"; + +/** + * @title ProtocolFeeRecipient + * @notice This contract is used to receive protocol fees and transfer them to the fee sharing setter. + * Fee sharing setter cannot receive ETH directly, so we need to use this contract as a middleman + * to convert ETH into WETH before sending it. + * @author LooksRare protocol team (👀,💎) + */ +contract ProtocolFeeRecipient is LowLevelERC20Transfer { + address public immutable FEE_SHARING_SETTER; + IWETH public immutable WETH; + + error NothingToTransfer(); + + constructor(address _feeSharingSetter, address _weth) { + FEE_SHARING_SETTER = _feeSharingSetter; + WETH = IWETH(_weth); + } + + function transferETH() external { + uint256 ethBalance = address(this).balance; + + if (ethBalance != 0) { + WETH.deposit{ value: ethBalance }(); + } + + uint256 wethBalance = IERC20(address(WETH)).balanceOf(address(this)); + + if (wethBalance == 0) { + revert NothingToTransfer(); + } + _executeERC20DirectTransfer(address(WETH), FEE_SHARING_SETTER, wethBalance); + } + + /** + * @param currency ERC20 currency address + */ + function transferERC20(address currency) external { + uint256 balance = IERC20(currency).balanceOf(address(this)); + if (balance == 0) { + revert NothingToTransfer(); + } + _executeERC20DirectTransfer(currency, FEE_SHARING_SETTER, balance); + } + + receive() external payable {} +} diff --git a/contracts/src/marketplace/StrategyManager.sol b/contracts/src/marketplace/StrategyManager.sol new file mode 100644 index 00000000..c80af8df --- /dev/null +++ b/contracts/src/marketplace/StrategyManager.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { CurrencyManager } from "./CurrencyManager.sol"; + +// Interfaces +import { IStrategy } from "./interfaces/IStrategy.sol"; +import { IStrategyManager } from "./interfaces/IStrategyManager.sol"; + +/** + * @title StrategyManager + * @notice This contract handles the addition and the update of execution strategies. + * @author LooksRare protocol team (👀,💎) + */ +contract StrategyManager is IStrategyManager, CurrencyManager { + /** + * @notice This variable keeps the count of how many strategies exist. + * It includes strategies that have been removed. + */ + uint256 private _countStrategies = 1; + + /** + * @notice This returns the strategy information for a strategy id. + */ + mapping(uint256 => Strategy) public strategyInfo; + + /** + * @notice Constructor + * @param _owner Owner address + */ + constructor(address _owner) CurrencyManager(_owner) { + strategyInfo[0] = Strategy({ + isActive: true, + standardProtocolFeeBp: 50, + minTotalFeeBp: 50, + maxProtocolFeeBp: 200, + selector: bytes4(0), + isMakerBid: false, + implementation: address(0) + }); + + emit NewStrategy(0, 50, 50, 200, bytes4(0), false, address(0)); + } + + /** + * @notice This function allows the owner to add a new execution strategy to the protocol. + * @param standardProtocolFeeBp Standard protocol fee (in basis point) + * @param minTotalFeeBp Minimum total fee (in basis point) + * @param maxProtocolFeeBp Maximum protocol fee (in basis point) + * @param selector Function selector for the strategy + * @param isMakerBid Whether the function selector is for maker bid + * @param implementation Implementation address + * @dev Strategies have an id that is incremental. + * Only callable by owner. + */ + function addStrategy( + uint16 standardProtocolFeeBp, + uint16 minTotalFeeBp, + uint16 maxProtocolFeeBp, + bytes4 selector, + bool isMakerBid, + address implementation + ) external onlyOwner { + if (minTotalFeeBp > maxProtocolFeeBp || standardProtocolFeeBp > minTotalFeeBp || maxProtocolFeeBp > 500) { + revert StrategyProtocolFeeTooHigh(); + } + + if (selector == bytes4(0)) { + revert StrategyHasNoSelector(); + } + + if (!IStrategy(implementation).isLooksRareV2Strategy()) { + revert NotV2Strategy(); + } + + strategyInfo[_countStrategies] = Strategy({ + isActive: true, + standardProtocolFeeBp: standardProtocolFeeBp, + minTotalFeeBp: minTotalFeeBp, + maxProtocolFeeBp: maxProtocolFeeBp, + selector: selector, + isMakerBid: isMakerBid, + implementation: implementation + }); + + emit NewStrategy( + _countStrategies++, + standardProtocolFeeBp, + minTotalFeeBp, + maxProtocolFeeBp, + selector, + isMakerBid, + implementation + ); + } + + /** + * @notice This function allows the owner to update parameters for an existing execution strategy. + * @param strategyId Strategy id + * @param isActive Whether the strategy must be active + * @param newStandardProtocolFee New standard protocol fee (in basis point) + * @param newMinTotalFee New minimum total fee (in basis point) + * @dev Only callable by owner. + */ + function updateStrategy( + uint256 strategyId, + bool isActive, + uint16 newStandardProtocolFee, + uint16 newMinTotalFee + ) external onlyOwner { + if (strategyId >= _countStrategies) { + revert StrategyNotUsed(); + } + + if (newMinTotalFee > strategyInfo[strategyId].maxProtocolFeeBp || newStandardProtocolFee > newMinTotalFee) { + revert StrategyProtocolFeeTooHigh(); + } + + strategyInfo[strategyId].isActive = isActive; + strategyInfo[strategyId].standardProtocolFeeBp = newStandardProtocolFee; + strategyInfo[strategyId].minTotalFeeBp = newMinTotalFee; + + emit StrategyUpdated(strategyId, isActive, newStandardProtocolFee, newMinTotalFee); + } +} diff --git a/contracts/src/marketplace/TransferManager.sol b/contracts/src/marketplace/TransferManager.sol new file mode 100644 index 00000000..f0015e67 --- /dev/null +++ b/contracts/src/marketplace/TransferManager.sol @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { OwnableTwoSteps } from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol"; +import { LowLevelERC721Transfer } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC721Transfer.sol"; +import { LowLevelERC1155Transfer } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC1155Transfer.sol"; + +// Interfaces and errors +import { ITransferManager } from "./interfaces/ITransferManager.sol"; +import { AmountInvalid, LengthsInvalid } from "./errors/SharedErrors.sol"; + +// Libraries +import { OrderStructs } from "./libraries/OrderStructs.sol"; + +// Enums +import { CollectionType } from "./enums/CollectionType.sol"; + +/** + * @title TransferManager + * @notice This contract provides the transfer functions for ERC721/ERC1155/Hypercert/Hyperboard for contracts that require them. + * Collection type "0" refers to ERC721 transfer functions. + * Collection type "1" refers to ERC1155 transfer functions. + * Collection type "2" refers to Hypercert transfer functions. + * Collection type "3" refers to Hyperboard transfer functions. + * @dev "Safe" transfer functions for ERC721 are not implemented since they come with added gas costs + * to verify if the recipient is a contract as it requires verifying the receiver interface is valid. + * @author LooksRare protocol team (👀,💎) + */ +// TODO Needs to be updated to split a fraction and transfer the new fraction to the bidder +contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelERC1155Transfer, OwnableTwoSteps { + /** + * @notice This returns whether the user has approved the operator address. + * The first address is the user and the second address is the operator (e.g. LooksRareProtocol). + */ + mapping(address => mapping(address => bool)) public hasUserApprovedOperator; + + /** + * @notice This returns whether the operator address is allowed by this contract's owner. + */ + mapping(address => bool) public isOperatorAllowed; + + /** + * @notice Constructor + * @param _owner Owner address + */ + constructor(address _owner) OwnableTwoSteps(_owner) {} + + /** + * @notice This function transfers items for a single ERC721 collection. + * @param collection Collection address + * @param from Sender address + * @param to Recipient address + * @param itemIds Array of itemIds + * @param amounts Array of amounts + */ + function transferItemsERC721( + address collection, + address from, + address to, + uint256[] calldata itemIds, + uint256[] calldata amounts + ) external { + uint256 length = itemIds.length; + if (length == 0) { + revert LengthsInvalid(); + } + + _isOperatorValidForTransfer(from, msg.sender); + + for (uint256 i; i < length; ) { + if (amounts[i] != 1) { + revert AmountInvalid(); + } + _executeERC721TransferFrom(collection, from, to, itemIds[i]); + unchecked { + ++i; + } + } + } + + /** + * @notice This function transfers items for a single ERC1155 collection. + * @param collection Collection address + * @param from Sender address + * @param to Recipient address + * @param itemIds Array of itemIds + * @param amounts Array of amounts + * @dev It does not allow batch transferring if from = msg.sender since native function should be used. + */ + function transferItemsERC1155( + address collection, + address from, + address to, + uint256[] calldata itemIds, + uint256[] calldata amounts + ) external { + uint256 length = itemIds.length; + + if (length == 0 || amounts.length != length) { + revert LengthsInvalid(); + } + + _isOperatorValidForTransfer(from, msg.sender); + + if (length == 1) { + if (amounts[0] == 0) { + revert AmountInvalid(); + } + _executeERC1155SafeTransferFrom(collection, from, to, itemIds[0], amounts[0]); + } else { + for (uint256 i; i < length; ) { + if (amounts[i] == 0) { + revert AmountInvalid(); + } + + unchecked { + ++i; + } + } + _executeERC1155SafeBatchTransferFrom(collection, from, to, itemIds, amounts); + } + } + + /** + * @notice This function transfers items for a single Hypercert. + * @param collection Collection address + * @param from Sender address + * @param to Recipient address + * @param itemIds Array of itemIds + * @param amounts Array of amounts + * @dev It does not allow batch transferring if from = msg.sender since native function should be used. + */ + function transferItemsHypercert( + address collection, + address from, + address to, + uint256[] calldata itemIds, + uint256[] calldata amounts + ) external { + uint256 length = itemIds.length; + + if (length == 0 || amounts.length != length) { + revert LengthsInvalid(); + } + + _isOperatorValidForTransfer(from, msg.sender); + + if (length == 1) { + if (amounts[0] == 0) { + revert AmountInvalid(); + } + _executeERC1155SafeTransferFrom(collection, from, to, itemIds[0], amounts[0]); + } else { + for (uint256 i; i < length; ) { + if (amounts[i] == 0) { + revert AmountInvalid(); + } + + unchecked { + ++i; + } + } + _executeERC1155SafeBatchTransferFrom(collection, from, to, itemIds, amounts); + } + } + + /** + * @notice This function transfers items for a single Hyperboard. + * @param collection Collection address + * @param from Sender address + * @param to Recipient address + * @param itemIds Array of itemIds + * @param amounts Array of amounts + * @dev It does not allow batch transferring if from = msg.sender since native function should be used. + */ + function transferItemsHyperboard( + address collection, + address from, + address to, + uint256[] calldata itemIds, + uint256[] calldata amounts + ) external { + uint256 length = itemIds.length; + + if (length == 0 || amounts.length != length) { + revert LengthsInvalid(); + } + + _isOperatorValidForTransfer(from, msg.sender); + + if (length == 1) { + if (amounts[0] == 0) { + revert AmountInvalid(); + } + _executeERC1155SafeTransferFrom(collection, from, to, itemIds[0], amounts[0]); + } else { + for (uint256 i; i < length; ) { + if (amounts[i] == 0) { + revert AmountInvalid(); + } + + unchecked { + ++i; + } + } + _executeERC1155SafeBatchTransferFrom(collection, from, to, itemIds, amounts); + } + } + + /** + * @notice This function transfers items across an array of collections that can be both ERC721 and ERC1155. + * @param items Array of BatchTransferItem + * @param from Sender address + * @param to Recipient address + */ + function transferBatchItemsAcrossCollections( + BatchTransferItem[] calldata items, + address from, + address to + ) external { + uint256 itemsLength = items.length; + + if (itemsLength == 0) { + revert LengthsInvalid(); + } + + if (from != msg.sender) { + _isOperatorValidForTransfer(from, msg.sender); + } + + for (uint256 i; i < itemsLength; ) { + uint256[] calldata itemIds = items[i].itemIds; + uint256 itemIdsLengthForSingleCollection = itemIds.length; + uint256[] calldata amounts = items[i].amounts; + + if (itemIdsLengthForSingleCollection == 0 || amounts.length != itemIdsLengthForSingleCollection) { + revert LengthsInvalid(); + } + + CollectionType collectionType = items[i].collectionType; + if (collectionType == CollectionType.ERC721) { + for (uint256 j; j < itemIdsLengthForSingleCollection; ) { + if (amounts[j] != 1) { + revert AmountInvalid(); + } + _executeERC721TransferFrom(items[i].collection, from, to, itemIds[j]); + unchecked { + ++j; + } + } + } else if (collectionType == CollectionType.ERC1155) { + for (uint256 j; j < itemIdsLengthForSingleCollection; ) { + if (amounts[j] == 0) { + revert AmountInvalid(); + } + + unchecked { + ++j; + } + } + _executeERC1155SafeBatchTransferFrom(items[i].collection, from, to, itemIds, amounts); + } + + unchecked { + ++i; + } + } + } + + /** + * @notice This function allows a user to grant approvals for an array of operators. + * Users cannot grant approvals if the operator is not allowed by this contract's owner. + * @param operators Array of operator addresses + * @dev Each operator address must be globally allowed to be approved. + */ + function grantApprovals(address[] calldata operators) external { + uint256 length = operators.length; + + if (length == 0) { + revert LengthsInvalid(); + } + + for (uint256 i; i < length; ) { + address operator = operators[i]; + + if (!isOperatorAllowed[operator]) { + revert OperatorNotAllowed(); + } + + if (hasUserApprovedOperator[msg.sender][operator]) { + revert OperatorAlreadyApprovedByUser(); + } + + hasUserApprovedOperator[msg.sender][operator] = true; + + unchecked { + ++i; + } + } + + emit ApprovalsGranted(msg.sender, operators); + } + + /** + * @notice This function allows a user to revoke existing approvals for an array of operators. + * @param operators Array of operator addresses + * @dev Each operator address must be approved at the user level to be revoked. + */ + function revokeApprovals(address[] calldata operators) external { + uint256 length = operators.length; + if (length == 0) { + revert LengthsInvalid(); + } + + for (uint256 i; i < length; ) { + address operator = operators[i]; + + if (!hasUserApprovedOperator[msg.sender][operator]) { + revert OperatorNotApprovedByUser(); + } + + delete hasUserApprovedOperator[msg.sender][operator]; + unchecked { + ++i; + } + } + + emit ApprovalsRemoved(msg.sender, operators); + } + + /** + * @notice This function allows an operator to be added for the shared transfer system. + * Once the operator is allowed, users can grant NFT approvals to this operator. + * @param operator Operator address to allow + * @dev Only callable by owner. + */ + function allowOperator(address operator) external onlyOwner { + if (isOperatorAllowed[operator]) { + revert OperatorAlreadyAllowed(); + } + + isOperatorAllowed[operator] = true; + + emit OperatorAllowed(operator); + } + + /** + * @notice This function allows the user to remove an operator for the shared transfer system. + * @param operator Operator address to remove + * @dev Only callable by owner. + */ + function removeOperator(address operator) external onlyOwner { + if (!isOperatorAllowed[operator]) { + revert OperatorNotAllowed(); + } + + delete isOperatorAllowed[operator]; + + emit OperatorRemoved(operator); + } + + /** + * @notice This function is internal and verifies whether the transfer + * (by an operator on behalf of a user) is valid. If not, it reverts. + * @param user User address + * @param operator Operator address + */ + function _isOperatorValidForTransfer(address user, address operator) private view { + if (isOperatorAllowed[operator] && hasUserApprovedOperator[user][operator]) { + return; + } + + revert TransferCallerInvalid(); + } +} diff --git a/contracts/src/marketplace/TransferSelectorNFT.sol b/contracts/src/marketplace/TransferSelectorNFT.sol new file mode 100644 index 00000000..5e504203 --- /dev/null +++ b/contracts/src/marketplace/TransferSelectorNFT.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Direct dependencies +import { PackableReentrancyGuard } from "@looksrare/contracts-libs/contracts/PackableReentrancyGuard.sol"; +import { ExecutionManager } from "./ExecutionManager.sol"; +import { TransferManager } from "./TransferManager.sol"; + +// Libraries +import { OrderStructs } from "./libraries/OrderStructs.sol"; + +// Enums +import { CollectionType } from "./enums/CollectionType.sol"; + +/** + * @title TransferSelectorNFT + * @notice This contract handles the logic for transferring non-fungible items. + * @author LooksRare protocol team (👀,💎) + */ +contract TransferSelectorNFT is ExecutionManager, PackableReentrancyGuard { + error UnsupportedCollectionType(); + /** + * @notice Transfer manager for ERC721 and ERC1155. + */ + + TransferManager public immutable transferManager; + + /** + * @notice Constructor + * @param _owner Owner address + * @param _protocolFeeRecipient Protocol fee recipient address + * @param _transferManager Address of the transfer manager for ERC721/ERC1155 + */ + constructor( + address _owner, + address _protocolFeeRecipient, + address _transferManager + ) ExecutionManager(_owner, _protocolFeeRecipient) { + transferManager = TransferManager(_transferManager); + } + + /** + * @notice This function is internal and used to transfer non-fungible tokens. + * @param collection Collection address + * @param collectionType Collection type (e.g. 0 = ERC721, 1 = ERC1155) + * @param sender Sender address + * @param recipient Recipient address + * @param itemIds Array of itemIds + * @param amounts Array of amounts + */ + function _transferNFT( + address collection, + CollectionType collectionType, + address sender, + address recipient, + uint256[] memory itemIds, + uint256[] memory amounts + ) internal { + if (collectionType == CollectionType.ERC721) { + transferManager.transferItemsERC721(collection, sender, recipient, itemIds, amounts); + } else if (collectionType == CollectionType.ERC1155) { + transferManager.transferItemsERC1155(collection, sender, recipient, itemIds, amounts); + } else if (collectionType == CollectionType.Hypercert) { + transferManager.transferItemsERC1155(collection, sender, recipient, itemIds, amounts); + } else if (collectionType == CollectionType.Hyperboard) { + revert UnsupportedCollectionType(); + } + } +} diff --git a/contracts/src/marketplace/constants/AssemblyConstants.sol b/contracts/src/marketplace/constants/AssemblyConstants.sol new file mode 100644 index 00000000..8557dece --- /dev/null +++ b/contracts/src/marketplace/constants/AssemblyConstants.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/* + * @dev error OrderInvalid() + * Memory layout: + * - 0x00: Left-padded selector (data begins at 0x1c) + * Revert buffer is memory[0x1c:0x20] + */ +uint256 constant OrderInvalid_error_selector = 0x2e0c0f71; +uint256 constant OrderInvalid_error_length = 0x04; + +/* + * @dev error CurrencyInvalid() + * Memory layout: + * - 0x00: Left-padded selector (data begins at 0x1c) + * Revert buffer is memory[0x1c:0x20] + */ +uint256 constant CurrencyInvalid_error_selector = 0x4f795487; +uint256 constant CurrencyInvalid_error_length = 0x04; + +/* + * @dev error OutsideOfTimeRange() + * Memory layout: + * - 0x00: Left-padded selector (data begins at 0x1c) + * Revert buffer is memory[0x1c:0x20] + */ +uint256 constant OutsideOfTimeRange_error_selector = 0x7476320f; +uint256 constant OutsideOfTimeRange_error_length = 0x04; + +/* + * @dev error NoSelectorForStrategy() + * Memory layout: + * - 0x00: Left-padded selector (data begins at 0x1c) + * Revert buffer is memory[0x1c:0x20] + */ +uint256 constant NoSelectorForStrategy_error_selector = 0xab984846; +uint256 constant NoSelectorForStrategy_error_length = 0x04; + +uint256 constant Error_selector_offset = 0x1c; + +uint256 constant OneWord = 0x20; diff --git a/contracts/src/marketplace/constants/NumericConstants.sol b/contracts/src/marketplace/constants/NumericConstants.sol new file mode 100644 index 00000000..63029eea --- /dev/null +++ b/contracts/src/marketplace/constants/NumericConstants.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @dev 100% represented in basis point is 10_000. + */ +uint256 constant ONE_HUNDRED_PERCENT_IN_BP = 10_000; + +/** + * @dev The maximum length of a proof for a batch order is 10. + * The maximum merkle tree that can used for signing has a height of + * 2**10 = 1_024. + */ +uint256 constant MAX_CALLDATA_PROOF_LENGTH = 10; diff --git a/contracts/src/marketplace/constants/ValidationCodeConstants.sol b/contracts/src/marketplace/constants/ValidationCodeConstants.sol new file mode 100644 index 00000000..73cbc996 --- /dev/null +++ b/contracts/src/marketplace/constants/ValidationCodeConstants.sol @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * 0. No error + */ + +/** + * @dev The maker order is expected to be valid. + * There can be other reasons that cause makers orders to be + * invalid (e.g. trading restrictions for the protocol, fallbacks). + */ +uint256 constant ORDER_EXPECTED_TO_BE_VALID = 0; + +/** + * 1. Strategy & currency-related codes + */ + +/** + * @dev The currency is not allowed in the protocol. + * This maker order could become valid only with owner action. + * If the order is a maker bid and currency = address(0), it is permanently invalid. + */ +uint256 constant CURRENCY_NOT_ALLOWED = 101; + +/** + * @dev The strategy is not implemented in the protocol. + * This maker order can become valid only with owner action. + */ +uint256 constant STRATEGY_NOT_IMPLEMENTED = 111; + +/** + * @dev The strategy is not for this quote type. + * This maker order can never become valid. + */ +uint256 constant STRATEGY_INVALID_QUOTE_TYPE = 112; + +/** + * @dev The strategy exists but is not currently active. + * This maker order can become valid again only with owner action. + */ +uint256 constant STRATEGY_NOT_ACTIVE = 113; + +/** + * 2. Maker order struct-related codes + */ + +/** + * @dev The maker order is permanently invalid for a standard sale (e.g. invalid collection type or amounts) + * This maker order cannot become valid again. + */ +uint256 constant MAKER_ORDER_INVALID_STANDARD_SALE = 201; + +/** + * @dev The maker order is permanently invalid for a non-standard sale strategy. + * This maker order cannot become valid again. + */ +uint256 constant MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE = 211; + +/** + * @dev The maker order is invalid due to a currency support. + * This maker order may become valid in the future depending on the strategy's currency support. + * Please refer to the strategy's implementation code. + */ +uint256 constant MAKER_ORDER_INVALID_CURRENCY_NON_STANDARD_SALE = 212; + +/** + * @dev The maker order is temporarily invalid due to a strategy-specific reason. + * This maker order may become valid in the future. + * Please refer to the strategy's implementation code. + */ +uint256 constant MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE = 213; + +/** + * 3. Nonce-related codes + */ + +/** + * @dev The signer's subset nonce is cancelled. + * This maker order will not become valid again. + */ +uint256 constant USER_SUBSET_NONCE_CANCELLED = 301; + +/** + * @dev The signer's order nonce is executed or cancelled. + * This maker order will not become valid again. + */ +uint256 constant USER_ORDER_NONCE_EXECUTED_OR_CANCELLED = 311; + +/** + * @dev The signer's order nonce is in partial fill status with an other order hash. + * This maker order will not become valid again. + */ +uint256 constant USER_ORDER_NONCE_IN_EXECUTION_WITH_OTHER_HASH = 312; + +/** + * @dev The signer's global bid nonce is not matching the order's bid nonce. + * This maker order will not become valid again. + */ +uint256 constant INVALID_USER_GLOBAL_BID_NONCE = 321; + +/** + * @dev The signer's global ask nonce is not matching the order's ask nonce. + * This maker order will not become valid again. + */ +uint256 constant INVALID_USER_GLOBAL_ASK_NONCE = 322; + +/** + * 4. Codes related to signatures (EOA, EIP-1271) and merkle tree computations + */ + +/** + * @dev The order hash proof is not in the merkle tree. + * This maker order is not valid with the set of merkle root and proofs. + * It cannot become valid with the current merkle proof and root. + */ +uint256 constant ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE = 401; + +/** + * @dev The merkle proof is too large to be verified according. + * There is a proof's size limit defined in the MerkleProofCalldataWithNodes. + * It cannot become valid with the current merkle proof and root. + */ +uint256 constant MERKLE_PROOF_PROOF_TOO_LARGE = 402; + +/** + * @dev The signature's length is invalid. + * The signature's length must be either 64 or 65 bytes. + * This maker order will never be valid. + */ +uint256 constant INVALID_SIGNATURE_LENGTH = 411; + +/** + * @dev The signature's s parameter is invalid. + * This maker order will never be valid. + */ +uint256 constant INVALID_S_PARAMETER_EOA = 412; + +/** + * @dev The signature's v parameter is invalid. + * It must be either equal to 27 or 28. + * This maker order will never be valid with this signature. + */ +uint256 constant INVALID_V_PARAMETER_EOA = 413; + +/** + * @dev The signer recovered (using ecrecover) is the null address. + * This maker order will never be valid with this signature. + */ +uint256 constant NULL_SIGNER_EOA = 414; + +/** + * @dev The recovered signer is not the target signer. + * This maker order will never be valid with this signature. + */ +uint256 constant INVALID_SIGNER_EOA = 415; + +/** + * @dev The signature is generated by a EIP1271 signer contract but the + * contract does not implement the required function to verify the signature. + */ +uint256 constant MISSING_IS_VALID_SIGNATURE_FUNCTION_EIP1271 = 421; + +/** + * @dev The signature by the EIP1271 signer contract is invalid. + * This maker order may become valid again depending on the implementation of the + * contract signing the order. + */ +uint256 constant SIGNATURE_INVALID_EIP1271 = 422; + +/** + * 5. Timestamp-related codes + */ + +/** + * @dev The start time is greater than the end time. + * This maker order will never be valid. + */ +uint256 constant START_TIME_GREATER_THAN_END_TIME = 501; + +/** + * @dev The block time is greater than the end time. + * This maker order will never be valid. + */ +uint256 constant TOO_LATE_TO_EXECUTE_ORDER = 502; + +/** + * @dev The block time is earlier than the start time. + * A buffer of 5 minutes is included for orders that are about to be valid. + * This maker order will become valid without any user action. + */ +uint256 constant TOO_EARLY_TO_EXECUTE_ORDER = 503; + +/** + * 6. Transfer-related (ERC20, ERC721, ERC1155 tokens), including transfers and approvals, codes. + */ + +/** + * @dev The same itemId is twice in the bundle. + * This maker order can be valid for ERC1155 collections but will never be valid for ERC721. + */ +uint256 constant SAME_ITEM_ID_IN_BUNDLE = 601; + +/** + * @dev The ERC20 balance of the signer (maker bid user) is inferior to the order bid price. + * This maker order can become valid without any user's action. + */ +uint256 constant ERC20_BALANCE_INFERIOR_TO_PRICE = 611; + +/** + * @dev The ERC20 approval amount of the signer (maker bid user) is inferior to the order bid price. + * This maker order can become valid only with the user's action. + */ +uint256 constant ERC20_APPROVAL_INFERIOR_TO_PRICE = 612; + +/** + * @dev The ERC721 itemId does not exist. + * This maker order can become valid if the item is created later. + */ +uint256 constant ERC721_ITEM_ID_DOES_NOT_EXIST = 621; + +/** + * @dev The ERC721 itemId is not owned by the signer (maker ask user). + * This maker order can become valid without any user's action. + */ +uint256 constant ERC721_ITEM_ID_NOT_IN_BALANCE = 622; + +/** + * @dev The transfer manager contract has not been approved by the ERC721 collection + * contract, either for the entire collection or the itemId. + * This maker order can become valid only with the user's action. + * The collection may not follow the ERC721 standard. + */ +uint256 constant ERC721_NO_APPROVAL_FOR_ALL_OR_ITEM_ID = 623; + +/** + * @dev The ERC1155 collection contract does not implement balanceOf. + */ +uint256 constant ERC1155_BALANCE_OF_DOES_NOT_EXIST = 631; + +/** + * @dev The ERC20 balance of the signer (maker ask user) is inferior to the amount + * required to be sold. + * This maker order can become valid without any user's action. + */ +uint256 constant ERC1155_BALANCE_OF_ITEM_ID_INFERIOR_TO_AMOUNT = 632; + +/** + * @dev The ERC1155 collection contract does not implement isApprovedForAll. + * The collection may not follow the ERC1155 standard. + */ +uint256 constant ERC1155_IS_APPROVED_FOR_ALL_DOES_NOT_EXIST = 633; + +/** + * @dev The transfer manager contract has not been approved by the ERC1155 + * collection contract. + * This maker order can become valid only with the user's action. + */ +uint256 constant ERC1155_NO_APPROVAL_FOR_ALL = 634; + +/** + * 7. Asset-type codes + */ + +/** + * @dev The collection type specified in the order seems incorrect. + * It is expected to be collectionType = 0. + */ +uint256 constant POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC721 = 701; + +/** + * @dev The collection type specified in the order seems incorrect. + * It is expected to be collectionType = 1. + */ +uint256 constant POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC1155 = 702; + +/** + * 8. Transfer manager-related codes + */ + +/** + * @dev The user has not approved the protocol to transfer NFTs on behalf + * of the user. + * This maker order can become valid only with the user's action. + */ +uint256 constant NO_TRANSFER_MANAGER_APPROVAL_BY_USER_FOR_EXCHANGE = 801; + +/** + * @dev The transfer manager's owner has revoked the ability to transfer NFTs + * on behalf of all users that have also approved the protocol. + * This maker order can become valid again only with owner action. + */ +uint256 constant TRANSFER_MANAGER_APPROVAL_REVOKED_BY_OWNER_FOR_EXCHANGE = 802; + +/** + * 9. Creator fee-related codes + */ + +/** + * @dev The collection contract has a flexible royalty fee structure that + * prevents this bundle to be traded. + * It applies at the protocol level. + * For instance, 2 items in a bundle have different creator recipients. + */ +uint256 constant BUNDLE_ERC2981_NOT_SUPPORTED = 901; + +/** + * @dev The creator fee applied at the protocol is higher than the threshold + * allowed. The transaction will revert. + * It applies at the protocol level. + * This maker order can become valid only with the creator's action. + */ +uint256 constant CREATOR_FEE_TOO_HIGH = 902; diff --git a/contracts/src/marketplace/enums/CollectionType.sol b/contracts/src/marketplace/enums/CollectionType.sol new file mode 100644 index 00000000..d95a2dc7 --- /dev/null +++ b/contracts/src/marketplace/enums/CollectionType.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @notice CollectionType is used in OrderStructs.Maker's collectionType to determine the collection type being traded. + */ +//TODO remove 721??? +enum CollectionType { + ERC721, + ERC1155, + Hypercert, + Hyperboard +} diff --git a/contracts/src/marketplace/enums/QuoteType.sol b/contracts/src/marketplace/enums/QuoteType.sol new file mode 100644 index 00000000..2cb766d7 --- /dev/null +++ b/contracts/src/marketplace/enums/QuoteType.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @notice QuoteType is used in OrderStructs.Maker's quoteType to determine whether the maker order is a bid or an ask. + */ +enum QuoteType { + Bid, + Ask +} diff --git a/contracts/src/marketplace/errors/ChainlinkErrors.sol b/contracts/src/marketplace/errors/ChainlinkErrors.sol new file mode 100644 index 00000000..bb21b470 --- /dev/null +++ b/contracts/src/marketplace/errors/ChainlinkErrors.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @notice It is returned if the Chainlink price is invalid (e.g. negative). + */ +error ChainlinkPriceInvalid(); + +/** + * @notice It is returned if the decimals from the NFT floor price feed is invalid. + * Chainlink price feeds are expected to have 18 decimals. + * @dev It can only be returned for owner operations. + */ +error DecimalsInvalid(); + +/** + * @notice It is returned if the fixed discount for a maker bid is greater than floor price. + */ +error DiscountGreaterThanFloorPrice(); + +/** + * @notice It is returned if the latency tolerance is set too high (i.e. greater than 3,600 sec). + */ +error LatencyToleranceTooHigh(); + +/** + * @notice It is returned if the price feed for a collection is already set. + * @dev It can only be returned for owner operations. + */ +error PriceFeedAlreadySet(); + +/** + * @notice It is returned when the price feed is not available. + */ +error PriceFeedNotAvailable(); + +/** + * @notice It is returned if the current block time relative to the latest price's update time + * is greater than the latency tolerance. + */ +error PriceNotRecentEnough(); diff --git a/contracts/src/marketplace/errors/SharedErrors.sol b/contracts/src/marketplace/errors/SharedErrors.sol new file mode 100644 index 00000000..bb123902 --- /dev/null +++ b/contracts/src/marketplace/errors/SharedErrors.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @notice It is returned if the amount is invalid. + * For ERC721, any number that is not 1. For ERC1155, if amount is 0. + */ +error AmountInvalid(); + +/** + * @notice It is returned if the ask price is too high for the bid user. + */ +error AskTooHigh(); + +/** + * @notice It is returned if the bid price is too low for the ask user. + */ +error BidTooLow(); + +/** + * @notice It is returned if the function cannot be called by the sender. + */ +error CallerInvalid(); + +/** + * @notice It is returned if the currency is invalid. + */ +error CurrencyInvalid(); + +/** + * @notice The function selector is invalid for this strategy implementation. + */ +error FunctionSelectorInvalid(); + +/** + * @notice It is returned if there is either a mismatch or an error in the length of the array(s). + */ +error LengthsInvalid(); + +/** + * @notice It is returned if the merkle proof provided is invalid. + */ +error MerkleProofInvalid(); + +/** + * @notice It is returned if the length of the merkle proof provided is greater than tolerated. + * @param length Proof length + */ +error MerkleProofTooLarge(uint256 length); + +/** + * @notice It is emitted if the call recipient is not a contract. + */ +error NotAContract(); + +/** + * @notice It is returned if the order is permanently invalid. + * There may be an issue with the order formatting. + */ +error OrderInvalid(); + +/** + * @notice It is returned if the maker quote type is invalid. + */ +error QuoteTypeInvalid(); diff --git a/contracts/src/marketplace/executionStrategies/BaseStrategy.sol b/contracts/src/marketplace/executionStrategies/BaseStrategy.sol new file mode 100644 index 00000000..75ce5f87 --- /dev/null +++ b/contracts/src/marketplace/executionStrategies/BaseStrategy.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Interfaces +import { IStrategy } from "../interfaces/IStrategy.sol"; + +// Assembly constants +import { OrderInvalid_error_selector } from "../constants/AssemblyConstants.sol"; + +// Libraries +import { OrderStructs } from "../libraries/OrderStructs.sol"; + +// Enums +import { CollectionType } from "../enums/CollectionType.sol"; + +/** + * @title BaseStrategy + * @author LooksRare protocol team (👀,💎) + */ +abstract contract BaseStrategy is IStrategy { + /** + * @inheritdoc IStrategy + */ + function isLooksRareV2Strategy() external pure override returns (bool) { + return true; + } + + /** + * @dev This is equivalent to + * if (amount == 0 || (amount != 1 && collectionType == 0)) { + * return (0, OrderInvalid.selector); + * } + * @dev OrderInvalid_error_selector is a left-padded 4 bytes. If the error selector is returned + * instead of reverting, the error selector needs to be right-padded by + * 28 bytes. Therefore it needs to be left shifted by 28 x 8 = 224 bits. + */ + function _validateAmountNoRevert(uint256 amount, CollectionType collectionType) internal pure { + assembly { + if or(iszero(amount), and(xor(amount, 1), iszero(collectionType))) { + mstore(0x00, 0x00) + mstore(0x20, shl(224, OrderInvalid_error_selector)) + return(0, 0x40) + } + } + } +} diff --git a/contracts/src/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.sol b/contracts/src/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.sol new file mode 100644 index 00000000..f95a5c12 --- /dev/null +++ b/contracts/src/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { OwnableTwoSteps } from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol"; + +/** + * @title BaseStrategyChainlinkPriceLatency + * @notice This contract allows the owner to define the maximum acceptable Chainlink price latency. + * @author LooksRare protocol team (👀,💎) + */ +contract BaseStrategyChainlinkPriceLatency is OwnableTwoSteps { + /** + * @notice Maximum latency accepted after which + * the execution strategy rejects the retrieved price. + * + * For ETH, it cannot be higher than 3,600 as Chainlink will at least update the + * price every 3,600 seconds, provided ETH's price does not deviate more than 0.5%. + * + * For NFTs, it cannot be higher than 86,400 as Chainlink will at least update the + * price every 86,400 seconds, provided ETH's price does not deviate more than 2%. + */ + uint256 public immutable maxLatency; + + /** + * @notice Constructor + * @param _owner Owner address + * @param _maxLatency Maximum price latency allowed + */ + constructor(address _owner, uint256 _maxLatency) OwnableTwoSteps(_owner) { + maxLatency = _maxLatency; + } +} diff --git a/contracts/src/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol b/contracts/src/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol new file mode 100644 index 00000000..ad6b9f9d --- /dev/null +++ b/contracts/src/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "../../libraries/OrderStructs.sol"; +import { CurrencyValidator } from "../../libraries/CurrencyValidator.sol"; + +// Interfaces +import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; + +// Enums +import { QuoteType } from "../../enums/QuoteType.sol"; + +// Shared errors +import { BidTooLow, OrderInvalid, CurrencyInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "../../errors/SharedErrors.sol"; +import { ChainlinkPriceInvalid, PriceFeedNotAvailable, PriceNotRecentEnough } from "../../errors/ChainlinkErrors.sol"; + +// Base strategy contracts +import { BaseStrategy, IStrategy } from "../BaseStrategy.sol"; +import { BaseStrategyChainlinkPriceLatency } from "./BaseStrategyChainlinkPriceLatency.sol"; + +/** + * @title StrategyChainlinkUSDDynamicAsk + * @notice This contract allows a seller to sell an NFT priced in USD and the receivable amount to be in ETH. + * @author LooksRare protocol team (👀,💎) + */ +contract StrategyChainlinkUSDDynamicAsk is BaseStrategy, BaseStrategyChainlinkPriceLatency { + /** + * @dev It is possible to call priceFeed.decimals() to get the decimals, + * but to save gas, it is hard coded instead. + */ + uint256 public constant ETH_USD_PRICE_FEED_DECIMALS = 1e8; + + /** + * @notice Wrapped ether (WETH) address. + */ + address public immutable WETH; + + /** + * @notice ETH/USD Chainlink price feed + */ + AggregatorV3Interface public immutable priceFeed; + + /** + * @notice Constructor + * @param _weth Wrapped ether address + * @param _owner Owner address + * @param _priceFeed Address of the ETH/USD price feed + */ + constructor(address _owner, address _weth, address _priceFeed) BaseStrategyChainlinkPriceLatency(_owner, 3_600) { + WETH = _weth; + priceFeed = AggregatorV3Interface(_priceFeed); + } + + /** + * @notice This function validates the order under the context of the chosen strategy + * and returns the fulfillable items/amounts/price/nonce invalidation status. + * This strategy looks at the seller's desired sale price in USD and minimum sale price in ETH, + * converts the USD value into ETH using Chainlink's price feed and chooses the higher price. + * @param takerBid Taker bid struct (taker bid-specific parameters for the execution) + * @param makerAsk Maker ask struct (maker ask-specific parameters for the execution) + * @dev The client has to provide the seller's desired sale price in USD as the additionalParameters + */ + function executeStrategyWithTakerBid( + OrderStructs.Taker calldata takerBid, + OrderStructs.Maker calldata makerAsk + ) + external + view + returns (uint256 price, uint256[] memory itemIds, uint256[] memory amounts, bool isNonceInvalidated) + { + uint256 itemIdsLength = makerAsk.itemIds.length; + + if (itemIdsLength == 0 || itemIdsLength != makerAsk.amounts.length) { + revert OrderInvalid(); + } + + CurrencyValidator.allowNativeOrAllowedCurrency(makerAsk.currency, WETH); + + (, int256 answer, , uint256 updatedAt, ) = priceFeed.latestRoundData(); + + if (answer <= 0) { + revert ChainlinkPriceInvalid(); + } + + if (block.timestamp - updatedAt > maxLatency) { + revert PriceNotRecentEnough(); + } + + // The client has to provide a USD value that is augmented by 1e18. + uint256 desiredSalePriceInUSD = abi.decode(makerAsk.additionalParameters, (uint256)); + + uint256 ethPriceInUSD = uint256(answer); + uint256 minPriceInETH = makerAsk.price; + uint256 desiredSalePriceInETH = (desiredSalePriceInUSD * ETH_USD_PRICE_FEED_DECIMALS) / ethPriceInUSD; + + if (minPriceInETH >= desiredSalePriceInETH) { + price = minPriceInETH; + } else { + price = desiredSalePriceInETH; + } + + uint256 maxPrice = abi.decode(takerBid.additionalParameters, (uint256)); + if (maxPrice < price) { + revert BidTooLow(); + } + + itemIds = makerAsk.itemIds; + amounts = makerAsk.amounts; + isNonceInvalidated = true; + } + + /** + * @inheritdoc IStrategy + */ + function isMakerOrderValid( + OrderStructs.Maker calldata makerAsk, + bytes4 functionSelector + ) external view override returns (bool isValid, bytes4 errorSelector) { + if (functionSelector != StrategyChainlinkUSDDynamicAsk.executeStrategyWithTakerBid.selector) { + return (isValid, FunctionSelectorInvalid.selector); + } + + if (makerAsk.quoteType != QuoteType.Ask) { + return (isValid, QuoteTypeInvalid.selector); + } + + uint256 itemIdsLength = makerAsk.itemIds.length; + + if (itemIdsLength == 0 || itemIdsLength != makerAsk.amounts.length) { + return (isValid, OrderInvalid.selector); + } + + for (uint256 i; i < itemIdsLength; ) { + _validateAmountNoRevert(makerAsk.amounts[i], makerAsk.collectionType); + unchecked { + ++i; + } + } + + if (makerAsk.currency != address(0)) { + if (makerAsk.currency != WETH) { + return (isValid, CurrencyInvalid.selector); + } + } + + (, int256 answer, , uint256 updatedAt, ) = priceFeed.latestRoundData(); + + if (answer <= 0) { + return (isValid, ChainlinkPriceInvalid.selector); + } + + if (block.timestamp - updatedAt > maxLatency) { + return (isValid, PriceNotRecentEnough.selector); + } + + isValid = true; + } +} diff --git a/contracts/src/marketplace/executionStrategies/StrategyCollectionOffer.sol b/contracts/src/marketplace/executionStrategies/StrategyCollectionOffer.sol new file mode 100644 index 00000000..90b3b872 --- /dev/null +++ b/contracts/src/marketplace/executionStrategies/StrategyCollectionOffer.sol @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "../libraries/OrderStructs.sol"; + +// OpenZeppelin's library for verifying Merkle proofs +import { MerkleProofMemory } from "../libraries/OpenZeppelin/MerkleProofMemory.sol"; + +// Enums +import { QuoteType } from "../enums/QuoteType.sol"; + +// Shared errors +import { OrderInvalid, FunctionSelectorInvalid, MerkleProofInvalid, QuoteTypeInvalid } from "../errors/SharedErrors.sol"; + +// Base strategy contracts +import { BaseStrategy, IStrategy } from "./BaseStrategy.sol"; + +/** + * @title StrategyCollectionOffer + * @notice This contract offers execution strategies for users to create maker bid offers for items in a collection. + * There are two available functions: + * 1. executeCollectionStrategyWithTakerAsk --> it applies to all itemIds in a collection + * 2. executeCollectionStrategyWithTakerAskWithProof --> it allows adding merkle proof criteria. + * @notice The bidder can only bid on 1 item id at a time. + * 1. If ERC721, the amount must be 1. + * 2. If ERC1155, the amount can be greater than 1. + * @dev Use cases can include trait-based offers or rarity score offers. + * @author LooksRare protocol team (👀,💎) + */ +// TODO This allows for a buyer to declare a set of items they're willing to buy in a merkle tree +contract StrategyCollectionOffer is BaseStrategy { + /** + * @notice This function validates the order under the context of the chosen strategy and + * returns the fulfillable items/amounts/price/nonce invalidation status. + * This strategy executes a collection offer against a taker ask order without the need of merkle proofs. + * @param takerAsk Taker ask struct (taker ask-specific parameters for the execution) + * @param makerBid Maker bid struct (maker bid-specific parameters for the execution) + */ + function executeCollectionStrategyWithTakerAsk( + OrderStructs.Taker calldata takerAsk, + OrderStructs.Maker calldata makerBid + ) + external + pure + returns (uint256 price, uint256[] memory itemIds, uint256[] calldata amounts, bool isNonceInvalidated) + { + price = makerBid.price; + amounts = makerBid.amounts; + + // A collection order can only be executable for 1 itemId but quantity to fill can vary + if (amounts.length != 1) { + revert OrderInvalid(); + } + + uint256 offeredItemId = abi.decode(takerAsk.additionalParameters, (uint256)); + itemIds = new uint256[](1); + itemIds[0] = offeredItemId; + isNonceInvalidated = true; + } + + /** + * @notice This function validates the order under the context of the chosen strategy + * and returns the fulfillable items/amounts/price/nonce invalidation status. + * This strategy executes a collection offer against a taker ask order with the need of a merkle proof. + * @param takerAsk Taker ask struct (taker ask-specific parameters for the execution) + * @param makerBid Maker bid struct (maker bid-specific parameters for the execution) + * @dev The transaction reverts if the maker does not include a merkle root in the additionalParameters. + */ + function executeCollectionStrategyWithTakerAskWithProof( + OrderStructs.Taker calldata takerAsk, + OrderStructs.Maker calldata makerBid + ) + external + pure + returns (uint256 price, uint256[] memory itemIds, uint256[] calldata amounts, bool isNonceInvalidated) + { + price = makerBid.price; + amounts = makerBid.amounts; + + // A collection order can only be executable for 1 itemId but the actual quantity to fill can vary + if (amounts.length != 1) { + revert OrderInvalid(); + } + + (uint256 offeredItemId, bytes32[] memory proof) = abi.decode( + takerAsk.additionalParameters, + (uint256, bytes32[]) + ); + itemIds = new uint256[](1); + itemIds[0] = offeredItemId; + isNonceInvalidated = true; + + bytes32 root = abi.decode(makerBid.additionalParameters, (bytes32)); + bytes32 node = keccak256(abi.encodePacked(offeredItemId)); + + // Verify the merkle root for the given merkle proof + if (!MerkleProofMemory.verify(proof, root, node)) { + revert MerkleProofInvalid(); + } + } + + /** + * @inheritdoc IStrategy + */ + function isMakerOrderValid( + OrderStructs.Maker calldata makerBid, + bytes4 functionSelector + ) external pure override returns (bool isValid, bytes4 errorSelector) { + if ( + functionSelector != StrategyCollectionOffer.executeCollectionStrategyWithTakerAskWithProof.selector && + functionSelector != StrategyCollectionOffer.executeCollectionStrategyWithTakerAsk.selector + ) { + return (isValid, FunctionSelectorInvalid.selector); + } + + if (makerBid.quoteType != QuoteType.Bid) { + return (isValid, QuoteTypeInvalid.selector); + } + + if (makerBid.amounts.length != 1) { + return (isValid, OrderInvalid.selector); + } + + _validateAmountNoRevert(makerBid.amounts[0], makerBid.collectionType); + + // If no root is provided or invalid length, it should be invalid. + // @dev It does not mean the merkle root is valid against a specific itemId that exists in the collection. + if ( + functionSelector == StrategyCollectionOffer.executeCollectionStrategyWithTakerAskWithProof.selector && + makerBid.additionalParameters.length != 32 + ) { + return (isValid, OrderInvalid.selector); + } + + isValid = true; + } +} diff --git a/contracts/src/marketplace/executionStrategies/StrategyDutchAuction.sol b/contracts/src/marketplace/executionStrategies/StrategyDutchAuction.sol new file mode 100644 index 00000000..377539c0 --- /dev/null +++ b/contracts/src/marketplace/executionStrategies/StrategyDutchAuction.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "../libraries/OrderStructs.sol"; + +// Enums +import { QuoteType } from "../enums/QuoteType.sol"; + +// Shared errors +import { BidTooLow, OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "../errors/SharedErrors.sol"; + +// Base strategy contracts +import { BaseStrategy, IStrategy } from "./BaseStrategy.sol"; + +/** + * @title StrategyDutchAuction + * @notice This contract offers a single execution strategy for users to create Dutch auctions. + * @author LooksRare protocol team (👀,💎) + */ +contract StrategyDutchAuction is BaseStrategy { + /** + * @notice This function validates the order under the context of the chosen strategy + * and returns the fulfillable items/amounts/price/nonce invalidation status. + * The execution price set by the seller decreases linearly within the defined period. + * @param takerBid Taker bid struct (taker ask-specific parameters for the execution) + * @param makerAsk Maker ask struct (maker bid-specific parameters for the execution) + * @dev The client has to provide the seller's desired initial start price as the additionalParameters. + */ + function executeStrategyWithTakerBid( + OrderStructs.Taker calldata takerBid, + OrderStructs.Maker calldata makerAsk + ) + external + view + returns (uint256 price, uint256[] memory itemIds, uint256[] memory amounts, bool isNonceInvalidated) + { + uint256 itemIdsLength = makerAsk.itemIds.length; + + if (itemIdsLength == 0 || itemIdsLength != makerAsk.amounts.length) { + revert OrderInvalid(); + } + + uint256 startPrice = abi.decode(makerAsk.additionalParameters, (uint256)); + + if (startPrice < makerAsk.price) { + revert OrderInvalid(); + } + + uint256 startTime = makerAsk.startTime; + uint256 endTime = makerAsk.endTime; + + price = + ((endTime - block.timestamp) * startPrice + (block.timestamp - startTime) * makerAsk.price) / + (endTime - startTime); + + uint256 maxPrice = abi.decode(takerBid.additionalParameters, (uint256)); + if (maxPrice < price) { + revert BidTooLow(); + } + + isNonceInvalidated = true; + + itemIds = makerAsk.itemIds; + amounts = makerAsk.amounts; + } + + /** + * @inheritdoc IStrategy + */ + function isMakerOrderValid( + OrderStructs.Maker calldata makerAsk, + bytes4 functionSelector + ) external pure override returns (bool isValid, bytes4 errorSelector) { + if (functionSelector != StrategyDutchAuction.executeStrategyWithTakerBid.selector) { + return (isValid, FunctionSelectorInvalid.selector); + } + + if (makerAsk.quoteType != QuoteType.Ask) { + return (isValid, QuoteTypeInvalid.selector); + } + + uint256 itemIdsLength = makerAsk.itemIds.length; + + if (itemIdsLength == 0 || itemIdsLength != makerAsk.amounts.length) { + return (isValid, OrderInvalid.selector); + } + + for (uint256 i; i < itemIdsLength; ) { + _validateAmountNoRevert(makerAsk.amounts[i], makerAsk.collectionType); + unchecked { + ++i; + } + } + + uint256 startPrice = abi.decode(makerAsk.additionalParameters, (uint256)); + + if (startPrice < makerAsk.price) { + return (isValid, OrderInvalid.selector); + } + + isValid = true; + } +} diff --git a/contracts/src/marketplace/executionStrategies/StrategyItemIdsRange.sol b/contracts/src/marketplace/executionStrategies/StrategyItemIdsRange.sol new file mode 100644 index 00000000..81ffd51d --- /dev/null +++ b/contracts/src/marketplace/executionStrategies/StrategyItemIdsRange.sol @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "../libraries/OrderStructs.sol"; + +// Enums +import { QuoteType } from "../enums/QuoteType.sol"; + +// Shared errors +import { OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "../errors/SharedErrors.sol"; + +// Base strategy contracts +import { BaseStrategy, IStrategy } from "./BaseStrategy.sol"; + +/** + * @title StrategyItemIdsRange + * @notice This contract offers a single execution strategy for users to bid on + * a specific amount of items in a range bounded by 2 item ids. + * @author LooksRare protocol team (👀,💎) + */ +// TODO this enables bidding on all fractions belonging to a claimID +contract StrategyItemIdsRange is BaseStrategy { + /** + * @notice This function validates the order under the context of the chosen strategy + * and returns the fulfillable items/amounts/price/nonce invalidation status. + * With this strategy, the bidder picks a item id range (e.g. 1-100) + * and a seller can fulfill the order with any tokens within the specified id range. + * @param takerAsk Taker ask struct (taker ask-specific parameters for the execution) + * @param makerBid Maker bid struct (maker bid-specific parameters for the execution) + */ + function executeStrategyWithTakerAsk( + OrderStructs.Taker calldata takerAsk, + OrderStructs.Maker calldata makerBid + ) + external + pure + returns (uint256 price, uint256[] memory itemIds, uint256[] memory amounts, bool isNonceInvalidated) + { + (itemIds, amounts) = abi.decode(takerAsk.additionalParameters, (uint256[], uint256[])); + uint256 length = itemIds.length; + if (length != amounts.length) { + revert OrderInvalid(); + } + + (uint256 minItemId, uint256 maxItemId, uint256 desiredAmount) = abi.decode( + makerBid.additionalParameters, + (uint256, uint256, uint256) + ); + + if (minItemId >= maxItemId || desiredAmount == 0) { + revert OrderInvalid(); + } + + uint256 totalOfferedAmount; + uint256 lastItemId; + + for (uint256 i; i < length; ) { + uint256 offeredItemId = itemIds[i]; + // Force the client to sort the item ids in ascending order, + // in order to prevent taker ask from providing duplicated + // item ids + if (offeredItemId <= lastItemId) { + if (i != 0) { + revert OrderInvalid(); + } + } + + if (offeredItemId < minItemId || offeredItemId > maxItemId) { + revert OrderInvalid(); + } + + totalOfferedAmount += amounts[i]; + + lastItemId = offeredItemId; + + unchecked { + ++i; + } + } + + if (totalOfferedAmount != desiredAmount) { + revert OrderInvalid(); + } + + price = makerBid.price; + isNonceInvalidated = true; + } + + /** + * @inheritdoc IStrategy + */ + function isMakerOrderValid( + OrderStructs.Maker calldata makerBid, + bytes4 functionSelector + ) external pure override returns (bool isValid, bytes4 errorSelector) { + if (functionSelector != StrategyItemIdsRange.executeStrategyWithTakerAsk.selector) { + return (isValid, FunctionSelectorInvalid.selector); + } + + if (makerBid.quoteType != QuoteType.Bid) { + return (isValid, QuoteTypeInvalid.selector); + } + + (uint256 minItemId, uint256 maxItemId, uint256 desiredAmount) = abi.decode( + makerBid.additionalParameters, + (uint256, uint256, uint256) + ); + + if (minItemId >= maxItemId || desiredAmount == 0) { + return (isValid, OrderInvalid.selector); + } + + isValid = true; + } +} diff --git a/contracts/src/marketplace/helpers/OrderValidatorV2A.sol b/contracts/src/marketplace/helpers/OrderValidatorV2A.sol new file mode 100644 index 00000000..2d917b34 --- /dev/null +++ b/contracts/src/marketplace/helpers/OrderValidatorV2A.sol @@ -0,0 +1,865 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IERC165 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC165.sol"; +import { IERC20 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC20.sol"; +import { IERC721 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC721.sol"; +import { IERC1155 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC1155.sol"; +import { IERC1271 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC1271.sol"; + +// Libraries +import { OrderStructs } from "../libraries/OrderStructs.sol"; +import { MerkleProofCalldataWithNodes } from "../libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol"; + +// Interfaces +import { ICreatorFeeManager } from "../interfaces/ICreatorFeeManager.sol"; +import { IStrategy } from "../interfaces/IStrategy.sol"; +import { IRoyaltyFeeRegistry } from "../interfaces/IRoyaltyFeeRegistry.sol"; + +// Shared errors +import { OrderInvalid } from "../errors/SharedErrors.sol"; + +// Other dependencies +import { LooksRareProtocol } from "../LooksRareProtocol.sol"; +import { TransferManager } from "../TransferManager.sol"; + +// Constants +import "../constants/ValidationCodeConstants.sol"; +import { MAX_CALLDATA_PROOF_LENGTH, ONE_HUNDRED_PERCENT_IN_BP } from "../constants/NumericConstants.sol"; + +// Enums +import { CollectionType } from "../enums/CollectionType.sol"; +import { QuoteType } from "../enums/QuoteType.sol"; + +/** + * @title OrderValidatorV2A + * @notice This contract is used to check the validity of maker ask/bid orders in the LooksRareProtocol (v2). + * It performs checks for: + * 1. Protocol allowlist issues (i.e. currency or strategy not allowed) + * 2. Maker order-specific issues (e.g., order invalid due to format or other-strategy specific issues) + * 3. Nonce related issues (e.g., nonce executed or cancelled) + * 4. Signature related issues and merkle tree parameters + * 5. Timestamp related issues (e.g., order expired) + * 6. Asset-related issues for ERC20/ERC721/ERC1155 (approvals and balances) + * 7. Collection-type suggestions + * 8. Transfer manager related issues + * 9. Creator fee related issues (e.g., creator fee too high, ERC2981 bundles) + * @dev This version does not handle strategies with partial fills. + * @author LooksRare protocol team (👀,💎) + */ +//TODO this might need hypercerts specific changes like checking on amount of units in a fraction +contract OrderValidatorV2A { + using OrderStructs for OrderStructs.Maker; + + /** + * @notice ERC721 potential interfaceId. + */ + bytes4 public constant ERC721_INTERFACE_ID_1 = 0x5b5e139f; + + /** + * @notice ERC721 potential interfaceId. + */ + bytes4 public constant ERC721_INTERFACE_ID_2 = 0x80ac58cd; + + /** + * @notice ERC1155 interfaceId. + */ + bytes4 public constant ERC1155_INTERFACE_ID = 0xd9b67a26; + + /** + * @notice Magic value nonce returned if executed (or cancelled). + */ + bytes32 public constant MAGIC_VALUE_ORDER_NONCE_EXECUTED = keccak256("ORDER_NONCE_EXECUTED"); + + /** + * @notice Number of distinct criteria groups checked to evaluate the validity of an order. + */ + uint256 public constant CRITERIA_GROUPS = 9; + + /** + * @notice LooksRareProtocol domain separator. + */ + bytes32 public domainSeparator; + + /** + * @notice Maximum creator fee (in basis point). + */ + uint256 public maxCreatorFeeBp; + + /** + * @notice CreatorFeeManager. + */ + ICreatorFeeManager public creatorFeeManager; + + /** + * @notice LooksRareProtocol. + */ + LooksRareProtocol public looksRareProtocol; + + /** + * @notice TransferManager + */ + TransferManager public transferManager; + + /** + * @notice Constructor + * @param _looksRareProtocol LooksRare protocol address + * @dev It derives automatically other external variables such as the creator fee manager and domain separator. + */ + constructor(address _looksRareProtocol) { + looksRareProtocol = LooksRareProtocol(_looksRareProtocol); + transferManager = looksRareProtocol.transferManager(); + + _deriveProtocolParameters(); + } + + /** + * @notice Derive protocol parameters. Anyone can call this function. + * @dev It allows adjusting if the domain separator or creator fee manager address were to change. + */ + function deriveProtocolParameters() external { + _deriveProtocolParameters(); + } + + /** + * @notice This function verifies the validity of an array of maker orders. + * @param makerOrders Array of maker orders + * @param signatures Array of signatures + * @param merkleTrees Array of merkle trees + * @return validationCodes Arrays of validation codes + */ + function checkMultipleMakerOrderValidities( + OrderStructs.Maker[] calldata makerOrders, + bytes[] calldata signatures, + OrderStructs.MerkleTree[] calldata merkleTrees + ) external view returns (uint256[9][] memory validationCodes) { + uint256 length = makerOrders.length; + + validationCodes = new uint256[CRITERIA_GROUPS][](length); + + for (uint256 i; i < length; ) { + validationCodes[i] = checkMakerOrderValidity(makerOrders[i], signatures[i], merkleTrees[i]); + unchecked { + ++i; + } + } + } + + /** + * @notice This function verifies the validity of a maker order. + * @param makerOrder Maker struct + * @param signature Signature + * @param merkleTree Merkle tree + * @return validationCodes Array of validation codes + */ + function checkMakerOrderValidity( + OrderStructs.Maker calldata makerOrder, + bytes calldata signature, + OrderStructs.MerkleTree calldata merkleTree + ) public view returns (uint256[9] memory validationCodes) { + bytes32 orderHash = makerOrder.hash(); + + validationCodes[0] = _checkValidityCurrencyAndStrategy( + makerOrder.quoteType, + makerOrder.currency, + makerOrder.strategyId + ); + + // It will exit here if the strategy does not exist. + // However, if the strategy is implemented but invalid (except if wrong quote type), + // it can continue the validation process. + if (validationCodes[0] == STRATEGY_NOT_IMPLEMENTED || validationCodes[0] == STRATEGY_INVALID_QUOTE_TYPE) { + return validationCodes; + } + + uint256 validationCode1; + uint256[] memory itemIds; + uint256[] memory amounts; + uint256 price; + + if (makerOrder.quoteType == QuoteType.Ask) { + (validationCode1, itemIds, amounts, price) = _checkValidityMakerAskItemIdsAndAmountsAndPrice(makerOrder); + } else { + (validationCode1, itemIds, , price) = _checkValidityMakerBidItemIdsAndAmountsAndPrice(makerOrder); + } + + validationCodes[1] = validationCode1; + + validationCodes[2] = _checkValidityNonces( + makerOrder.quoteType, + makerOrder.signer, + makerOrder.globalNonce, + makerOrder.orderNonce, + makerOrder.subsetNonce, + orderHash + ); + + validationCodes[3] = _checkValidityMerkleProofAndOrderHash(merkleTree, orderHash, signature, makerOrder.signer); + validationCodes[4] = _checkValidityTimestamps(makerOrder.startTime, makerOrder.endTime); + + validationCodes[3] = _checkValidityMerkleProofAndOrderHash(merkleTree, orderHash, signature, makerOrder.signer); + validationCodes[4] = _checkValidityTimestamps(makerOrder.startTime, makerOrder.endTime); + + if (makerOrder.quoteType == QuoteType.Bid) { + validationCodes[5] = _checkValidityMakerBidERC20Assets(makerOrder.currency, makerOrder.signer, price); + } else { + validationCodes[5] = _checkValidityMakerAskNFTAssets( + makerOrder.collection, + makerOrder.collectionType, + makerOrder.signer, + itemIds, + amounts + ); + } + + validationCodes[6] = _checkIfPotentialInvalidCollectionTypes(makerOrder.collection, makerOrder.collectionType); + + if (makerOrder.quoteType == QuoteType.Bid) { + validationCodes[7] = ORDER_EXPECTED_TO_BE_VALID; + } else { + validationCodes[7] = _checkValidityTransferManagerApprovals(makerOrder.signer); + } + + validationCodes[8] = _checkValidityCreatorFee(makerOrder.collection, price, itemIds); + } + + /** + * @notice This function is private and is used to adjust the protocol parameters. + */ + function _deriveProtocolParameters() private { + domainSeparator = looksRareProtocol.domainSeparator(); + creatorFeeManager = looksRareProtocol.creatorFeeManager(); + maxCreatorFeeBp = looksRareProtocol.maxCreatorFeeBp(); + } + + /** + * @notice This function is private and verifies the validity of nonces for maker order. + * @param makerSigner Address of the maker signer + * @param globalNonce Global nonce + * @param orderNonce Order nonce + * @param subsetNonce Subset nonce + * @param orderHash Order hash + * @return validationCode Validation code + */ + function _checkValidityNonces( + QuoteType quoteType, + address makerSigner, + uint256 globalNonce, + uint256 orderNonce, + uint256 subsetNonce, + bytes32 orderHash + ) private view returns (uint256 validationCode) { + // 1. Check subset nonce + if (looksRareProtocol.userSubsetNonce(makerSigner, subsetNonce)) { + return USER_SUBSET_NONCE_CANCELLED; + } + + // 2. Check order nonce + bytes32 orderNonceStatus = looksRareProtocol.userOrderNonce(makerSigner, orderNonce); + + if (orderNonceStatus == MAGIC_VALUE_ORDER_NONCE_EXECUTED) { + return USER_ORDER_NONCE_EXECUTED_OR_CANCELLED; + } + + if (orderNonceStatus != bytes32(0) && orderNonceStatus != orderHash) { + return USER_ORDER_NONCE_IN_EXECUTION_WITH_OTHER_HASH; + } + + // 3. Check global nonces + (uint256 globalBidNonce, uint256 globalAskNonce) = looksRareProtocol.userBidAskNonces(makerSigner); + + if (quoteType == QuoteType.Bid && globalNonce != globalBidNonce) { + return INVALID_USER_GLOBAL_BID_NONCE; + } + if (quoteType == QuoteType.Ask && globalNonce != globalAskNonce) { + return INVALID_USER_GLOBAL_ASK_NONCE; + } + } + + /** + * @notice This function is private and verifies the validity of the currency and strategy. + * @param quoteType Quote type + * @param currency Address of the currency + * @param strategyId Strategy id + * @return validationCode Validation code + */ + function _checkValidityCurrencyAndStrategy( + QuoteType quoteType, + address currency, + uint256 strategyId + ) private view returns (uint256 validationCode) { + // 1. Verify whether the currency is allowed + if (!looksRareProtocol.isCurrencyAllowed(currency)) { + return CURRENCY_NOT_ALLOWED; + } + + if (currency == address(0) && quoteType == QuoteType.Bid) { + return CURRENCY_NOT_ALLOWED; + } + + // 2. Verify whether the strategy is valid + (bool strategyIsActive, , , , , bool strategyIsMakerBid, address strategyImplementation) = looksRareProtocol + .strategyInfo(strategyId); + + if (strategyId != 0 && strategyImplementation == address(0)) { + return STRATEGY_NOT_IMPLEMENTED; + } + + if (strategyId != 0) { + if ( + (strategyIsMakerBid && quoteType != QuoteType.Bid) || + (!strategyIsMakerBid && quoteType != QuoteType.Ask) + ) { + return STRATEGY_INVALID_QUOTE_TYPE; + } + } + + if (!strategyIsActive) { + return STRATEGY_NOT_ACTIVE; + } + } + + /** + * @notice This function verifies the validity for order timestamps. + * @param startTime Start time + * @param endTime End time + * @return validationCode Validation code + */ + function _checkValidityTimestamps( + uint256 startTime, + uint256 endTime + ) private view returns (uint256 validationCode) { + // @dev It is possible for startTime to be equal to endTime. + // If so, the execution only succeeds when the startTime = endTime = block.timestamp. + // For order invalidation, if the call succeeds, it is already too late for later execution since the + // next block will have a greater timestamp than the current one. + if (startTime >= endTime) { + return START_TIME_GREATER_THAN_END_TIME; + } + + if (endTime <= block.timestamp) { + return TOO_LATE_TO_EXECUTE_ORDER; + } + if (startTime >= block.timestamp + 5 minutes) { + return TOO_EARLY_TO_EXECUTE_ORDER; + } + } + + /** + * @notice This function is private and checks if the collection type may be potentially invalid. + * @param collection Address of the collection + * @param collectionType Collection type in the maker order + * @return validationCode Validation code + * @dev This function may return false positives. + * (i.e. collections that are tradable but do not implement the proper interfaceId). + * If ERC165 is not implemented, it will revert. + */ + function _checkIfPotentialInvalidCollectionTypes( + address collection, + CollectionType collectionType + ) private view returns (uint256 validationCode) { + if (collectionType == CollectionType.ERC721) { + bool isERC721 = IERC165(collection).supportsInterface(ERC721_INTERFACE_ID_1) || + IERC165(collection).supportsInterface(ERC721_INTERFACE_ID_2); + + if (!isERC721) { + return POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC721; + } + } else if (collectionType == CollectionType.ERC1155) { + if (!IERC165(collection).supportsInterface(ERC1155_INTERFACE_ID)) { + return POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC1155; + } + } + } + + /** + * @notice This function verifies that (1) ERC20 approvals + * and (2) balances are sufficient to process the maker bid order. + * @param currency Currency address + * @param user User address + * @param price Price (defined by the maker order) + * @return validationCode Validation code + */ + function _checkValidityMakerBidERC20Assets( + address currency, + address user, + uint256 price + ) private view returns (uint256 validationCode) { + if (currency != address(0)) { + if (IERC20(currency).balanceOf(user) < price) { + return ERC20_BALANCE_INFERIOR_TO_PRICE; + } + + if (IERC20(currency).allowance(user, address(looksRareProtocol)) < price) { + return ERC20_APPROVAL_INFERIOR_TO_PRICE; + } + } + } + + /** + * @notice This function verifies the validity of NFT assets (approvals, balances, and others). + * @param collection Collection address + * @param collectionType Collection type + * @param user User address + * @param itemIds Array of item ids + * @param amounts Array of amounts + * @return validationCode Validation code + */ + function _checkValidityMakerAskNFTAssets( + address collection, + CollectionType collectionType, + address user, + uint256[] memory itemIds, + uint256[] memory amounts + ) private view returns (uint256 validationCode) { + validationCode = _checkIfItemIdsDiffer(itemIds); + + if (validationCode != ORDER_EXPECTED_TO_BE_VALID) { + return validationCode; + } + + if (collectionType == CollectionType.ERC721) { + validationCode = _checkValidityERC721AndEquivalents(collection, user, itemIds); + } else if (collectionType == CollectionType.ERC1155) { + validationCode = _checkValidityERC1155(collection, user, itemIds, amounts); + } + } + + /** + * @notice This function verifies the validity of (1) ERC721 approvals + * and (2) balances to process the maker ask order. + * @param collection Collection address + * @param user User address + * @param itemIds Array of item ids + * @return validationCode Validation code + */ + function _checkValidityERC721AndEquivalents( + address collection, + address user, + uint256[] memory itemIds + ) private view returns (uint256 validationCode) { + // 1. Verify itemId is owned by user and catch revertion if ERC721 ownerOf fails + uint256 length = itemIds.length; + + bool success; + bytes memory data; + + for (uint256 i; i < length; ) { + (success, data) = collection.staticcall(abi.encodeCall(IERC721.ownerOf, (itemIds[i]))); + + if (!success) { + return ERC721_ITEM_ID_DOES_NOT_EXIST; + } + + if (abi.decode(data, (address)) != user) { + return ERC721_ITEM_ID_NOT_IN_BALANCE; + } + + unchecked { + ++i; + } + } + + // 2. Verify if collection is approved by transfer manager + (success, data) = collection.staticcall( + abi.encodeCall(IERC721.isApprovedForAll, (user, address(transferManager))) + ); + + bool isApprovedAll; + if (success) { + isApprovedAll = abi.decode(data, (bool)); + } + + if (!isApprovedAll) { + for (uint256 i; i < length; ) { + // 3. If collection is not approved by transfer manager, try to see if it is approved individually + (success, data) = collection.staticcall(abi.encodeCall(IERC721.getApproved, (itemIds[i]))); + + address approvedAddress; + + if (success) { + approvedAddress = abi.decode(data, (address)); + } + + if (approvedAddress != address(transferManager)) { + return ERC721_NO_APPROVAL_FOR_ALL_OR_ITEM_ID; + } + + unchecked { + ++i; + } + } + } + } + + /** + * @notice This function verifies the validity of (1) ERC1155 approvals + * (2) and balances to process the maker ask order. + * @param collection Collection address + * @param user User address + * @param itemIds Array of item ids + * @param amounts Array of amounts + * @return validationCode Validation code + */ + function _checkValidityERC1155( + address collection, + address user, + uint256[] memory itemIds, + uint256[] memory amounts + ) private view returns (uint256 validationCode) { + // 1. Verify each itemId is owned by user and catch revertion if ERC1155 ownerOf fails + address[] memory users = new address[](1); + users[0] = user; + + uint256 length = itemIds.length; + + // 1.1 Use balanceOfBatch + (bool success, bytes memory data) = collection.staticcall( + abi.encodeCall(IERC1155.balanceOfBatch, (users, itemIds)) + ); + + if (success) { + uint256[] memory balances = abi.decode(data, (uint256[])); + for (uint256 i; i < length; ) { + if (balances[i] < amounts[i]) { + return ERC1155_BALANCE_OF_ITEM_ID_INFERIOR_TO_AMOUNT; + } + unchecked { + ++i; + } + } + } else { + // 1.2 If the balanceOfBatch does not work, use loop with balanceOf function + for (uint256 i; i < length; ) { + (success, data) = collection.staticcall(abi.encodeCall(IERC1155.balanceOf, (user, itemIds[i]))); + + if (!success) { + return ERC1155_BALANCE_OF_DOES_NOT_EXIST; + } + + if (abi.decode(data, (uint256)) < amounts[i]) { + return ERC1155_BALANCE_OF_ITEM_ID_INFERIOR_TO_AMOUNT; + } + + unchecked { + ++i; + } + } + } + + // 2. Verify if collection is approved by transfer manager + (success, data) = collection.staticcall( + abi.encodeCall(IERC1155.isApprovedForAll, (user, address(transferManager))) + ); + + if (!success) { + return ERC1155_IS_APPROVED_FOR_ALL_DOES_NOT_EXIST; + } + + if (!abi.decode(data, (bool))) { + return ERC1155_NO_APPROVAL_FOR_ALL; + } + } + + /** + * @notice This function verifies the validity of a Merkle proof and the order hash. + * @param merkleTree Merkle tree struct + * @param orderHash Order hash + * @param signature Signature + * @param signer Signer address + * @return validationCode Validation code + */ + function _checkValidityMerkleProofAndOrderHash( + OrderStructs.MerkleTree calldata merkleTree, + bytes32 orderHash, + bytes calldata signature, + address signer + ) private view returns (uint256 validationCode) { + if (merkleTree.proof.length != 0) { + if (merkleTree.proof.length > MAX_CALLDATA_PROOF_LENGTH) { + return MERKLE_PROOF_PROOF_TOO_LARGE; + } + + if (!MerkleProofCalldataWithNodes.verifyCalldata(merkleTree.proof, merkleTree.root, orderHash)) { + return ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE; + } + + bytes32 batchOrderHash = looksRareProtocol.hashBatchOrder(merkleTree.root, merkleTree.proof.length); + + return _computeDigestAndVerify(batchOrderHash, signature, signer); + } else { + return _computeDigestAndVerify(orderHash, signature, signer); + } + } + + /** + * @notice Check the validity of creator fee + * @param collection Collection address + * @param itemIds Item ids + * @return validationCode Validation code + */ + function _checkValidityCreatorFee( + address collection, + uint256 price, + uint256[] memory itemIds + ) private view returns (uint256 validationCode) { + if (address(creatorFeeManager) != address(0)) { + (bool status, bytes memory data) = address(creatorFeeManager).staticcall( + abi.encodeCall(ICreatorFeeManager.viewCreatorFeeInfo, (collection, price, itemIds)) + ); + + // The only path possible (to revert) in the fee manager is the bundle being not supported. + if (!status) { + return BUNDLE_ERC2981_NOT_SUPPORTED; + } + + (address creator, uint256 creatorFeeAmount) = abi.decode(data, (address, uint256)); + + if (creator != address(0)) { + if (creatorFeeAmount * ONE_HUNDRED_PERCENT_IN_BP > (price * uint256(maxCreatorFeeBp))) { + return CREATOR_FEE_TOO_HIGH; + } + } + } + } + + /** + * @notice This function computes the digest and verify the signature. + * @param computedHash Hash of order or merkle root + * @param makerSignature Signature of the maker + * @param signer Signer address + * @return validationCode Validation code + */ + function _computeDigestAndVerify( + bytes32 computedHash, + bytes calldata makerSignature, + address signer + ) private view returns (uint256 validationCode) { + return + _validateSignature( + keccak256(abi.encodePacked("\x19\x01", domainSeparator, computedHash)), + makerSignature, + signer + ); + } + + /** + * @notice This function checks the validity of the signature. + * @param hash Message hash + * @param signature A 64 or 65 bytes signature + * @param signer Signer address + * @return validationCode Validation code + */ + function _validateSignature( + bytes32 hash, + bytes calldata signature, + address signer + ) private view returns (uint256 validationCode) { + // Logic if EOA + if (signer.code.length == 0) { + bytes32 r; + bytes32 s; + uint8 v; + + if (signature.length == 64) { + bytes32 vs; + assembly { + r := calldataload(signature.offset) + vs := calldataload(add(signature.offset, 0x20)) + s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + v := add(shr(255, vs), 27) + } + } else if (signature.length == 65) { + assembly { + r := calldataload(signature.offset) + s := calldataload(add(signature.offset, 0x20)) + v := byte(0, calldataload(add(signature.offset, 0x40))) + } + } else { + return INVALID_SIGNATURE_LENGTH; + } + + if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { + return INVALID_S_PARAMETER_EOA; + } + + if (v != 27 && v != 28) { + return INVALID_V_PARAMETER_EOA; + } + + address recoveredSigner = ecrecover(hash, v, r, s); + + if (recoveredSigner == address(0)) { + return NULL_SIGNER_EOA; + } + + if (signer != recoveredSigner) { + return INVALID_SIGNER_EOA; + } + } else { + // Logic if ERC1271 + (bool success, bytes memory data) = signer.staticcall( + abi.encodeCall(IERC1271.isValidSignature, (hash, signature)) + ); + + if (!success) { + return MISSING_IS_VALID_SIGNATURE_FUNCTION_EIP1271; + } + + if (abi.decode(data, (bytes4)) != IERC1271.isValidSignature.selector) { + return SIGNATURE_INVALID_EIP1271; + } + } + } + + /** + * @dev This function checks if transfer manager approvals are not revoked by user, nor by the owner + * @param user Address of the user + * @return validationCode Validation code + */ + function _checkValidityTransferManagerApprovals(address user) private view returns (uint256 validationCode) { + if (!transferManager.hasUserApprovedOperator(user, address(looksRareProtocol))) { + return NO_TRANSFER_MANAGER_APPROVAL_BY_USER_FOR_EXCHANGE; + } + + if (!transferManager.isOperatorAllowed(address(looksRareProtocol))) { + return TRANSFER_MANAGER_APPROVAL_REVOKED_BY_OWNER_FOR_EXCHANGE; + } + } + + function _checkValidityMakerAskItemIdsAndAmountsAndPrice( + OrderStructs.Maker memory makerAsk + ) private view returns (uint256 validationCode, uint256[] memory itemIds, uint256[] memory amounts, uint256 price) { + if (makerAsk.strategyId == 0) { + itemIds = makerAsk.itemIds; + amounts = makerAsk.amounts; + price = makerAsk.price; + + validationCode = _getOrderValidationCodeForStandardStrategy( + makerAsk.collectionType, + itemIds.length, + amounts + ); + } else { + itemIds = makerAsk.itemIds; + amounts = makerAsk.amounts; + // @dev It should ideally be adjusted by real price + price = makerAsk.price; + + (, , , , bytes4 strategySelector, , address strategyImplementation) = looksRareProtocol.strategyInfo( + makerAsk.strategyId + ); + + (bool isValid, bytes4 errorSelector) = IStrategy(strategyImplementation).isMakerOrderValid( + makerAsk, + strategySelector + ); + + validationCode = _getOrderValidationCodeForNonStandardStrategies(isValid, errorSelector); + } + } + + function _checkValidityMakerBidItemIdsAndAmountsAndPrice( + OrderStructs.Maker memory makerBid + ) private view returns (uint256 validationCode, uint256[] memory itemIds, uint256[] memory amounts, uint256 price) { + if (makerBid.strategyId == 0) { + itemIds = makerBid.itemIds; + amounts = makerBid.amounts; + price = makerBid.price; + + validationCode = _getOrderValidationCodeForStandardStrategy( + makerBid.collectionType, + itemIds.length, + amounts + ); + } else { + // @dev It should ideally be adjusted by real price + // amounts and itemIds are not used since most non-native maker bids won't target a single item + price = makerBid.price; + + (, , , , bytes4 strategySelector, , address strategyImplementation) = looksRareProtocol.strategyInfo( + makerBid.strategyId + ); + + (bool isValid, bytes4 errorSelector) = IStrategy(strategyImplementation).isMakerOrderValid( + makerBid, + strategySelector + ); + + validationCode = _getOrderValidationCodeForNonStandardStrategies(isValid, errorSelector); + } + } + + /** + * @notice This function checks if the same itemId is repeated + * in an array of item ids. + * @param itemIds Array of item ids + * @dev This is for bundles. + * For example, if itemIds = [1,2,1], it will return SAME_ITEM_ID_IN_BUNDLE. + * @return validationCode Validation code + */ + function _checkIfItemIdsDiffer(uint256[] memory itemIds) private pure returns (uint256 validationCode) { + uint256 length = itemIds.length; + + // Only check if length of array is greater than 1 + if (length > 1) { + for (uint256 i = 0; i < length - 1; ) { + for (uint256 j = i + 1; j < length; ) { + if (itemIds[i] == itemIds[j]) { + return SAME_ITEM_ID_IN_BUNDLE; + } + + unchecked { + ++j; + } + } + + unchecked { + ++i; + } + } + } + } + + function _getOrderValidationCodeForStandardStrategy( + CollectionType collectionType, + uint256 expectedLength, + uint256[] memory amounts + ) private pure returns (uint256 validationCode) { + if (expectedLength == 0 || (amounts.length != expectedLength)) { + validationCode = MAKER_ORDER_INVALID_STANDARD_SALE; + } else { + for (uint256 i; i < expectedLength; ) { + uint256 amount = amounts[i]; + + if (amount == 0) { + validationCode = MAKER_ORDER_INVALID_STANDARD_SALE; + } + + if (collectionType == CollectionType.ERC721 && amount != 1) { + validationCode = MAKER_ORDER_INVALID_STANDARD_SALE; + } + + unchecked { + ++i; + } + } + } + } + + function _getOrderValidationCodeForNonStandardStrategies( + bool isValid, + bytes4 errorSelector + ) private pure returns (uint256 validationCode) { + if (isValid) { + validationCode = ORDER_EXPECTED_TO_BE_VALID; + } else { + if (errorSelector == OrderInvalid.selector) { + validationCode = MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE; + } else { + validationCode = MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE; + } + } + } +} diff --git a/contracts/src/marketplace/helpers/ProtocolHelpers.sol b/contracts/src/marketplace/helpers/ProtocolHelpers.sol new file mode 100644 index 00000000..01162985 --- /dev/null +++ b/contracts/src/marketplace/helpers/ProtocolHelpers.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { SignatureCheckerCalldata } from "@looksrare/contracts-libs/contracts/SignatureCheckerCalldata.sol"; + +// Libraries +import { OrderStructs } from "../libraries/OrderStructs.sol"; + +// Other dependencies +import { LooksRareProtocol } from "../LooksRareProtocol.sol"; + +/** + * @title ProtocolHelpers + * @notice This contract contains helper view functions for order creation. + * @author LooksRare protocol team (👀,💎) + */ +contract ProtocolHelpers { + using OrderStructs for OrderStructs.Maker; + + // Encoding prefix for EIP-712 signatures + string internal constant _ENCODING_PREFIX = "\x19\x01"; + + // LooksRareProtocol + LooksRareProtocol public looksRareProtocol; + + /** + * @notice Constructor + * @param _looksRareProtocol LooksRare protocol address + */ + constructor(address _looksRareProtocol) { + looksRareProtocol = LooksRareProtocol(_looksRareProtocol); + } + + /** + * @notice Compute digest for maker bid struct + * @param maker Maker struct + * @return digest Digest + */ + function computeMakerDigest(OrderStructs.Maker memory maker) public view returns (bytes32 digest) { + bytes32 domainSeparator = looksRareProtocol.domainSeparator(); + return keccak256(abi.encodePacked(_ENCODING_PREFIX, domainSeparator, maker.hash())); + } + + /** + * @notice Compute digest for merkle tree struct + * @param merkleTree Merkle tree struct + * @return digest Digest + */ + function computeDigestMerkleTree(OrderStructs.MerkleTree memory merkleTree) public view returns (bytes32 digest) { + bytes32 domainSeparator = looksRareProtocol.domainSeparator(); + bytes32 batchOrderHash = looksRareProtocol.hashBatchOrder(merkleTree.root, merkleTree.proof.length); + return keccak256(abi.encodePacked(_ENCODING_PREFIX, domainSeparator, batchOrderHash)); + } + + /** + * @notice Verify maker order signature + * @param maker Maker struct + * @param makerSignature Maker signature + * @param signer Signer address + * @dev It returns true only if the SignatureCheckerCalldata does not revert before. + */ + function verifyMakerSignature( + OrderStructs.Maker memory maker, + bytes calldata makerSignature, + address signer + ) public view returns (bool) { + bytes32 digest = computeMakerDigest(maker); + SignatureCheckerCalldata.verify(digest, signer, makerSignature); + return true; + } + + /** + * @notice Verify merkle tree signature + * @param merkleTree Merkle tree struct + * @param makerSignature Maker signature + * @param signer Signer address + * @dev It returns true only if the SignatureCheckerCalldata does not revert before. + */ + function verifyMerkleTree( + OrderStructs.MerkleTree memory merkleTree, + bytes calldata makerSignature, + address signer + ) public view returns (bool) { + bytes32 digest = computeDigestMerkleTree(merkleTree); + SignatureCheckerCalldata.verify(digest, signer, makerSignature); + return true; + } +} diff --git a/contracts/src/marketplace/interfaces/ICreatorFeeManager.sol b/contracts/src/marketplace/interfaces/ICreatorFeeManager.sol new file mode 100644 index 00000000..d469ff27 --- /dev/null +++ b/contracts/src/marketplace/interfaces/ICreatorFeeManager.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Interfaces +import { IRoyaltyFeeRegistry } from "./IRoyaltyFeeRegistry.sol"; + +/** + * @title ICreatorFeeManager + * @author LooksRare protocol team (👀,💎) + */ +interface ICreatorFeeManager { + /** + * @notice It is returned if the bundle contains multiple itemIds with different creator fee structure. + */ + error BundleEIP2981NotAllowed(address collection); + + /** + * @notice It returns the royalty fee registry address/interface. + * @return royaltyFeeRegistry Interface of the royalty fee registry + */ + function royaltyFeeRegistry() external view returns (IRoyaltyFeeRegistry royaltyFeeRegistry); + + /** + * @notice This function returns the creator address and calculates the creator fee amount. + * @param collection Collection address + * @param price Transaction price + * @param itemIds Array of item ids + * @return creator Creator address + * @return creatorFeeAmount Creator fee amount + */ + function viewCreatorFeeInfo( + address collection, + uint256 price, + uint256[] memory itemIds + ) external view returns (address creator, uint256 creatorFeeAmount); +} diff --git a/contracts/src/marketplace/interfaces/ICurrencyManager.sol b/contracts/src/marketplace/interfaces/ICurrencyManager.sol new file mode 100644 index 00000000..72d50d2e --- /dev/null +++ b/contracts/src/marketplace/interfaces/ICurrencyManager.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @title ICurrencyManager + * @author LooksRare protocol team (👀,💎) + */ +interface ICurrencyManager { + /** + * @notice It is emitted if the currency status in the allowlist is updated. + * @param currency Currency address (address(0) = ETH) + * @param isAllowed Whether the currency is allowed + */ + event CurrencyStatusUpdated(address currency, bool isAllowed); +} diff --git a/contracts/src/marketplace/interfaces/IExecutionManager.sol b/contracts/src/marketplace/interfaces/IExecutionManager.sol new file mode 100644 index 00000000..945637b5 --- /dev/null +++ b/contracts/src/marketplace/interfaces/IExecutionManager.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @title IExecutionManager + * @author LooksRare protocol team (👀,💎) + */ +interface IExecutionManager { + /** + * @notice It is issued when there is a new creator fee manager. + * @param creatorFeeManager Address of the new creator fee manager + */ + event NewCreatorFeeManager(address creatorFeeManager); + + /** + * @notice It is issued when there is a new maximum creator fee (in basis point). + * @param maxCreatorFeeBp New maximum creator fee (in basis point) + */ + event NewMaxCreatorFeeBp(uint256 maxCreatorFeeBp); + + /** + * @notice It is issued when there is a new protocol fee recipient address. + * @param protocolFeeRecipient Address of the new protocol fee recipient + */ + event NewProtocolFeeRecipient(address protocolFeeRecipient); + + /** + * @notice It is returned if the creator fee (in basis point) is too high. + */ + error CreatorFeeBpTooHigh(); + + /** + * @notice It is returned if the new protocol fee recipient is set to address(0). + */ + error NewProtocolFeeRecipientCannotBeNullAddress(); + + /** + * @notice It is returned if there is no selector for maker ask/bid for a given strategyId, + * depending on the quote type. + */ + error NoSelectorForStrategy(); + + /** + * @notice It is returned if the current block timestamp is not between start and end times in the maker order. + */ + error OutsideOfTimeRange(); + + /** + * @notice It is returned if the strategy id has no implementation. + * @dev It is returned if there is no implementation address and the strategyId is strictly greater than 0. + */ + error StrategyNotAvailable(uint256 strategyId); +} diff --git a/contracts/src/marketplace/interfaces/IImmutableCreate2Factory.sol b/contracts/src/marketplace/interfaces/IImmutableCreate2Factory.sol new file mode 100644 index 00000000..9071ab43 --- /dev/null +++ b/contracts/src/marketplace/interfaces/IImmutableCreate2Factory.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +interface IImmutableCreate2Factory { + function safeCreate2( + bytes32 salt, + bytes calldata initializationCode + ) external payable returns (address deploymentAddress); +} diff --git a/contracts/src/marketplace/interfaces/ILooksRareProtocol.sol b/contracts/src/marketplace/interfaces/ILooksRareProtocol.sol new file mode 100644 index 00000000..09722537 --- /dev/null +++ b/contracts/src/marketplace/interfaces/ILooksRareProtocol.sol @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "../libraries/OrderStructs.sol"; + +/** + * @title ILooksRareProtocol + * @author LooksRare protocol team (👀,💎) + */ +interface ILooksRareProtocol { + /** + * @notice This struct contains an order nonce's invalidation status + * and the order hash that triggered the status change. + * @param orderHash Maker order hash + * @param orderNonce Order nonce + * @param isNonceInvalidated Whether this transaction invalidated the maker user's order nonce at the protocol level + */ + struct NonceInvalidationParameters { + bytes32 orderHash; + uint256 orderNonce; + bool isNonceInvalidated; + } + + /** + * @notice It is emitted when there is an affiliate fee paid. + * @param affiliate Affiliate address + * @param currency Address of the currency + * @param affiliateFee Affiliate fee (in the currency) + */ + event AffiliatePayment(address affiliate, address currency, uint256 affiliateFee); + + /** + * @notice It is emitted if there is a change in the domain separator. + */ + event NewDomainSeparator(); + + /** + * @notice It is emitted when there is a new gas limit for a ETH transfer (before it is wrapped to WETH). + * @param gasLimitETHTransfer Gas limit for an ETH transfer + */ + event NewGasLimitETHTransfer(uint256 gasLimitETHTransfer); + + /** + * @notice It is emitted when a taker ask transaction is completed. + * @param nonceInvalidationParameters Struct about nonce invalidation parameters + * @param askUser Address of the ask user + * @param bidUser Address of the bid user + * @param strategyId Id of the strategy + * @param currency Address of the currency + * @param collection Address of the collection + * @param itemIds Array of item ids + * @param amounts Array of amounts (for item ids) + * @param feeRecipients Array of fee recipients + * feeRecipients[0] User who receives the proceeds of the sale (it can be the taker ask user or different) + * feeRecipients[1] Creator fee recipient (if none, address(0)) + * @param feeAmounts Array of fee amounts + * feeAmounts[0] Fee amount for the user receiving sale proceeds + * feeAmounts[1] Creator fee amount + * feeAmounts[2] Protocol fee amount prior to adjustment for a potential affiliate payment + */ + // maker (receives the NFT) + event TakerAsk( + // taker (initiates the transaction) + NonceInvalidationParameters nonceInvalidationParameters, + address askUser, + address bidUser, + uint256 strategyId, + address currency, + address collection, + uint256[] itemIds, + uint256[] amounts, + address[2] feeRecipients, + uint256[3] feeAmounts + ); + + /** + * @notice It is emitted when a taker bid transaction is completed. + * @param nonceInvalidationParameters Struct about nonce invalidation parameters + * @param bidUser Address of the bid user + * @param bidRecipient Address of the recipient of the bid + * @param strategyId Id of the strategy + * @param currency Address of the currency + * @param collection Address of the collection + * @param itemIds Array of item ids + * @param amounts Array of amounts (for item ids) + * @param feeRecipients Array of fee recipients + * feeRecipients[0] User who receives the proceeds of the sale (it is the maker ask user) + * feeRecipients[1] Creator fee recipient (if none, address(0)) + * @param feeAmounts Array of fee amounts + * feeAmounts[0] Fee amount for the user receiving sale proceeds + * feeAmounts[1] Creator fee amount + * feeAmounts[2] Protocol fee amount prior to adjustment for a potential affiliate payment + */ + // taker (receives the NFT) + event TakerBid( + // taker (initiates the transaction) + NonceInvalidationParameters nonceInvalidationParameters, + address bidUser, + address bidRecipient, + uint256 strategyId, + address currency, + address collection, + uint256[] itemIds, + uint256[] amounts, + address[2] feeRecipients, + uint256[3] feeAmounts + ); + + /** + * @notice It is returned if the gas limit for a standard ETH transfer is too low. + */ + error NewGasLimitETHTransferTooLow(); + + /** + * @notice It is returned if the domain separator cannot be updated (i.e. the chainId is the same). + */ + error SameDomainSeparator(); + + /** + * @notice It is returned if the domain separator should change. + */ + error ChainIdInvalid(); + + /** + * @notice It is returned if the nonces are invalid. + */ + error NoncesInvalid(); + + /** + * @notice This function allows a user to execute a taker ask (against a maker bid). + * @param takerAsk Taker ask struct + * @param makerBid Maker bid struct + * @param makerSignature Maker signature + * @param merkleTree Merkle tree struct (if the signature contains multiple maker orders) + * @param affiliate Affiliate address + */ + function executeTakerAsk( + OrderStructs.Taker calldata takerAsk, + OrderStructs.Maker calldata makerBid, + bytes calldata makerSignature, + OrderStructs.MerkleTree calldata merkleTree, + address affiliate + ) external; + + /** + * @notice This function allows a user to execute a taker bid (against a maker ask). + * @param takerBid Taker bid struct + * @param makerAsk Maker ask struct + * @param makerSignature Maker signature + * @param merkleTree Merkle tree struct (if the signature contains multiple maker orders) + * @param affiliate Affiliate address + */ + function executeTakerBid( + OrderStructs.Taker calldata takerBid, + OrderStructs.Maker calldata makerAsk, + bytes calldata makerSignature, + OrderStructs.MerkleTree calldata merkleTree, + address affiliate + ) external payable; + + /** + * @notice This function allows a user to batch buy with an array of taker bids (against an array of maker asks). + * @param takerBids Array of taker bid structs + * @param makerAsks Array of maker ask structs + * @param makerSignatures Array of maker signatures + * @param merkleTrees Array of merkle tree structs if the signature contains multiple maker orders + * @param affiliate Affiliate address + * @param isAtomic Whether the execution should be atomic + * i.e. whether it should revert if 1 or more transactions fail + */ + function executeMultipleTakerBids( + OrderStructs.Taker[] calldata takerBids, + OrderStructs.Maker[] calldata makerAsks, + bytes[] calldata makerSignatures, + OrderStructs.MerkleTree[] calldata merkleTrees, + address affiliate, + bool isAtomic + ) external payable; +} diff --git a/contracts/src/marketplace/interfaces/INonceManager.sol b/contracts/src/marketplace/interfaces/INonceManager.sol new file mode 100644 index 00000000..6011291d --- /dev/null +++ b/contracts/src/marketplace/interfaces/INonceManager.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @title INonceManager + * @author LooksRare protocol team (👀,💎) + */ +interface INonceManager { + /** + * @notice This struct contains the global bid and ask nonces of a user. + * @param bidNonce Bid nonce + * @param askNonce Ask nonce + */ + struct UserBidAskNonces { + uint256 bidNonce; + uint256 askNonce; + } + + /** + * @notice It is emitted when there is an update of the global bid/ask nonces for a user. + * @param user Address of the user + * @param bidNonce New bid nonce + * @param askNonce New ask nonce + */ + event NewBidAskNonces(address user, uint256 bidNonce, uint256 askNonce); + + /** + * @notice It is emitted when order nonces are cancelled for a user. + * @param user Address of the user + * @param orderNonces Array of order nonces cancelled + */ + event OrderNoncesCancelled(address user, uint256[] orderNonces); + + /** + * @notice It is emitted when subset nonces are cancelled for a user. + * @param user Address of the user + * @param subsetNonces Array of subset nonces cancelled + */ + event SubsetNoncesCancelled(address user, uint256[] subsetNonces); +} diff --git a/contracts/src/marketplace/interfaces/IRoyaltyFeeRegistry.sol b/contracts/src/marketplace/interfaces/IRoyaltyFeeRegistry.sol new file mode 100644 index 00000000..a76c84cb --- /dev/null +++ b/contracts/src/marketplace/interfaces/IRoyaltyFeeRegistry.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @title IRoyaltyFeeRegistry + * @author LooksRare protocol team (👀,💎) + */ +interface IRoyaltyFeeRegistry { + /** + * @notice This function returns the royalty information for a collection at a given transaction price. + * @param collection Collection address + * @param price Transaction price + * @return receiver Receiver address + * @return royaltyFee Royalty fee amount + */ + function royaltyInfo( + address collection, + uint256 price + ) external view returns (address receiver, uint256 royaltyFee); +} diff --git a/contracts/src/marketplace/interfaces/IStrategy.sol b/contracts/src/marketplace/interfaces/IStrategy.sol new file mode 100644 index 00000000..39585c5f --- /dev/null +++ b/contracts/src/marketplace/interfaces/IStrategy.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "../libraries/OrderStructs.sol"; + +/** + * @title IStrategy + * @author LooksRare protocol team (👀,💎) + */ +interface IStrategy { + /** + * @notice Validate *only the maker* order under the context of the chosen strategy. It does not revert if + * the maker order is invalid. Instead it returns false and the error's 4 bytes selector. + * @param makerOrder Maker struct (maker specific parameters for the execution) + * @param functionSelector Function selector for the strategy + * @return isValid Whether the maker struct is valid + * @return errorSelector If isValid is false, it returns the error's 4 bytes selector + */ + function isMakerOrderValid( + OrderStructs.Maker calldata makerOrder, + bytes4 functionSelector + ) external view returns (bool isValid, bytes4 errorSelector); + + /** + * @notice This function acts as a safety check for the protocol's owner when adding new execution strategies. + * @return isStrategy Whether it is a LooksRare V2 protocol strategy + */ + function isLooksRareV2Strategy() external pure returns (bool isStrategy); +} diff --git a/contracts/src/marketplace/interfaces/IStrategyManager.sol b/contracts/src/marketplace/interfaces/IStrategyManager.sol new file mode 100644 index 00000000..283431a2 --- /dev/null +++ b/contracts/src/marketplace/interfaces/IStrategyManager.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @title IStrategyManager + * @author LooksRare protocol team (👀,💎) + */ +interface IStrategyManager { + /** + * @notice This struct contains the parameter of an execution strategy. + * @param strategyId Id of the new strategy + * @param standardProtocolFeeBp Standard protocol fee (in basis point) + * @param minTotalFeeBp Minimum total fee (in basis point) + * @param maxProtocolFeeBp Maximum protocol fee (in basis point) + * @param selector Function selector for the transaction to be executed + * @param isMakerBid Whether the strategyId is for maker bid + * @param implementation Address of the implementation of the strategy + */ + struct Strategy { + bool isActive; + uint16 standardProtocolFeeBp; + uint16 minTotalFeeBp; + uint16 maxProtocolFeeBp; + bytes4 selector; + bool isMakerBid; + address implementation; + } + + /** + * @notice It is emitted when a new strategy is added. + * @param strategyId Id of the new strategy + * @param standardProtocolFeeBp Standard protocol fee (in basis point) + * @param minTotalFeeBp Minimum total fee (in basis point) + * @param maxProtocolFeeBp Maximum protocol fee (in basis point) + * @param selector Function selector for the transaction to be executed + * @param isMakerBid Whether the strategyId is for maker bid + * @param implementation Address of the implementation of the strategy + */ + event NewStrategy( + uint256 strategyId, + uint16 standardProtocolFeeBp, + uint16 minTotalFeeBp, + uint16 maxProtocolFeeBp, + bytes4 selector, + bool isMakerBid, + address implementation + ); + + /** + * @notice It is emitted when an existing strategy is updated. + * @param strategyId Id of the strategy + * @param isActive Whether the strategy is active (or not) after the update + * @param standardProtocolFeeBp Standard protocol fee (in basis point) + * @param minTotalFeeBp Minimum total fee (in basis point) + */ + event StrategyUpdated(uint256 strategyId, bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp); + + /** + * @notice If the strategy has not set properly its implementation contract. + * @dev It can only be returned for owner operations. + */ + error NotV2Strategy(); + + /** + * @notice It is returned if the strategy has no selector. + * @dev It can only be returned for owner operations. + */ + error StrategyHasNoSelector(); + + /** + * @notice It is returned if the strategyId is invalid. + */ + error StrategyNotUsed(); + + /** + * @notice It is returned if the strategy's protocol fee is too high. + * @dev It can only be returned for owner operations. + */ + error StrategyProtocolFeeTooHigh(); +} diff --git a/contracts/src/marketplace/interfaces/ITransferManager.sol b/contracts/src/marketplace/interfaces/ITransferManager.sol new file mode 100644 index 00000000..56f70e19 --- /dev/null +++ b/contracts/src/marketplace/interfaces/ITransferManager.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "../libraries/OrderStructs.sol"; + +// Enums +import { CollectionType } from "../enums/CollectionType.sol"; + +/** + * @title ITransferManager + * @author LooksRare protocol team (👀,💎) + */ +interface ITransferManager { + /** + * @notice This struct is only used for transferBatchItemsAcrossCollections. + * @param collection Collection address + * @param collectionType 0 for ERC721, 1 for ERC1155 + * @param itemIds Array of item ids to transfer + * @param amounts Array of amounts to transfer + */ + struct BatchTransferItem { + address collection; + CollectionType collectionType; + uint256[] itemIds; + uint256[] amounts; + } + + /** + * @notice It is emitted if operators' approvals to transfer NFTs are granted by a user. + * @param user Address of the user + * @param operators Array of operator addresses + */ + event ApprovalsGranted(address user, address[] operators); + + /** + * @notice It is emitted if operators' approvals to transfer NFTs are revoked by a user. + * @param user Address of the user + * @param operators Array of operator addresses + */ + event ApprovalsRemoved(address user, address[] operators); + + /** + * @notice It is emitted if a new operator is added to the global allowlist. + * @param operator Operator address + */ + event OperatorAllowed(address operator); + + /** + * @notice It is emitted if an operator is removed from the global allowlist. + * @param operator Operator address + */ + event OperatorRemoved(address operator); + + /** + * @notice It is returned if the operator to approve has already been approved by the user. + */ + error OperatorAlreadyApprovedByUser(); + + /** + * @notice It is returned if the operator to revoke has not been previously approved by the user. + */ + error OperatorNotApprovedByUser(); + + /** + * @notice It is returned if the transfer caller is already allowed by the owner. + * @dev This error can only be returned for owner operations. + */ + error OperatorAlreadyAllowed(); + + /** + * @notice It is returned if the operator to approve is not in the global allowlist defined by the owner. + * @dev This error can be returned if the user tries to grant approval to an operator address not in the + * allowlist or if the owner tries to remove the operator from the global allowlist. + */ + error OperatorNotAllowed(); + + /** + * @notice It is returned if the transfer caller is invalid. + * For a transfer called to be valid, the operator must be in the global allowlist and + * approved by the 'from' user. + */ + error TransferCallerInvalid(); +} diff --git a/contracts/src/marketplace/libraries/CurrencyValidator.sol b/contracts/src/marketplace/libraries/CurrencyValidator.sol new file mode 100644 index 00000000..d7523744 --- /dev/null +++ b/contracts/src/marketplace/libraries/CurrencyValidator.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Assembly +import { CurrencyInvalid_error_selector, CurrencyInvalid_error_length, Error_selector_offset } from "../constants/AssemblyConstants.sol"; + +/** + * @title CurrencyValidator + * @notice This library validates the order currency to be the + * chain's native currency or the specified ERC20 token. + * @author LooksRare protocol team (👀,💎) + */ +library CurrencyValidator { + /** + * @dev This is equivalent to + * if (orderCurrency != address(0)) { + * if (orderCurrency != allowedCurrency) { + * revert CurrencyInvalid(); + * } + * } + * + * 1. If orderCurrency == WETH, allowedCurrency == WETH -> WETH * 0 == 0 + * 2. If orderCurrency == ETH, allowedCurrency == WETH -> 0 * 1 == 0 + * 3. If orderCurrency == USDC, allowedCurrency == WETH -> USDC * 1 != 0 + */ + function allowNativeOrAllowedCurrency(address orderCurrency, address allowedCurrency) internal pure { + assembly { + if mul(orderCurrency, iszero(eq(orderCurrency, allowedCurrency))) { + mstore(0x00, CurrencyInvalid_error_selector) + revert(Error_selector_offset, CurrencyInvalid_error_length) + } + } + } +} diff --git a/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol b/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol new file mode 100644 index 00000000..d3d04cfe --- /dev/null +++ b/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "../../libraries/OrderStructs.sol"; + +/** + * @title MerkleProofCalldataWithNodes + * @notice This library is adjusted from the work of OpenZeppelin. + * It is based on the 4.7.0 (utils/cryptography/MerkleProof.sol). + * @author OpenZeppelin (adjusted by LooksRare) + */ +library MerkleProofCalldataWithNodes { + /** + * @notice This returns true if a `leaf` can be proved to be a part of a Merkle tree defined by `root`. + * For this, a `proof` must be provided, containing sibling hashes on the branch from the leaf to the + * root of the tree. Each pair of leaves and each pair of pre-images are assumed to be sorted. + */ + function verifyCalldata( + OrderStructs.MerkleTreeNode[] calldata proof, + bytes32 root, + bytes32 leaf + ) internal pure returns (bool) { + return processProofCalldata(proof, leaf) == root; + } + + /** + * @notice This returns the rebuilt hash obtained by traversing a Merkle tree up from `leaf` using `proof`. + * A `proof` is valid if and only if the rebuilt hash matches the root of the tree. + * When processing the proof, the pairs of leafs & pre-images are assumed to be sorted. + */ + function processProofCalldata( + OrderStructs.MerkleTreeNode[] calldata proof, + bytes32 leaf + ) internal pure returns (bytes32) { + bytes32 computedHash = leaf; + uint256 length = proof.length; + + for (uint256 i = 0; i < length; ) { + if (proof[i].position == OrderStructs.MerkleTreeNodePosition.Left) { + computedHash = _efficientHash(proof[i].value, computedHash); + } else { + computedHash = _efficientHash(computedHash, proof[i].value); + } + unchecked { + ++i; + } + } + return computedHash; + } + + function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, a) + mstore(0x20, b) + value := keccak256(0x00, 0x40) + } + } +} diff --git a/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofMemory.sol b/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofMemory.sol new file mode 100644 index 00000000..1e00db5a --- /dev/null +++ b/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofMemory.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @title MerkleProofMemory + * @notice This library is adjusted from the work of OpenZeppelin. + * It is based on the 4.7.0 (utils/cryptography/MerkleProof.sol). + * @author OpenZeppelin (adjusted by LooksRare) + */ +// TODO compare changes with OpenZeppelin +library MerkleProofMemory { + /** + * @notice This returns true if a `leaf` can be proved to be a part of a Merkle tree defined by `root`. + * For this, a `proof` must be provided, containing sibling hashes on the branch from the leaf to the + * root of the tree. Each pair of leaves and each pair of pre-images are assumed to be sorted. + */ + function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { + return processProof(proof, leaf) == root; + } + + /** + * @notice This returns the rebuilt hash obtained by traversing a Merkle tree up from `leaf` using `proof`. + * A `proof` is valid if and only if the rebuilt hash matches the root of the tree. + * When processing the proof, the pairs of leafs & pre-images are assumed to be sorted. + */ + function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { + bytes32 computedHash = leaf; + uint256 length = proof.length; + + for (uint256 i = 0; i < length; ) { + computedHash = _hashPair(computedHash, proof[i]); + unchecked { + ++i; + } + } + return computedHash; + } + + function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { + return a < b ? _efficientHash(a, b) : _efficientHash(b, a); + } + + function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, a) + mstore(0x20, b) + value := keccak256(0x00, 0x40) + } + } +} diff --git a/contracts/src/marketplace/libraries/OrderStructs.sol b/contracts/src/marketplace/libraries/OrderStructs.sol new file mode 100644 index 00000000..e7600695 --- /dev/null +++ b/contracts/src/marketplace/libraries/OrderStructs.sol @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Enums +import { CollectionType } from "../enums/CollectionType.sol"; +import { QuoteType } from "../enums/QuoteType.sol"; + +/** + * @title OrderStructs + * @notice This library contains all order struct types for the LooksRare protocol (v2). + * @author LooksRare protocol team (👀,💎) + */ +library OrderStructs { + /** + * 1. Maker struct + */ + + /** + * @notice Maker is the struct for a maker order. + * @param quoteType Quote type (i.e. 0 = BID, 1 = ASK) + * @param globalNonce Global user order nonce for maker orders + * @param subsetNonce Subset nonce (shared across bid/ask maker orders) + * @param orderNonce Order nonce (it can be shared across bid/ask maker orders) + * @param strategyId Strategy id + * @param collectionType Collection type (i.e. 0 = ERC721, 1 = ERC1155, 2 = Hypercert, 3 = Hyperboard) + * @param collection Collection address + * @param currency Currency address (@dev address(0) = ETH) + * @param signer Signer address + * @param startTime Start timestamp + * @param endTime End timestamp + * @param price Minimum price for maker ask, maximum price for maker bid + * @param itemIds Array of itemIds + * @param amounts Array of amounts + * @param additionalParameters Extra data specific for the order + */ + struct Maker { + QuoteType quoteType; + uint256 globalNonce; + uint256 subsetNonce; + uint256 orderNonce; + uint256 strategyId; + CollectionType collectionType; + address collection; + address currency; + address signer; + uint256 startTime; + uint256 endTime; + uint256 price; + uint256[] itemIds; + uint256[] amounts; + bytes additionalParameters; + } + + /** + * 2. Taker struct + */ + + /** + * @notice Taker is the struct for a taker ask/bid order. It contains the parameters required for a direct purchase. + * @dev Taker struct is matched against MakerAsk/MakerBid structs at the protocol level. + * @param recipient Recipient address (to receive NFTs or non-fungible tokens) + * @param additionalParameters Extra data specific for the order + */ + struct Taker { + address recipient; + bytes additionalParameters; + } + + /** + * 3. Merkle tree struct + */ + + enum MerkleTreeNodePosition { + Left, + Right + } + + /** + * @notice MerkleTreeNode is a MerkleTree's node. + * @param value It can be an order hash or a proof + * @param position The node's position in its branch. + * It can be left or right or none + * (before the tree is sorted). + */ + struct MerkleTreeNode { + bytes32 value; + MerkleTreeNodePosition position; + } + + /** + * @notice MerkleTree is the struct for a merkle tree of order hashes. + * @dev A Merkle tree can be computed with order hashes. + * It can contain order hashes from both maker bid and maker ask structs. + * @param root Merkle root + * @param proof Array containing the merkle proof + */ + struct MerkleTree { + bytes32 root; + MerkleTreeNode[] proof; + } + + /** + * 4. Constants + */ + + /** + * @notice This is the type hash constant used to compute the maker order hash. + */ + bytes32 internal constant _MAKER_TYPEHASH = + keccak256( + "Maker(" + "uint8 quoteType," + "uint256 globalNonce," + "uint256 subsetNonce," + "uint256 orderNonce," + "uint256 strategyId," + "uint8 collectionType," + "address collection," + "address currency," + "address signer," + "uint256 startTime," + "uint256 endTime," + "uint256 price," + "uint256[] itemIds," + "uint256[] amounts," + "bytes additionalParameters" + ")" + ); + + /** + * 5. Hash functions + */ + + /** + * @notice This function is used to compute the order hash for a maker struct. + * @param maker Maker order struct + * @return makerHash Hash of the maker struct + */ + function hash(Maker memory maker) internal pure returns (bytes32) { + // Encoding is done into two parts to avoid stack too deep issues + return + keccak256( + bytes.concat( + abi.encode( + _MAKER_TYPEHASH, + maker.quoteType, + maker.globalNonce, + maker.subsetNonce, + maker.orderNonce, + maker.strategyId, + maker.collectionType, + maker.collection, + maker.currency + ), + abi.encode( + maker.signer, + maker.startTime, + maker.endTime, + maker.price, + keccak256(abi.encodePacked(maker.itemIds)), + keccak256(abi.encodePacked(maker.amounts)), + keccak256(maker.additionalParameters) + ) + ) + ); + } +} diff --git a/contracts/contracts/AllowlistMinter.sol b/contracts/src/protocol/AllowlistMinter.sol similarity index 100% rename from contracts/contracts/AllowlistMinter.sol rename to contracts/src/protocol/AllowlistMinter.sol diff --git a/contracts/src/HypercertMinter.sol b/contracts/src/protocol/HypercertMinter.sol similarity index 100% rename from contracts/src/HypercertMinter.sol rename to contracts/src/protocol/HypercertMinter.sol diff --git a/contracts/src/SemiFungible1155.sol b/contracts/src/protocol/SemiFungible1155.sol similarity index 100% rename from contracts/src/SemiFungible1155.sol rename to contracts/src/protocol/SemiFungible1155.sol diff --git a/contracts/contracts/interfaces/IAllowlist.sol b/contracts/src/protocol/interfaces/IAllowlist.sol similarity index 100% rename from contracts/contracts/interfaces/IAllowlist.sol rename to contracts/src/protocol/interfaces/IAllowlist.sol diff --git a/contracts/src/interfaces/IHypercertToken.sol b/contracts/src/protocol/interfaces/IHypercertToken.sol similarity index 100% rename from contracts/src/interfaces/IHypercertToken.sol rename to contracts/src/protocol/interfaces/IHypercertToken.sol diff --git a/contracts/contracts/libs/Errors.sol b/contracts/src/protocol/libs/Errors.sol similarity index 100% rename from contracts/contracts/libs/Errors.sol rename to contracts/src/protocol/libs/Errors.sol diff --git a/contracts/test/foundry/HypercertTrader.admin.t.sol b/contracts/test/foundry/HypercertTrader.admin.t.sol deleted file mode 100644 index 3b7ee0eb..00000000 --- a/contracts/test/foundry/HypercertTrader.admin.t.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.16; - -import { HypercertTrader } from "../../src/HypercertTrader.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; - -interface IHypercertMinter { - function ownerOf(uint256 id) external view returns (address); - - function unitsOf(uint256 id) external view returns (uint256); -} - -contract HypercertTraderHelper is HypercertTrader { - error NotAllowed(); - error InvalidOffer(string); - - // TODO - Use UUPS pattern for contracts and getting owner - address internal alice = address(1); - address internal bob = address(2); - - HypercertMinter public hypercertMinter = new HypercertMinter(); - - function getOfferCount() external view returns (uint256) { - return _offerCounter; - } -} - -contract HypercertTraderAdminTest is HypercertTraderHelper, PRBTest, StdCheats, StdUtils { - HypercertTraderHelper internal hypercertTrader; - - function setUp() public { - hypercertTrader = new HypercertTraderHelper(); - } - - function testPausability() public { - AcceptedToken[] memory acceptedTokens = new AcceptedToken[](1); - acceptedTokens[0] = AcceptedToken(address(0), 1); - - // Contract is not paused - assertEq(hypercertTrader.paused(), false); - - // Bob can't pause the contracts - vm.startPrank(bob); - vm.expectRevert("Ownable: caller is not the owner"); - hypercertTrader.pause(); - - // Owner can pause the contract - vm.startPrank(owner()); - vm.expectEmit(true, false, false, false); - emit Paused(owner()); - hypercertTrader.pause(); - - // All functions are paused - vm.expectRevert("Pausable: paused"); - hypercertTrader.createOffer(address(hypercertMinter), 1, 1, 1, 1, acceptedTokens); - - vm.expectRevert("Pausable: paused"); - hypercertTrader.cancelOffer(1); - - vm.expectRevert("Pausable: paused"); - hypercertTrader.buyUnits(alice, 1, 1, address(0), 1); - - // Bob can't unpause the contract - vm.startPrank(bob); - vm.expectRevert("Ownable: caller is not the owner"); - hypercertTrader.unpause(); - - // Owner can unpause the contract - vm.startPrank(owner()); - vm.expectEmit(true, false, false, false); - emit Unpaused(owner()); - hypercertTrader.unpause(); - - // All functions are unpaused - vm.expectRevert(NotAllowed.selector); - hypercertTrader.createOffer(address(hypercertMinter), 1, 1, 1, 1, acceptedTokens); - - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "No contract address found")); - hypercertTrader.cancelOffer(1); - - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Min/Max units")); - hypercertTrader.buyUnits(alice, 1, 1, address(0), 1); - } -} diff --git a/contracts/test/foundry/HypercertTrader.offers.t.sol b/contracts/test/foundry/HypercertTrader.offers.t.sol deleted file mode 100644 index 6901b314..00000000 --- a/contracts/test/foundry/HypercertTrader.offers.t.sol +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.16; - -import { HypercertTrader } from "../../src/HypercertTrader.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; - -interface IHypercertMinter { - function ownerOf(uint256 id) external view returns (address); - - function unitsOf(uint256 id) external view returns (uint256); -} - -contract HypercertTraderHelper is HypercertTrader { - error NotAllowed(); - error InvalidOffer(string); - - address alice = address(1); - address bob = address(2); - - HypercertMinter public hypercertMinter = new HypercertMinter(); - - function getOfferCount() external view returns (uint256) { - return _offerCounter; - } - - function exposedValidateBuyOffer( - address offerer, - address hypercertContract, - uint256 fractionID, - uint256 units, - uint256 minUnitsPerTrade, - uint256 maxUnitsPerTrade, - AcceptedToken[] memory acceptedTokens - ) external payable { - _validateOffer( - offerer, - hypercertContract, - fractionID, - units, - minUnitsPerTrade, - maxUnitsPerTrade, - acceptedTokens - ); - } -} - -contract HypercertTraderCreateOfferTest is HypercertTraderHelper, PRBTest, StdCheats, StdUtils { - HypercertTraderHelper internal hypercertTrader; - - function setUp() public { - hypercertTrader = new HypercertTraderHelper(); - } - - function testCreateOfferWithAllowance() public { - // Setup - vm.startPrank(alice); - hypercertMinter.mintClaim(alice, 10000, "ipfs://test", IHypercertToken.TransferRestrictions.FromCreatorOnly); - - uint256 baseID = 1 << 128; - uint256 tokenIndex = 1; - uint256 tokenID = baseID + tokenIndex; - - AcceptedToken[] memory acceptedTokens = new AcceptedToken[](1); - acceptedTokens[0] = AcceptedToken(address(0), 1); - - // Reverts when Trader contract is not approved - vm.expectRevert(NotAllowed.selector); - hypercertTrader.createOffer(address(hypercertMinter), tokenID, 1, 1, 1, acceptedTokens); - - // Set approval - hypercertMinter.setApprovalForAll(address(hypercertTrader), true); - - // Alice creates an offer - vm.expectEmit(true, true, true, true); - emit OfferCreated(alice, address(hypercertMinter), tokenID, 0); - uint256 offerID = hypercertTrader.createOffer(address(hypercertMinter), tokenID, 1, 1, 1, acceptedTokens); - - assertEq(hypercertTrader.getOfferCount(), 1); - assertEq(hypercertTrader.totalUnitsForSale(address(hypercertMinter), tokenID), 1); - - // Offer is created - Offer memory offer = hypercertTrader.getOffer(offerID); - assertEq(offer.fractionID, tokenID); - assertEq(offer.unitsAvailable, 1); - assertEq(offer.minUnitsPerTrade, 1); - assertEq(offer.maxUnitsPerTrade, 1); - assertEq(offer.acceptedTokens.length, 1); - assertEq(uint256(offer.status), uint256(OfferStatus.Open)); - } - - function testCannotCreateOfferForNonExistentToken() public { - hypercertMinter.setApprovalForAll(address(hypercertTrader), true); - - AcceptedToken[] memory acceptedTokens = new AcceptedToken[](1); - acceptedTokens[0] = AcceptedToken(address(0), 1); - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Not owner")); - hypercertTrader.createOffer(address(hypercertMinter), 1, 1, 1, 1, acceptedTokens); - } - - function testCanCancelOffer() public { - // Setup - vm.startPrank(alice); - hypercertMinter.mintClaim(alice, 10000, "ipfs://test", IHypercertToken.TransferRestrictions.FromCreatorOnly); - - uint256 baseID = 1 << 128; - uint256 tokenIndex = 1; - uint256 tokenID = baseID + tokenIndex; - - AcceptedToken[] memory acceptedTokens = new AcceptedToken[](1); - acceptedTokens[0] = AcceptedToken(address(0), 1); - - hypercertMinter.setApprovalForAll(address(hypercertTrader), true); - - // Alice creates an offer - vm.expectEmit(true, true, true, true); - emit OfferCreated(alice, address(hypercertMinter), tokenID, 0); - uint256 offerID = hypercertTrader.createOffer(address(hypercertMinter), tokenID, 1, 1, 1, acceptedTokens); - - Offer memory offer = hypercertTrader.getOffer(offerID); - assertEq(offer.fractionID, tokenID); - assertEq(uint256(offer.status), uint256(OfferStatus.Open)); - assertEq(hypercertTrader.totalUnitsForSale(address(hypercertMinter), tokenID), 1); - - // Bob tries to cancel the offer and is rejected - changePrank(bob); - vm.expectRevert(NotAllowed.selector); - hypercertTrader.cancelOffer(offerID); - - // Alice cancels the offer - changePrank(alice); - vm.expectEmit(true, true, true, true); - emit OfferCancelled(alice, address(hypercertMinter), tokenID, 0); - hypercertTrader.cancelOffer(offerID); - - // The offer is cancelled - Offer memory updatedOffer = hypercertTrader.getOffer(offerID); - assertEq(uint256(updatedOffer.status), uint256(OfferStatus.Cancelled)); - assertEq(hypercertTrader.totalUnitsForSale(address(hypercertMinter), tokenID), 0); - } - - function testOfferValidations() public { - vm.mockCall( - address(hypercertMinter), - abi.encodeWithSelector(IHypercertMinter.ownerOf.selector, 42), - abi.encode(alice) - ); - vm.mockCall( - address(hypercertMinter), - abi.encodeWithSelector(IHypercertMinter.unitsOf.selector, 42), - abi.encode(10) - ); - AcceptedToken[] memory acceptedToken = new AcceptedToken[](1); - acceptedToken[0] = AcceptedToken(address(0), 1); - - // Fail on 0 units - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Insufficient units")); - hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 0, 1, 1, acceptedToken); - - // Fail on more units than in the fraction - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Insufficient units")); - hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 11, 1, 1, acceptedToken); - - // Fail on higher than max units - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Min/Max units")); - hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 1, 999, acceptedToken); - - // Fail on lower than min units - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Min/Max units")); - hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 999, 1, acceptedToken); - - // Fail when min-max are equal but the units are not divisible by the min-max value - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Units indivisible by fractions")); - hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 7, 2, 2, acceptedToken); - - // Fail when there's no accepted token - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "No accepted tokens")); - hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 1, 1, new AcceptedToken[](0)); - - // Fail when the accepted token has a minimum amount per unit of 0 - AcceptedToken[] memory invalidAcceptedToken = new AcceptedToken[](1); - invalidAcceptedToken[0] = AcceptedToken(address(0), 0); - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "No accepted tokens")); - hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 1, 1, invalidAcceptedToken); - - // Fail when accepted token that's not the native token - AcceptedToken[] memory nonNativeAcceptedToken = new AcceptedToken[](1); - nonNativeAcceptedToken[0] = AcceptedToken(address(1), 1); - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Only zero token")); - hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 1, 1, nonNativeAcceptedToken); - - // Fail on insufficient units in fraction - vm.mockCall( - address(hypercertMinter), - abi.encodeWithSelector(IHypercertMinter.unitsOf.selector, 42), - abi.encode(1) - ); - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Insufficient units")); - hypercertTrader.exposedValidateBuyOffer(alice, address(hypercertMinter), 42, 2, 1, 1, new AcceptedToken[](0)); - } -} diff --git a/contracts/test/foundry/HypercertTrader.sales.t.sol b/contracts/test/foundry/HypercertTrader.sales.t.sol deleted file mode 100644 index 07c0216a..00000000 --- a/contracts/test/foundry/HypercertTrader.sales.t.sol +++ /dev/null @@ -1,241 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.16; - -import { HypercertTrader } from "../../src/HypercertTrader.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; - -interface IHypercertMinter { - function ownerOf(uint256 id) external view returns (address); - - function unitsOf(uint256 id) external view returns (uint256); -} - -contract HypercertTraderHelper is HypercertTrader, PRBTest, StdCheats, StdUtils { - error NotAllowed(); - error InvalidOffer(string); - error InvalidBuy(string); - - address alice = makeAddr("alice"); - address bob = makeAddr("bob"); - - HypercertMinter public hypercertMinter = new HypercertMinter(); - - function getOfferCount() external view returns (uint256) { - return _offerCounter; - } - - function exposedValidateBuyOffer( - Offer memory offer, - uint256 unitAmount, - address buyToken, - uint256 tokenAmountPerUnit - ) external payable { - _validateBuyOffer(offer, unitAmount, buyToken, tokenAmountPerUnit); - } - - function createDefaultOffer(bool full) external returns (uint256 offerID, uint256 fractionID) { - vm.startPrank(alice); - hypercertMinter.mintClaim(alice, 10000, "ipfs://test", IHypercertToken.TransferRestrictions.FromCreatorOnly); - - uint256 baseID = 1 << 128; - uint256 tokenIndex = 1; - fractionID = baseID + tokenIndex; - - AcceptedToken[] memory acceptedTokens = new AcceptedToken[](1); - acceptedTokens[0] = AcceptedToken(address(0), 3); - - hypercertMinter.setApprovalForAll(address(this), true); - - vm.expectEmit(true, true, true, true); - emit OfferCreated(alice, address(hypercertMinter), fractionID, 0); - if (full) { - offerID = this.createOffer(address(hypercertMinter), fractionID, 10000, 10, 10000, acceptedTokens); - } else { - offerID = this.createOffer(address(hypercertMinter), fractionID, 1000, 10, 1000, acceptedTokens); - } - } -} - -//TODO cleanup inheritance -contract HypercertTraderBuyOfferTest is HypercertTraderHelper { - HypercertTraderHelper internal hypercertTrader; - - function setUp() public { - hypercertTrader = new HypercertTraderHelper(); - } - - function testBuyOfferFullBid() public { - // Alice has no balance - assertEq(alice.balance, 0); - - // Alice creates a offer - (uint256 offerID, uint256 fractionID) = hypercertTrader.createDefaultOffer(false); - assertEq(hypercertTrader.getOfferCount(), 1); - assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 1000); - - // Bob buys the full offer - startHoax(bob, 10 ether); - vm.expectEmit(true, true, true, true); - emit Trade(alice, bob, address(hypercertTrader.hypercertMinter()), fractionID, 1000, address(0), 10, offerID); - hypercertTrader.buyUnits{ value: 10000 }(bob, offerID, 1000, address(0), 10); - - // Bob owns the new fraction - assertEq(hypercertTrader.hypercertMinter().ownerOf(fractionID + 1), bob); - - // Alice still owns the old fraction and the units that weren't sold - assertEq(hypercertTrader.hypercertMinter().ownerOf(fractionID), alice); - assertEq(hypercertTrader.hypercertMinter().unitsOf(fractionID), 9000); - - // The offer is closed - Offer memory offer = hypercertTrader.getOffer(offerID); - assertEq(uint256(offer.status), uint256(OfferStatus.Fulfilled)); - assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 0); - - // And bob can't buy any more of the offer - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong status")); - hypercertTrader.buyUnits{ value: 10000 }(bob, offerID, 10, address(0), 10); - - // Alice received the funds - assertEq(alice.balance, 10000); - } - - function testBuyOfferFullFraction() public { - // Alice has no balance - assertEq(alice.balance, 0); - - // Alice creates a offer - (uint256 offerID, uint256 fractionID) = hypercertTrader.createDefaultOffer(true); - assertEq(hypercertTrader.getOfferCount(), 1); - assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 10000); - - // Bob buys the full offer for the full token - startHoax(bob, 10 ether); - vm.expectEmit(true, true, true, true); - emit Trade(alice, bob, address(hypercertTrader.hypercertMinter()), fractionID, 10000, address(0), 10, offerID); - hypercertTrader.buyUnits{ value: 100000 }(bob, offerID, 10000, address(0), 10); - - // Bob bought the full fraction and owns it - assertEq(hypercertTrader.hypercertMinter().ownerOf(fractionID), bob); - - // No new fraction was minted - assertEq(hypercertTrader.hypercertMinter().unitsOf(fractionID + 1), 0); - - // The offer is closed - Offer memory offer = hypercertTrader.getOffer(offerID); - assertEq(uint256(offer.status), uint256(OfferStatus.Fulfilled)); - assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 0); - - // And bob can't buy any more of the offer - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong status")); - hypercertTrader.buyUnits{ value: 10000 }(bob, offerID, 1, address(0), 10); - - // Alice received the funds - assertEq(alice.balance, 100000); - } - - function testBuyOfferPartial() public { - // Alice creates a offer - (uint256 offerID, uint256 fractionID) = hypercertTrader.createDefaultOffer(false); - assertEq(hypercertTrader.getOfferCount(), 1); - assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 1000); - - // Bob buys part of the offer - startHoax(bob, 10 ether); - vm.expectEmit(true, true, true, true); - emit Trade(alice, bob, address(hypercertTrader.hypercertMinter()), fractionID, 500, address(0), 10, offerID); - hypercertTrader.buyUnits{ value: 5000 }(bob, offerID, 500, address(0), 10); - - // Bob owns the new fraction worth 500 units - assertEq(hypercertTrader.hypercertMinter().ownerOf(fractionID + 1), bob); - assertEq(hypercertTrader.hypercertMinter().unitsOf(fractionID + 1), 500); - - // The offer is still open - Offer memory offer = hypercertTrader.getOffer(offerID); - assertEq(uint256(offer.status), uint256(OfferStatus.Open)); - assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 500); - - // And bob can buy the rest of the offer - vm.expectEmit(true, true, true, true); - emit Trade(alice, bob, address(hypercertTrader.hypercertMinter()), fractionID, 500, address(0), 10, offerID); - hypercertTrader.buyUnits{ value: 5000 }(bob, offerID, 500, address(0), 10); - - // Bob owns the new fraction worth 500 units - assertEq(hypercertTrader.hypercertMinter().ownerOf(fractionID + 2), bob); - assertEq(hypercertTrader.hypercertMinter().unitsOf(fractionID + 2), 500); - - // The offer is closed - offer = hypercertTrader.getOffer(offerID); - assertEq(uint256(offer.status), uint256(OfferStatus.Fulfilled)); - assertEq(hypercertTrader.totalUnitsForSale(address(hypercertTrader.hypercertMinter()), fractionID), 0); - } - - function testBuyOfferFailsLowBid() public { - // Alice creates a offer - (uint256 offerID, ) = hypercertTrader.createDefaultOffer(false); - assertEq(hypercertTrader.getOfferCount(), 1); - - // Bob tries to buy the offer with a low bid (tokenAmountPerUnit lower than min asking price) - startHoax(bob, 10 ether); - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong token/value")); - hypercertTrader.buyUnits{ value: 5000 }(bob, offerID, 500, address(0), 2); - - // Bob tries to buy the offer with a low bid (msg.value too low) - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong token/value")); - hypercertTrader.buyUnits{ value: 4999 }(bob, offerID, 500, address(0), 10); - - // The offer is still open - Offer memory offer = hypercertTrader.getOffer(offerID); - assertEq(uint256(offer.status), uint256(OfferStatus.Open)); - } - - function testBuyOfferValidations() public { - Offer memory offer = Offer({ - offerer: alice, - hypercertContract: address(hypercertMinter), - fractionID: 42, - unitsAvailable: 10, - minUnitsPerTrade: 2, - maxUnitsPerTrade: 5, - status: OfferStatus.Open, - offerType: OfferType.Units, - acceptedTokens: new AcceptedToken[](1) - }); - - vm.mockCall( - address(hypercertMinter), - abi.encodeWithSelector(IHypercertMinter.ownerOf.selector, 42), - abi.encode(alice) - ); - - offer.acceptedTokens[0] = AcceptedToken(address(0), 2); - - // Expect revert on mix/maxUnitsPerTrade - // Bid too low - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong token/value")); - this.exposedValidateBuyOffer(offer, 3, address(0), 1); - - // Units bought too low - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Min/Max units")); - this.exposedValidateBuyOffer(offer, 1, address(0), 3); - - // Too high - // Units bought too high - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Min/Max units")); - this.exposedValidateBuyOffer(offer, 11, address(0), 3); - - // Within range but no value - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong token/value")); - this.exposedValidateBuyOffer(offer, 3, address(0), 3); - - this.exposedValidateBuyOffer{ value: 10 }(offer, 3, address(0), 3); - - // Expect revert on wrong token - offer.acceptedTokens[0] = AcceptedToken(address(1337), 2); - vm.expectRevert(abi.encodeWithSelector(InvalidOffer.selector, "Wrong token/value")); - this.exposedValidateBuyOffer(offer, 3, address(1), 1); - } -} diff --git a/contracts/test/foundry/marketplace/BatchMakerCollectionOrders.t.sol b/contracts/test/foundry/marketplace/BatchMakerCollectionOrders.t.sol new file mode 100644 index 00000000..9222bd04 --- /dev/null +++ b/contracts/test/foundry/marketplace/BatchMakerCollectionOrders.t.sol @@ -0,0 +1,114 @@ +/// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Strategies +import { StrategyCollectionOffer } from "@hypercerts/marketplace/executionStrategies/StrategyCollectionOffer.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Helpers +import { EIP712MerkleTree } from "./utils/EIP712MerkleTree.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract BatchMakerCollectionOrdersTest is ProtocolBase { + StrategyCollectionOffer private strategy; + uint256 private constant price = 1 ether; // Fixed price of sale + EIP712MerkleTree private eip712MerkleTree; + + function setUp() public { + _setUp(); + + strategy = new StrategyCollectionOffer(); + vm.prank(_owner); + looksRareProtocol.addStrategy( + _standardProtocolFeeBp, + _minTotalFeeBp, + _maxProtocolFeeBp, + StrategyCollectionOffer.executeCollectionStrategyWithTakerAsk.selector, + true, + address(strategy) + ); + + _setUpUsers(); + eip712MerkleTree = new EIP712MerkleTree(looksRareProtocol); + } + + function testTakerAskMultipleOrdersSignedERC721(uint256 numberOrders) public { + vm.assume(numberOrders > 0 && numberOrders <= 10); + + mockERC721.batchMint(takerUser, numberOrders); + + OrderStructs.Maker[] memory makerBids = _createBatchMakerBids(numberOrders); + + (bytes memory signature, ) = eip712MerkleTree.sign(makerUserPK, makerBids, 0); + + for (uint256 i; i < numberOrders; i++) { + // To prove that we only need 1 signature for multiple collection offers, + // we are not using the signature from the sign call in the loop. + (, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign(makerUserPK, makerBids, i); + + OrderStructs.Maker memory makerBidToExecute = makerBids[i]; + + // Verify validity + _assertValidMakerOrderWithMerkleTree(makerBidToExecute, signature, merkleTree); + + OrderStructs.Taker memory takerOrder = OrderStructs.Taker(takerUser, abi.encode(i)); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerOrder, makerBidToExecute, signature, merkleTree, _EMPTY_AFFILIATE); + + // Maker user has received the asset + assertEq(mockERC721.ownerOf(i), makerUser); + + // Verify the nonce is marked as executed + assertEq( + looksRareProtocol.userOrderNonce(makerUser, makerBidToExecute.orderNonce), + MAGIC_VALUE_ORDER_NONCE_EXECUTED + ); + } + + uint256 totalValue = price * numberOrders; + assertEq( + weth.balanceOf(makerUser), + _initialWETHBalanceUser - totalValue, + "Maker bid user should pay the whole price" + ); + assertEq( + weth.balanceOf(takerUser), + _initialWETHBalanceUser + + (totalValue * _sellerProceedBpWithStandardProtocolFeeBp) / + ONE_HUNDRED_PERCENT_IN_BP, + "Taker ask user should receive 99.5% of the whole price (0.5% protocol)" + ); + } + + function _createBatchMakerBids(uint256 numberOrders) private view returns (OrderStructs.Maker[] memory makerBids) { + makerBids = new OrderStructs.Maker[](numberOrders); + for (uint256 i; i < numberOrders; i++) { + makerBids[i] = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, + collectionType: CollectionType.ERC721, + orderNonce: i, // incremental + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: 0 // Not used + }); + } + } +} diff --git a/contracts/test/foundry/marketplace/BatchMakerOrders.t.sol b/contracts/test/foundry/marketplace/BatchMakerOrders.t.sol new file mode 100644 index 00000000..fabceaae --- /dev/null +++ b/contracts/test/foundry/marketplace/BatchMakerOrders.t.sol @@ -0,0 +1,413 @@ +/// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Murky (third-party) library is used to compute Merkle trees in Solidity +import { Merkle } from "murky/Merkle.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Errors and constants +import { MerkleProofTooLarge, MerkleProofInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { MERKLE_PROOF_PROOF_TOO_LARGE, ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import { ONE_HUNDRED_PERCENT_IN_BP, MAX_CALLDATA_PROOF_LENGTH } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Helpers +import { EIP712MerkleTree } from "./utils/EIP712MerkleTree.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract BatchMakerOrdersTest is ProtocolBase { + uint256 private constant price = 1.2222 ether; // Fixed price of sale + EIP712MerkleTree private eip712MerkleTree; + + function setUp() public { + _setUp(); + _setUpUsers(); + eip712MerkleTree = new EIP712MerkleTree(looksRareProtocol); + } + + function testTakerBidMultipleOrdersSignedERC721(uint256 numberOrders, uint256 orderIndex) public { + _assertMerkleTreeAssumptions(numberOrders, orderIndex); + + mockERC721.batchMint(makerUser, numberOrders); + + OrderStructs.Maker[] memory makerAsks = _createBatchMakerAsks(numberOrders); + + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( + makerUserPK, + makerAsks, + orderIndex + ); + + OrderStructs.Maker memory makerAskToExecute = makerAsks[orderIndex]; + + // Verify validity + _assertValidMakerOrderWithMerkleTree(makerAskToExecute, signature, merkleTree); + + // Execute taker bid transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + _genericTakerOrder(), + makerAskToExecute, + signature, + merkleTree, + _EMPTY_AFFILIATE + ); + + // Taker user has received the asset + assertEq(mockERC721.ownerOf(orderIndex), takerUser); + // Taker bid user pays the whole price + assertEq(address(takerUser).balance, _initialETHBalanceUser - price); + // Maker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq( + address(makerUser).balance, + _initialETHBalanceUser + (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP + ); + // No leftover in the balance of the contract + assertEq(address(looksRareProtocol).balance, 0); + // Verify the nonce is marked as executed + assertEq( + looksRareProtocol.userOrderNonce(makerUser, makerAskToExecute.orderNonce), + MAGIC_VALUE_ORDER_NONCE_EXECUTED + ); + } + + function testTakerAskMultipleOrdersSignedERC721(uint256 numberOrders, uint256 orderIndex) public { + _assertMerkleTreeAssumptions(numberOrders, orderIndex); + + mockERC721.batchMint(takerUser, numberOrders); + + OrderStructs.Maker[] memory makerBids = _createBatchMakerBids(numberOrders); + + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( + makerUserPK, + makerBids, + orderIndex + ); + + OrderStructs.Maker memory makerBidToExecute = makerBids[orderIndex]; + + // Verify validity + _assertValidMakerOrderWithMerkleTree(makerBidToExecute, signature, merkleTree); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk( + _genericTakerOrder(), + makerBidToExecute, + signature, + merkleTree, + _EMPTY_AFFILIATE + ); + + // Maker user has received the asset + assertEq(mockERC721.ownerOf(orderIndex), makerUser); + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - price); + // Taker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq( + weth.balanceOf(takerUser), + _initialWETHBalanceUser + (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP + ); + // Verify the nonce is marked as executed + assertEq( + looksRareProtocol.userOrderNonce(makerUser, makerBidToExecute.orderNonce), + MAGIC_VALUE_ORDER_NONCE_EXECUTED + ); + } + + function testTakerBidMultipleOrdersSignedERC721MerkleProofInvalid(uint256 numberOrders, uint256 orderIndex) public { + _assertMerkleTreeAssumptions(numberOrders, orderIndex); + + mockERC721.batchMint(makerUser, numberOrders); + + OrderStructs.Maker[] memory makerAsks = _createBatchMakerAsks(numberOrders); + + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( + makerUserPK, + makerAsks, + orderIndex + ); + + bytes32 tamperedRoot = bytes32(uint256(merkleTree.root) + 1); + merkleTree.root = tamperedRoot; + + OrderStructs.Maker memory makerAskToExecute = makerAsks[orderIndex]; + + // Verify invalidity of maker ask order + _assertMakerOrderReturnValidationCodeWithMerkleTree( + makerAskToExecute, + signature, + merkleTree, + ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE + ); + + vm.prank(takerUser); + vm.expectRevert(MerkleProofInvalid.selector); + looksRareProtocol.executeTakerBid{ value: price }( + _genericTakerOrder(), + makerAskToExecute, + signature, + merkleTree, + _EMPTY_AFFILIATE + ); + } + + function testTakerAskMultipleOrdersSignedERC721MerkleProofInvalid(uint256 numberOrders, uint256 orderIndex) public { + _assertMerkleTreeAssumptions(numberOrders, orderIndex); + + mockERC721.batchMint(takerUser, numberOrders); + + OrderStructs.Maker[] memory makerBids = _createBatchMakerBids(numberOrders); + + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( + makerUserPK, + makerBids, + orderIndex + ); + + bytes32 tamperedRoot = bytes32(uint256(merkleTree.root) + 1); + merkleTree.root = tamperedRoot; + + OrderStructs.Maker memory makerBidToExecute = makerBids[orderIndex]; + + // Verify invalidity of maker bid order + _assertMakerOrderReturnValidationCodeWithMerkleTree( + makerBidToExecute, + signature, + merkleTree, + ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE + ); + + vm.prank(takerUser); + vm.expectRevert(MerkleProofInvalid.selector); + looksRareProtocol.executeTakerAsk( + _genericTakerOrder(), + makerBidToExecute, + signature, + merkleTree, + _EMPTY_AFFILIATE + ); + } + + function testTakerBidMultipleOrdersSignedERC721MerkleProofWrongPosition( + uint256 numberOrders, + uint256 orderIndex + ) public { + _assertMerkleTreeAssumptions(numberOrders, orderIndex); + + mockERC721.batchMint(makerUser, numberOrders); + + OrderStructs.Maker[] memory makerAsks = _createBatchMakerAsks(numberOrders); + + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( + makerUserPK, + makerAsks, + orderIndex + ); + + // Swap every node's position + OrderStructs.MerkleTreeNode[] memory proof = merkleTree.proof; + for (uint256 i; i < proof.length; i++) { + if (proof[i].position == OrderStructs.MerkleTreeNodePosition.Left) { + proof[i].position = OrderStructs.MerkleTreeNodePosition.Right; + } else { + proof[i].position = OrderStructs.MerkleTreeNodePosition.Left; + } + } + + OrderStructs.Maker memory makerAskToExecute = makerAsks[orderIndex]; + + // Verify invalidity of maker ask order + _assertMakerOrderReturnValidationCodeWithMerkleTree( + makerAskToExecute, + signature, + merkleTree, + ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE + ); + + vm.prank(takerUser); + vm.expectRevert(MerkleProofInvalid.selector); + looksRareProtocol.executeTakerBid{ value: price }( + _genericTakerOrder(), + makerAskToExecute, + signature, + merkleTree, + _EMPTY_AFFILIATE + ); + } + + function testTakerAskMultipleOrdersSignedERC721MerkleProofWrongPosition( + uint256 numberOrders, + uint256 orderIndex + ) public { + _assertMerkleTreeAssumptions(numberOrders, orderIndex); + + mockERC721.batchMint(takerUser, numberOrders); + + OrderStructs.Maker[] memory makerBids = _createBatchMakerBids(numberOrders); + + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( + makerUserPK, + makerBids, + orderIndex + ); + + // Swap every node's position + OrderStructs.MerkleTreeNode[] memory proof = merkleTree.proof; + for (uint256 i; i < proof.length; i++) { + if (proof[i].position == OrderStructs.MerkleTreeNodePosition.Left) { + proof[i].position = OrderStructs.MerkleTreeNodePosition.Right; + } else { + proof[i].position = OrderStructs.MerkleTreeNodePosition.Left; + } + } + + OrderStructs.Maker memory makerBidToExecute = makerBids[orderIndex]; + + // Verify invalidity of maker bid order + _assertMakerOrderReturnValidationCodeWithMerkleTree( + makerBidToExecute, + signature, + merkleTree, + ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE + ); + + vm.prank(takerUser); + vm.expectRevert(MerkleProofInvalid.selector); + looksRareProtocol.executeTakerAsk( + _genericTakerOrder(), + makerBidToExecute, + signature, + merkleTree, + _EMPTY_AFFILIATE + ); + } + + function testTakerBidRevertsIfProofTooLarge() public { + uint256 testProofLengthUpTo = MAX_CALLDATA_PROOF_LENGTH + 3; + mockERC721.batchMint(makerUser, 2 ** testProofLengthUpTo); + + // Keep it reasonably large + for (uint256 proofLength = MAX_CALLDATA_PROOF_LENGTH + 1; proofLength <= testProofLengthUpTo; proofLength++) { + uint256 numberOrders = 2 ** proofLength; + uint256 orderIndex = numberOrders - 1; + + OrderStructs.Maker[] memory makerAsks = _createBatchMakerAsks(numberOrders); + + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( + makerUserPK, + makerAsks, + orderIndex + ); + + OrderStructs.Maker memory makerAskToExecute = makerAsks[orderIndex]; + + // Verify validity + _assertMakerOrderReturnValidationCodeWithMerkleTree( + makerAskToExecute, + signature, + merkleTree, + MERKLE_PROOF_PROOF_TOO_LARGE + ); + + vm.prank(takerUser); + vm.expectRevert(abi.encodeWithSelector(MerkleProofTooLarge.selector, proofLength)); + looksRareProtocol.executeTakerBid{ value: price }( + _genericTakerOrder(), + makerAskToExecute, + signature, + merkleTree, + _EMPTY_AFFILIATE + ); + } + } + + function testTakerAskRevertsIfProofTooLarge() public { + uint256 testProofLengthUpTo = MAX_CALLDATA_PROOF_LENGTH + 3; + mockERC721.batchMint(takerUser, 2 ** testProofLengthUpTo); + + // Keep it reasonably large + for (uint256 proofLength = MAX_CALLDATA_PROOF_LENGTH + 1; proofLength <= testProofLengthUpTo; proofLength++) { + uint256 numberOrders = 2 ** proofLength; + uint256 orderIndex = numberOrders - 1; + + OrderStructs.Maker[] memory makerBids = _createBatchMakerBids(numberOrders); + + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( + makerUserPK, + makerBids, + orderIndex + ); + + OrderStructs.Maker memory makerBidToExecute = makerBids[orderIndex]; + + // Verify validity + _assertMakerOrderReturnValidationCodeWithMerkleTree( + makerBidToExecute, + signature, + merkleTree, + MERKLE_PROOF_PROOF_TOO_LARGE + ); + + vm.prank(takerUser); + vm.expectRevert(abi.encodeWithSelector(MerkleProofTooLarge.selector, proofLength)); + looksRareProtocol.executeTakerBid{ value: price }( + _genericTakerOrder(), + makerBidToExecute, + signature, + merkleTree, + _EMPTY_AFFILIATE + ); + } + } + + function _createBatchMakerAsks(uint256 numberOrders) private view returns (OrderStructs.Maker[] memory makerAsks) { + makerAsks = new OrderStructs.Maker[](numberOrders); + for (uint256 i; i < numberOrders; i++) { + makerAsks[i] = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: i, // incremental + collection: address(mockERC721), + currency: ETH, + signer: makerUser, + price: price, + itemId: i + }); + } + } + + function _createBatchMakerBids(uint256 numberOrders) private view returns (OrderStructs.Maker[] memory makerBids) { + makerBids = new OrderStructs.Maker[](numberOrders); + for (uint256 i; i < numberOrders; i++) { + makerBids[i] = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: i, // incremental + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: i + }); + } + } + + function _assertMerkleTreeAssumptions(uint256 numberOrders, uint256 orderIndex) private pure { + vm.assume(numberOrders > 0 && numberOrders <= 2 ** MAX_CALLDATA_PROOF_LENGTH); + vm.assume(orderIndex < numberOrders); + } +} diff --git a/contracts/test/foundry/marketplace/BatchOrderTypehashRegistry.t.sol b/contracts/test/foundry/marketplace/BatchOrderTypehashRegistry.t.sol new file mode 100644 index 00000000..cbbf7cb3 --- /dev/null +++ b/contracts/test/foundry/marketplace/BatchOrderTypehashRegistry.t.sol @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { Test } from "forge-std/Test.sol"; + +import { BatchOrderTypehashRegistry } from "@hypercerts/marketplace/BatchOrderTypehashRegistry.sol"; + +// Shared errors +import { MerkleProofTooLarge } from "@hypercerts/marketplace/errors/SharedErrors.sol"; + +contract BatchOrderTypehashRegistryInheriter is BatchOrderTypehashRegistry { + function getBatchOrderTypehash(uint256 height) external pure returns (bytes32 typehash) { + return _getBatchOrderTypehash(height); + } +} + +contract BatchOrderTypehashRegistryTest is Test { + function testHash() public { + BatchOrderTypehashRegistryInheriter registry = new BatchOrderTypehashRegistryInheriter(); + bytes32 root = hex"6942000000000000000000000000000000000000000000000000000000000000"; + assertEq( + registry.hashBatchOrder(root, 1), + hex"8f0c85a215cff55fe39cf62ee7a1e0b5205a8ade02ff12ffee9ece02d626ffc3" + ); + assertEq( + registry.hashBatchOrder(root, 2), + hex"f04a7d8a4688cf084b00b51ed583de7e5a19e59b073635e00a45a474899e89ec" + ); + assertEq( + registry.hashBatchOrder(root, 3), + hex"56ef3bb8c564d19cfe494776934aa5e7ed84c41ae609d5f10e726f76281dd30b" + ); + assertEq( + registry.hashBatchOrder(root, 4), + hex"2b0cb021eacab73e36d9ac9a04c1cf58589ff5bb4dc0d9b88ec29f67358ca812" + ); + assertEq( + registry.hashBatchOrder(root, 5), + hex"253b3cc8d591a8b01fc8967cefe3ac3d0e078b884d96aa589f1ffd4536921bbb" + ); + assertEq( + registry.hashBatchOrder(root, 6), + hex"7e4c4a2c5806fc4765bca325e8b78ccf9633bd1c7643144a56210293daefcbca" + ); + assertEq( + registry.hashBatchOrder(root, 7), + hex"e8e39cebe7137f0fadf6b88ba611044ac79c0168444eab66ca53bddd0c5fb717" + ); + assertEq( + registry.hashBatchOrder(root, 8), + hex"6e02f123509255ed381c7552de5e2ac1c1ea401a23e026e2452f01b70564affb" + ); + assertEq( + registry.hashBatchOrder(root, 9), + hex"7eeb4a7fe4655841fdd66f8ecfcf6cd261d50eafabbaebb10f63f5fe84ddddc9" + ); + assertEq( + registry.hashBatchOrder(root, 10), + hex"a96dee8b7b88deda5d50b55f641ca08c1ee00825eeb1db7a324f392fa0b8bb83" + ); + } + + function testGetTypehash() public { + BatchOrderTypehashRegistryInheriter registry = new BatchOrderTypehashRegistryInheriter(); + bytes memory makerOrderString = bytes( + "Maker(" + "uint8 quoteType," + "uint256 globalNonce," + "uint256 subsetNonce," + "uint256 orderNonce," + "uint256 strategyId," + "uint8 collectionType," + "address collection," + "address currency," + "address signer," + "uint256 startTime," + "uint256 endTime," + "uint256 price," + "uint256[] itemIds," + "uint256[] amounts," + "bytes additionalParameters" + ")" + ); + + assertEq( + registry.getBatchOrderTypehash(1), + keccak256(bytes.concat(bytes("BatchOrder(Maker[2] tree)"), makerOrderString)) + ); + + assertEq( + registry.getBatchOrderTypehash(2), + keccak256(bytes.concat(bytes("BatchOrder(Maker[2][2] tree)"), makerOrderString)) + ); + + assertEq( + registry.getBatchOrderTypehash(3), + keccak256(bytes.concat(bytes("BatchOrder(Maker[2][2][2] tree)"), makerOrderString)) + ); + + assertEq( + registry.getBatchOrderTypehash(4), + keccak256(bytes.concat(bytes("BatchOrder(Maker[2][2][2][2] tree)"), makerOrderString)) + ); + + assertEq( + registry.getBatchOrderTypehash(5), + keccak256(bytes.concat(bytes("BatchOrder(Maker[2][2][2][2][2] tree)"), makerOrderString)) + ); + + assertEq( + registry.getBatchOrderTypehash(6), + keccak256(bytes.concat(bytes("BatchOrder(Maker[2][2][2][2][2][2] tree)"), makerOrderString)) + ); + + assertEq( + registry.getBatchOrderTypehash(7), + keccak256(bytes.concat(bytes("BatchOrder(Maker[2][2][2][2][2][2][2] tree)"), makerOrderString)) + ); + + assertEq( + registry.getBatchOrderTypehash(8), + keccak256(bytes.concat(bytes("BatchOrder(Maker[2][2][2][2][2][2][2][2] tree)"), makerOrderString)) + ); + + assertEq( + registry.getBatchOrderTypehash(9), + keccak256(bytes.concat(bytes("BatchOrder(Maker[2][2][2][2][2][2][2][2][2] tree)"), makerOrderString)) + ); + + assertEq( + registry.getBatchOrderTypehash(10), + keccak256(bytes.concat(bytes("BatchOrder(Maker[2][2][2][2][2][2][2][2][2][2] tree)"), makerOrderString)) + ); + } + + function testGetTypehashMerkleProofTooLarge(uint256 height) public { + vm.assume(height > 10); + + BatchOrderTypehashRegistryInheriter registry = new BatchOrderTypehashRegistryInheriter(); + vm.expectRevert(abi.encodeWithSelector(MerkleProofTooLarge.selector, height)); + registry.getBatchOrderTypehash(height); + } +} diff --git a/contracts/test/foundry/marketplace/BundleTransactions.t.sol b/contracts/test/foundry/marketplace/BundleTransactions.t.sol new file mode 100644 index 00000000..c7331cd3 --- /dev/null +++ b/contracts/test/foundry/marketplace/BundleTransactions.t.sol @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Other tests +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +contract BundleTransactionsTest is ProtocolBase { + function setUp() public { + _setUp(); + } + + function testTakerAskERC721BundleNoRoyalties() public { + _setUpUsers(); + uint256 numberItemsInBundle = 5; + + ( + OrderStructs.Maker memory makerBid, + OrderStructs.Taker memory takerAsk + ) = _createMockMakerBidAndTakerAskWithBundle(address(mockERC721), address(weth), numberItemsInBundle); + + // Sign the order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Verify validity + _assertValidMakerOrder(makerBid, signature); + + // Mint the items + mockERC721.batchMint(takerUser, makerBid.itemIds); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + _assertMockERC721Ownership(makerBid.itemIds, makerUser); + + _assertSuccessfulTakerAskNoRoyalties(makerBid); + } + + function testTakerAskERC1155BundleNoRoyalties() public { + _setUpUsers(); + uint256 numberItemsInBundle = 5; + + ( + OrderStructs.Maker memory makerBid, + OrderStructs.Taker memory takerAsk + ) = _createMockMakerBidAndTakerAskWithBundle(address(mockERC1155), address(weth), numberItemsInBundle); + + // Sign the order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Verify validity + _assertValidMakerOrder(makerBid, signature); + + // Mint the items + mockERC1155.batchMint(takerUser, makerBid.itemIds, makerBid.amounts); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + for (uint256 i; i < makerBid.itemIds.length; i++) { + // Maker user has received all the assets in the bundle + assertEq(mockERC1155.balanceOf(makerUser, makerBid.itemIds[i]), makerBid.amounts[i]); + } + + _assertSuccessfulTakerAskNoRoyalties(makerBid); + } + + function testTakerAskERC721BundleWithRoyaltiesFromRegistry() public { + _setUpUsers(); + _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); + uint256 numberItemsInBundle = 5; + + ( + OrderStructs.Maker memory makerBid, + OrderStructs.Taker memory takerAsk + ) = _createMockMakerBidAndTakerAskWithBundle(address(mockERC721), address(weth), numberItemsInBundle); + + uint256 price = makerBid.price; + + // Sign the order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Verify validity + _assertValidMakerOrder(makerBid, signature); + + // Mint the items + mockERC721.batchMint(takerUser, makerBid.itemIds); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + _assertMockERC721Ownership(makerBid.itemIds, makerUser); + + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - price); + // Royalty recipient receives royalties + assertEq( + weth.balanceOf(_royaltyRecipient), + _initialWETHBalanceRoyaltyRecipient + (price * _standardRoyaltyFee) / ONE_HUNDRED_PERCENT_IN_BP + ); + assertEq( + weth.balanceOf(address(protocolFeeRecipient)), + (price * _standardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP, + "ProtocolFeeRecipient should receive protocol fee" + ); + // Taker ask user receives 99.5% of the whole price + assertEq( + weth.balanceOf(takerUser), + _initialWETHBalanceUser + (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP + ); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + function testTakerBidERC721BundleNoRoyalties() public { + _setUpUsers(); + uint256 numberItemsInBundle = 5; + + ( + OrderStructs.Maker memory makerAsk, + OrderStructs.Taker memory takerBid + ) = _createMockMakerAskAndTakerBidWithBundle(address(mockERC721), numberItemsInBundle); + + uint256 price = makerAsk.price; + + // Mint the items and sign the order + mockERC721.batchMint(makerUser, makerAsk.itemIds); + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Verify validity + _assertValidMakerOrder(makerAsk, signature); + + // Execute taker bid transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + _assertMockERC721Ownership(makerAsk.itemIds, takerUser); + + _assertSuccessfulTakerBidNoRoyalties(makerAsk); + } + + function testTakerBidERC1155BundleNoRoyalties() public { + _setUpUsers(); + uint256 numberItemsInBundle = 5; + + ( + OrderStructs.Maker memory makerAsk, + OrderStructs.Taker memory takerBid + ) = _createMockMakerAskAndTakerBidWithBundle(address(mockERC1155), numberItemsInBundle); + + uint256 price = makerAsk.price; + + // Mint the items and sign the order + mockERC1155.batchMint(makerUser, makerAsk.itemIds, makerAsk.amounts); + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Verify validity + _assertValidMakerOrder(makerAsk, signature); + + // Execute taker bid transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + for (uint256 i; i < makerAsk.itemIds.length; i++) { + // Taker user has received all the assets in the bundle + assertEq(mockERC1155.balanceOf(takerUser, makerAsk.itemIds[i]), makerAsk.amounts[i]); + } + + _assertSuccessfulTakerBidNoRoyalties(makerAsk); + } + + function testTakerBidERC721BundleWithRoyaltiesFromRegistry() public { + _setUpUsers(); + _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); + uint256 numberItemsInBundle = 5; + + ( + OrderStructs.Maker memory makerAsk, + OrderStructs.Taker memory takerBid + ) = _createMockMakerAskAndTakerBidWithBundle(address(mockERC721), numberItemsInBundle); + + uint256 price = makerAsk.price; + + // Mint the items and sign the order + mockERC721.batchMint(makerUser, makerAsk.itemIds); + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Verify validity + _assertValidMakerOrder(makerAsk, signature); + + // Execute taker bid transaction + vm.prank(takerUser); + + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + _assertMockERC721Ownership(makerAsk.itemIds, takerUser); + + // Taker bid user pays the whole price + assertEq(address(takerUser).balance, _initialETHBalanceUser - price); + // Royalty recipient receives the royalties + assertEq( + address(_royaltyRecipient).balance, + _initialETHBalanceRoyaltyRecipient + (price * _standardRoyaltyFee) / ONE_HUNDRED_PERCENT_IN_BP + ); + assertEq( + address(protocolFeeRecipient).balance, + (price * _standardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP, + "ProtocolFeeRecipient should receive protocol fee" + ); + // Maker ask user receives 99.5% of the whole price + assertEq( + address(makerUser).balance, + _initialETHBalanceUser + (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP + ); + // No leftover in the balance of the contract + assertEq(address(looksRareProtocol).balance, 0); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerAsk.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + function _assertSuccessfulTakerAskNoRoyalties(OrderStructs.Maker memory makerBid) private { + uint256 price = makerBid.price; + + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - price); + // Royalty recipient receives no royalty + assertEq(weth.balanceOf(_royaltyRecipient), _initialWETHBalanceRoyaltyRecipient); + assertEq( + weth.balanceOf(address(protocolFeeRecipient)), + (price * _minTotalFeeBp) / ONE_HUNDRED_PERCENT_IN_BP, + "ProtocolFeeRecipient should receive protocol fee" + ); + // Taker ask user receives 99.5% of the whole price (no royalties are paid) + assertEq( + weth.balanceOf(takerUser), + _initialWETHBalanceUser + (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP + ); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + function _assertSuccessfulTakerBidNoRoyalties(OrderStructs.Maker memory makerAsk) private { + uint256 price = makerAsk.price; + + // Taker bid user pays the whole price + assertEq(address(takerUser).balance, _initialETHBalanceUser - price); + // Royalty recipient receives no royalty + assertEq(address(_royaltyRecipient).balance, _initialETHBalanceRoyaltyRecipient); + assertEq( + address(protocolFeeRecipient).balance, + (price * _minTotalFeeBp) / ONE_HUNDRED_PERCENT_IN_BP, + "ProtocolFeeRecipient should receive protocol fee" + ); + // Maker ask user receives 99.5% of the whole price (no royalties are paid) + assertEq( + address(makerUser).balance, + _initialETHBalanceUser + (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP + ); + // No leftover in the balance of the contract + assertEq(address(looksRareProtocol).balance, 0); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerAsk.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } +} diff --git a/contracts/test/foundry/marketplace/CreatorFeeManagerWithRebates.t.sol b/contracts/test/foundry/marketplace/CreatorFeeManagerWithRebates.t.sol new file mode 100644 index 00000000..6a3b7ac0 --- /dev/null +++ b/contracts/test/foundry/marketplace/CreatorFeeManagerWithRebates.t.sol @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IERC721 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC721.sol"; + +import { CreatorFeeManagerWithRebates } from "@hypercerts/marketplace/CreatorFeeManagerWithRebates.sol"; + +// Libraries and interfaces +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { ICreatorFeeManager } from "@hypercerts/marketplace/interfaces/ICreatorFeeManager.sol"; +import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; + +// Shared errors +import { BUNDLE_ERC2981_NOT_SUPPORTED } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +contract CreatorFeeManagerWithRebatesTest is ProtocolBase { + function setUp() public { + _setUp(); + CreatorFeeManagerWithRebates creatorFeeManager = new CreatorFeeManagerWithRebates(address(royaltyFeeRegistry)); + vm.prank(_owner); + looksRareProtocol.updateCreatorFeeManager(address(creatorFeeManager)); + orderValidator.deriveProtocolParameters(); + } + + function _setUpRoyaltiesRegistry(uint256 fee) private { + vm.prank(_owner); + royaltyFeeRegistry.updateRoyaltyInfoForCollection( + address(mockERC721), + _royaltyRecipient, + _royaltyRecipient, + fee + ); + } + + function _testCreatorFeeRebatesArePaid(address erc721) private { + _setUpUsers(); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + erc721, + address(weth) + ); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + if (erc721 == address(mockERC721)) { + // Adjust royalties + _setUpRoyaltiesRegistry(_standardRoyaltyFee); + // Mint asset + mockERC721.mint(takerUser, makerBid.itemIds[0]); + } else if (erc721 == address(mockERC721WithRoyalties)) { + // Adjust ERC721 with royalties + mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( + makerBid.itemIds[0], + _royaltyRecipient, + _standardRoyaltyFee + ); + // Mint asset + mockERC721WithRoyalties.mint(takerUser, makerBid.itemIds[0]); + } + + _assertValidMakerOrder(makerBid, signature); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Verify ownership is transferred + assertEq(IERC721(erc721).ownerOf(makerBid.itemIds[0]), makerUser); + _assertSuccessfulTakerAsk(makerBid); + } + + function _testCreatorFeeRebatesArePaidForBundles(address erc721) private { + _setUpUsers(); + _setUpRoyaltiesRegistry(_standardRoyaltyFee); + + // Parameters + uint256 numberItemsInBundle = 5; + + // Create order + ( + OrderStructs.Maker memory makerBid, + OrderStructs.Taker memory takerAsk + ) = _createMockMakerBidAndTakerAskWithBundle(erc721, address(weth), numberItemsInBundle); + + if (erc721 == address(mockERC721)) { + // Adjust royalties + _setUpRoyaltiesRegistry(_standardRoyaltyFee); + // Mint the items + mockERC721.batchMint(takerUser, makerBid.itemIds); + } else if (erc721 == address(mockERC721WithRoyalties)) { + // Adjust ERC721 with royalties + for (uint256 i; i < makerBid.itemIds.length; i++) { + mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( + makerBid.itemIds[i], + _royaltyRecipient, + _standardRoyaltyFee + ); + } + // Mint the items + mockERC721WithRoyalties.batchMint(takerUser, makerBid.itemIds); + } + + // Sign the order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertValidMakerOrder(makerBid, signature); + + // Taker user actions + vm.prank(takerUser); + + // Execute taker ask transaction + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Verify ownership is transferred + for (uint256 i; i < makerBid.itemIds.length; i++) { + // Maker user has received all the assets in the bundle + assertEq(IERC721(erc721).ownerOf(makerBid.itemIds[i]), makerUser); + } + _assertSuccessfulTakerAsk(makerBid); + } + + function testCreatorRebatesArePaidForRoyaltyFeeManager() public { + _testCreatorFeeRebatesArePaid(address(mockERC721)); + } + + function testCreatorRebatesArePaidForERC2981() public { + _testCreatorFeeRebatesArePaid(address(mockERC721WithRoyalties)); + } + + function testCreatorRebatesArePaidForRoyaltyFeeManagerWithBundles() public { + _testCreatorFeeRebatesArePaidForBundles(address(mockERC721)); + } + + function testCreatorRoyaltiesGetPaidForERC2981WithBundles() public { + _testCreatorFeeRebatesArePaidForBundles(address(mockERC721WithRoyalties)); + } + + function testCreatorRoyaltiesRevertForEIP2981WithBundlesIfInfoDiffer() public { + _setUpUsers(); + + uint256 numberItemsInBundle = 5; + + ( + OrderStructs.Maker memory makerBid, + OrderStructs.Taker memory takerAsk + ) = _createMockMakerBidAndTakerAskWithBundle( + address(mockERC721WithRoyalties), + address(weth), + numberItemsInBundle + ); + + // Sign the order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint the items + mockERC721WithRoyalties.batchMint(takerUser, makerBid.itemIds); + + _assertValidMakerOrder(makerBid, signature); + + /** + * Different recipient + */ + + // Adjust ERC721 with royalties + for (uint256 i; i < makerBid.itemIds.length; i++) { + mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( + makerBid.itemIds[i], + i == 0 ? _royaltyRecipient : address(50), + 50 + ); + } + + _assertMakerOrderReturnValidationCode(makerBid, signature, BUNDLE_ERC2981_NOT_SUPPORTED); + + vm.prank(takerUser); + vm.expectRevert( + abi.encodeWithSelector( + ICreatorFeeManager.BundleEIP2981NotAllowed.selector, + address(mockERC721WithRoyalties) + ) + ); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCreatorRoyaltiesRevertForEIP2981WithBundlesIfAtLeastOneCallReverts(uint256 revertIndex) public { + _setUpUsers(); + + uint256 numberItemsInBundle = 5; + vm.assume(revertIndex < numberItemsInBundle); + + ( + OrderStructs.Maker memory makerBid, + OrderStructs.Taker memory takerAsk + ) = _createMockMakerBidAndTakerAskWithBundle( + address(mockERC721WithRoyalties), + address(weth), + numberItemsInBundle + ); + + // Sign the order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint the items + mockERC721WithRoyalties.batchMint(takerUser, makerBid.itemIds); + + _assertValidMakerOrder(makerBid, signature); + + // Adjust ERC721 with royalties + for (uint256 i; i < makerBid.itemIds.length; i++) { + mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( + makerBid.itemIds[i], + _royaltyRecipient, + // if greater than 10,000, will revert in royaltyInfo + i == revertIndex ? 10_001 : 50 + ); + } + + _assertMakerOrderReturnValidationCode(makerBid, signature, BUNDLE_ERC2981_NOT_SUPPORTED); + + vm.prank(takerUser); + vm.expectRevert( + abi.encodeWithSelector( + ICreatorFeeManager.BundleEIP2981NotAllowed.selector, + address(mockERC721WithRoyalties) + ) + ); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function _assertSuccessfulTakerAsk(OrderStructs.Maker memory makerBid) private { + uint256 price = makerBid.price; + + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - price); + assertEq( + weth.balanceOf(address(protocolFeeRecipient)), + (price * _standardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP, + "Protocol fee recipient should receive 0.5% of the whole price" + ); + assertEq( + weth.balanceOf(takerUser), + _initialWETHBalanceUser + (price * 9_900) / ONE_HUNDRED_PERCENT_IN_BP, + "Taker ask user should receive 99% of the whole price" + ); + assertEq( + weth.balanceOf(_royaltyRecipient), + _initialWETHBalanceRoyaltyRecipient + (price * 50) / ONE_HUNDRED_PERCENT_IN_BP, + "Royalty recipient receives 0.5% of the whole price" + ); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } +} diff --git a/contracts/test/foundry/marketplace/CreatorFeeManagerWithRoyalties.t.sol b/contracts/test/foundry/marketplace/CreatorFeeManagerWithRoyalties.t.sol new file mode 100644 index 00000000..d4fea298 --- /dev/null +++ b/contracts/test/foundry/marketplace/CreatorFeeManagerWithRoyalties.t.sol @@ -0,0 +1,402 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries and interfaces +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { ICreatorFeeManager } from "@hypercerts/marketplace/interfaces/ICreatorFeeManager.sol"; +import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; + +// Core contract +import { CreatorFeeManagerWithRoyalties } from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; + +// Shared errors +import { BUNDLE_ERC2981_NOT_SUPPORTED, CREATOR_FEE_TOO_HIGH } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { + CreatorFeeManagerWithRoyalties public creatorFeeManagerWithRoyalties; + + // New protocol fee + uint16 internal constant _newProtocolFee = 200; + + // New creator royalty fee + uint256 internal constant _newCreatorRoyaltyFee = 300; + + function _setUpRoyaltiesRegistry(uint256 fee) internal { + vm.prank(_owner); + royaltyFeeRegistry.updateRoyaltyInfoForCollection( + address(mockERC721), + _royaltyRecipient, + _royaltyRecipient, + fee + ); + } + + function setUp() public { + _setUp(); + creatorFeeManagerWithRoyalties = new CreatorFeeManagerWithRoyalties(address(royaltyFeeRegistry)); + vm.startPrank(_owner); + looksRareProtocol.updateCreatorFeeManager(address(creatorFeeManagerWithRoyalties)); + // Set up 2% as protocol fee, which is now equal to minimum fee + looksRareProtocol.updateStrategy(0, true, _newProtocolFee, _newProtocolFee); + vm.stopPrank(); + + // Adjust for new creator fee manager + orderValidator.deriveProtocolParameters(); + } + + function testCreatorRoyaltiesGetPaidForRoyaltyFeeManager() public { + _setUpUsers(); + + // Adjust royalties + _setUpRoyaltiesRegistry(_newCreatorRoyaltyFee); + + (OrderStructs.Maker memory makerBid, ) = _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint asset + mockERC721.mint(takerUser, makerBid.itemIds[0]); + + _assertValidMakerOrder(makerBid, signature); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk( + _genericTakerOrder(), + makerBid, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + // Taker user has received the asset + assertEq(mockERC721.ownerOf(makerBid.itemIds[0]), makerUser); + _assertSuccessfulTakerAsk(makerBid); + } + + function testCreatorRoyaltiesGetPaidForERC2981() public { + _setUpUsers(); + + (OrderStructs.Maker memory makerBid, ) = _createMockMakerBidAndTakerAsk( + address(mockERC721WithRoyalties), + address(weth) + ); + + // Adjust ERC721 with royalties + mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( + makerBid.itemIds[0], + _royaltyRecipient, + _newCreatorRoyaltyFee + ); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint asset + mockERC721WithRoyalties.mint(takerUser, makerBid.itemIds[0]); + + _assertValidMakerOrder(makerBid, signature); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk( + _genericTakerOrder(), + makerBid, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + // Taker user has received the asset + assertEq(mockERC721WithRoyalties.ownerOf(makerBid.itemIds[0]), makerUser); + _assertSuccessfulTakerAsk(makerBid); + } + + function testCreatorRoyaltiesGetPaidForRoyaltyFeeManagerWithBundles() public { + _setUpUsers(); + + // Adjust royalties + _setUpRoyaltiesRegistry(_newCreatorRoyaltyFee); + + uint256 numberItemsInBundle = 5; + + ( + OrderStructs.Maker memory makerBid, + OrderStructs.Taker memory takerAsk + ) = _createMockMakerBidAndTakerAskWithBundle(address(mockERC721), address(weth), numberItemsInBundle); + + // Sign the order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint the items + mockERC721.batchMint(takerUser, makerBid.itemIds); + + // Check order validity + _assertValidMakerOrder(makerBid, signature); + + // Taker user actions + vm.prank(takerUser); + + // Execute taker ask transaction + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + _assertMockERC721Ownership(makerBid.itemIds, makerUser); + + _assertSuccessfulTakerAskBundle(makerBid); + } + + function testCreatorRoyaltiesGetPaidForERC2981WithBundles() public { + _setUpUsers(); + + uint256 numberItemsInBundle = 5; + + ( + OrderStructs.Maker memory makerBid, + OrderStructs.Taker memory takerAsk + ) = _createMockMakerBidAndTakerAskWithBundle( + address(mockERC721WithRoyalties), + address(weth), + numberItemsInBundle + ); + + // Sign the order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint the items + mockERC721WithRoyalties.batchMint(takerUser, makerBid.itemIds); + + // Adjust ERC721 with royalties + for (uint256 i; i < makerBid.itemIds.length; i++) { + mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( + makerBid.itemIds[i], + _royaltyRecipient, + _newCreatorRoyaltyFee + ); + } + + _assertValidMakerOrder(makerBid, signature); + + // Taker user actions + vm.prank(takerUser); + + // Execute taker ask transaction + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + _assertSuccessfulTakerAskBundle(makerBid); + } + + function testCreatorRoyaltiesRevertForEIP2981WithBundlesIfInfoDiffer() public { + _setUpUsers(); + + uint256 numberItemsInBundle = 5; + + ( + OrderStructs.Maker memory makerBid, + OrderStructs.Taker memory takerAsk + ) = _createMockMakerBidAndTakerAskWithBundle( + address(mockERC721WithRoyalties), + address(weth), + numberItemsInBundle + ); + + // Sign the order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint the items + mockERC721WithRoyalties.batchMint(takerUser, makerBid.itemIds); + + /** + * 1. Different fee structure but same recipient + */ + + // Adjust ERC721 with royalties + for (uint256 i; i < makerBid.itemIds.length; i++) { + mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( + makerBid.itemIds[i], + _royaltyRecipient, + _newCreatorRoyaltyFee - i // It is not equal + ); + } + + _assertMakerOrderReturnValidationCode(makerBid, signature, BUNDLE_ERC2981_NOT_SUPPORTED); + + // Taker user action should revert + vm.prank(takerUser); + vm.expectRevert( + abi.encodeWithSelector( + ICreatorFeeManager.BundleEIP2981NotAllowed.selector, + address(mockERC721WithRoyalties) + ) + ); + + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + /** + * 2. Same fee structure but different recipient + */ + // Adjust ERC721 with royalties + for (uint256 i; i < makerBid.itemIds.length; i++) { + mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( + makerBid.itemIds[i], + i == 0 ? _royaltyRecipient : address(50), + _newCreatorRoyaltyFee + ); + } + + _assertMakerOrderReturnValidationCode(makerBid, signature, BUNDLE_ERC2981_NOT_SUPPORTED); + + vm.prank(takerUser); + vm.expectRevert( + abi.encodeWithSelector( + ICreatorFeeManager.BundleEIP2981NotAllowed.selector, + address(mockERC721WithRoyalties) + ) + ); + + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCreatorRoyaltiesRevertForEIP2981WithBundlesIfAtLeastOneCallReverts(uint256 revertIndex) public { + _setUpUsers(); + + uint256 numberItemsInBundle = 5; + vm.assume(revertIndex < numberItemsInBundle); + + ( + OrderStructs.Maker memory makerBid, + OrderStructs.Taker memory takerAsk + ) = _createMockMakerBidAndTakerAskWithBundle( + address(mockERC721WithRoyalties), + address(weth), + numberItemsInBundle + ); + + // Sign the order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint the items + mockERC721WithRoyalties.batchMint(takerUser, makerBid.itemIds); + + // Adjust ERC721 with royalties + for (uint256 i; i < makerBid.itemIds.length; i++) { + mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( + makerBid.itemIds[i], + _royaltyRecipient, + // if greater than 10,000, will revert in royaltyInfo + i == revertIndex ? 10_001 : _newCreatorRoyaltyFee + ); + } + + _assertMakerOrderReturnValidationCode(makerBid, signature, BUNDLE_ERC2981_NOT_SUPPORTED); + + // Taker user action should revert + vm.prank(takerUser); + vm.expectRevert( + abi.encodeWithSelector( + ICreatorFeeManager.BundleEIP2981NotAllowed.selector, + address(mockERC721WithRoyalties) + ) + ); + + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCreatorRoyaltiesRevertIfFeeHigherThanLimit() public { + _setUpUsers(); + uint256 _creatorRoyaltyFeeTooHigh = looksRareProtocol.maxCreatorFeeBp() + 1; + + // Adjust royalties + _setUpRoyaltiesRegistry(_creatorRoyaltyFeeTooHigh); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint asset + mockERC721.mint(takerUser, makerBid.itemIds[0]); + + _assertMakerOrderReturnValidationCode(makerBid, signature, CREATOR_FEE_TOO_HIGH); + + vm.expectRevert(IExecutionManager.CreatorFeeBpTooHigh.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // 2. Maker ask + + // Mint asset + mockERC721.mint(makerUser, 1); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + // The itemId changes as it is already minted before + makerAsk.itemIds[0] = 1; + + signature = _signMakerOrder(makerAsk, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, CREATOR_FEE_TOO_HIGH); + + vm.expectRevert(IExecutionManager.CreatorFeeBpTooHigh.selector); + vm.prank(takerUser); + + looksRareProtocol.executeTakerBid{ value: 1 ether }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function _assertSuccessfulTakerAsk(OrderStructs.Maker memory makerBid) private { + uint256 price = makerBid.price; + + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - price); + assertEq( + weth.balanceOf(address(protocolFeeRecipient)), + (price * _newProtocolFee) / ONE_HUNDRED_PERCENT_IN_BP, + "ProtocolFeeRecipient should receive 2% of the whole price" + ); + // Taker ask user receives 95% of the whole price + assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser + (price * 9_500) / ONE_HUNDRED_PERCENT_IN_BP); + // Royalty recipient receives 3% of the whole price + assertEq( + weth.balanceOf(_royaltyRecipient), + _initialWETHBalanceRoyaltyRecipient + (price * _newCreatorRoyaltyFee) / ONE_HUNDRED_PERCENT_IN_BP + ); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + function _assertSuccessfulTakerAskBundle(OrderStructs.Maker memory makerBid) private { + uint256 price = makerBid.price; + + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - price); + // Royalty recipient receives royalties + assertEq( + weth.balanceOf(_royaltyRecipient), + _initialWETHBalanceRoyaltyRecipient + (price * _newCreatorRoyaltyFee) / ONE_HUNDRED_PERCENT_IN_BP + ); + assertEq( + weth.balanceOf(address(protocolFeeRecipient)), + (price * _newProtocolFee) / ONE_HUNDRED_PERCENT_IN_BP, + "ProtocolFeeRecipient should receive protocol fee" + ); + // Taker ask user receives 95% of the whole price + assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser + (price * 9_500) / ONE_HUNDRED_PERCENT_IN_BP); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } +} diff --git a/contracts/test/foundry/marketplace/CurrencyManager.t.sol b/contracts/test/foundry/marketplace/CurrencyManager.t.sol new file mode 100644 index 00000000..3b00915a --- /dev/null +++ b/contracts/test/foundry/marketplace/CurrencyManager.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; + +// Core contracts +import { CurrencyManager, ICurrencyManager } from "@hypercerts/marketplace/CurrencyManager.sol"; + +// Other mocks and utils +import { TestHelpers } from "./utils/TestHelpers.sol"; +import { TestParameters } from "./utils/TestParameters.sol"; +import { MockERC20 } from "../../mock/MockERC20.sol"; + +contract CurrencyManagerTest is TestHelpers, TestParameters, ICurrencyManager { + CurrencyManager private currencyManager; + MockERC20 private mockERC20; + + function setUp() public asPrankedUser(_owner) { + currencyManager = new CurrencyManager(_owner); + mockERC20 = new MockERC20(); + } + + function testUpdateCurrencyStatus() public asPrankedUser(_owner) { + // Set to true + vm.expectEmit(true, false, false, true); + emit CurrencyStatusUpdated(address(mockERC20), true); + currencyManager.updateCurrencyStatus(address(mockERC20), true); + assertTrue(currencyManager.isCurrencyAllowed(address(mockERC20))); + + // Set to false + vm.expectEmit(true, false, false, true); + emit CurrencyStatusUpdated(address(mockERC20), false); + currencyManager.updateCurrencyStatus(address(mockERC20), false); + assertFalse(currencyManager.isCurrencyAllowed(address(mockERC20))); + } + + function testUpdateCurrencyStatusNotOwner() public { + vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); + currencyManager.updateCurrencyStatus(address(mockERC20), true); + } +} diff --git a/contracts/test/foundry/marketplace/DelegationRecipientsTaker.t.sol b/contracts/test/foundry/marketplace/DelegationRecipientsTaker.t.sol new file mode 100644 index 00000000..b052c146 --- /dev/null +++ b/contracts/test/foundry/marketplace/DelegationRecipientsTaker.t.sol @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries and interfaces +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { CreatorFeeManagerWithRoyalties } from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +contract DelegationRecipientsTakerTest is ProtocolBase { + function setUp() public { + _setUp(); + CreatorFeeManagerWithRoyalties creatorFeeManager = new CreatorFeeManagerWithRoyalties( + address(royaltyFeeRegistry) + ); + vm.prank(_owner); + looksRareProtocol.updateCreatorFeeManager(address(creatorFeeManager)); + } + + // Fixed price of sale + uint256 private constant price = 1 ether; + + /** + * One ERC721 is sold through a taker ask using WETH and the proceeds of the sale goes to a random recipient. + */ + function testTakerAskERC721WithRoyaltiesFromRegistryWithDelegation() public { + _setUpUsers(); + _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); + address randomRecipientSaleProceeds = address(420); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint asset + mockERC721.mint(takerUser, makerBid.itemIds[0]); + + // Adjust recipient + takerAsk.recipient = randomRecipientSaleProceeds; + + // Verify maker bid order + _assertValidMakerOrder(makerBid, signature); + + // Arrays for events + address[2] memory expectedRecipients; + expectedRecipients[0] = randomRecipientSaleProceeds; + expectedRecipients[1] = _royaltyRecipient; + + uint256[3] memory expectedFees; + expectedFees[2] = (price * _standardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; + expectedFees[1] = (price * _standardRoyaltyFee) / ONE_HUNDRED_PERCENT_IN_BP; + expectedFees[0] = price - (expectedFees[1] + expectedFees[2]); + + vm.prank(takerUser); + vm.expectEmit(true, false, false, true); + + emit TakerAsk( + NonceInvalidationParameters({ + orderHash: _computeOrderHash(makerBid), + orderNonce: makerBid.orderNonce, + isNonceInvalidated: true + }), + takerUser, + makerUser, + makerBid.strategyId, + makerBid.currency, + makerBid.collection, + makerBid.itemIds, + makerBid.amounts, + expectedRecipients, + expectedFees + ); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Taker user has received the asset + assertEq(mockERC721.ownerOf(makerBid.itemIds[0]), makerUser); + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - price); + // Random recipient user receives 99.5% of the whole price and taker user receives nothing. + assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser); + assertEq( + weth.balanceOf(randomRecipientSaleProceeds), + (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP + ); + // Royalty recipient receives 0.5% of the whole price + assertEq( + weth.balanceOf(_royaltyRecipient), + _initialWETHBalanceRoyaltyRecipient + (price * _standardRoyaltyFee) / ONE_HUNDRED_PERCENT_IN_BP + ); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + /** + * One ERC721 is sold through a taker bid and the NFT transfer goes to a random recipient. + */ + function testTakerBidERC721WithRoyaltiesFromRegistryWithDelegation() public { + address randomRecipientNFT = address(420); + + _setUpUsers(); + _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + + // Mint asset + mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Adjust recipient to random recipient + takerBid.recipient = randomRecipientNFT; + + // Verify validity of maker ask order + _assertValidMakerOrder(makerAsk, signature); + + // Arrays for events + address[2] memory expectedRecipients; + expectedRecipients[0] = makerUser; + expectedRecipients[1] = _royaltyRecipient; + + uint256[3] memory expectedFees; + expectedFees[0] = price - (expectedFees[1] + expectedFees[0]); + expectedFees[1] = (price * _standardRoyaltyFee) / ONE_HUNDRED_PERCENT_IN_BP; + expectedFees[2] = (price * _standardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; + + vm.prank(takerUser); + + emit TakerBid( + NonceInvalidationParameters({ + orderHash: _computeOrderHash(makerAsk), + orderNonce: makerAsk.orderNonce, + isNonceInvalidated: true + }), + takerUser, + randomRecipientNFT, + makerAsk.strategyId, + makerAsk.currency, + makerAsk.collection, + makerAsk.itemIds, + makerAsk.amounts, + expectedRecipients, + expectedFees + ); + + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + // Random recipient user has received the asset + assertEq(mockERC721.ownerOf(makerAsk.itemIds[0]), randomRecipientNFT); + // Taker bid user pays the whole price + assertEq(address(takerUser).balance, _initialETHBalanceUser - price); + // Maker ask user receives 99.5% of the whole price + assertEq( + address(makerUser).balance, + _initialETHBalanceUser + (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP + ); + // Royalty recipient receives 0.5% of the whole price + assertEq( + address(_royaltyRecipient).balance, + _initialETHBalanceRoyaltyRecipient + (price * _standardRoyaltyFee) / ONE_HUNDRED_PERCENT_IN_BP + ); + // No leftover in the balance of the contract + assertEq(address(looksRareProtocol).balance, 0); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerAsk.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } +} diff --git a/contracts/test/foundry/marketplace/DomainSeparatorUpdates.t.sol b/contracts/test/foundry/marketplace/DomainSeparatorUpdates.t.sol new file mode 100644 index 00000000..3936ba5a --- /dev/null +++ b/contracts/test/foundry/marketplace/DomainSeparatorUpdates.t.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; +import { SignatureEOAInvalid } from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; + +// Libraries and interfaces +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { ILooksRareProtocol } from "@hypercerts/marketplace/interfaces/ILooksRareProtocol.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +contract DomainSeparatorUpdatesTest is ProtocolBase { + function setUp() public { + _setUp(); + } + + function testUpdateDomainSeparator(uint64 newChainId) public asPrankedUser(_owner) { + vm.assume(newChainId != block.chainid); + + vm.chainId(newChainId); + vm.expectEmit(true, false, false, true); + emit NewDomainSeparator(); + looksRareProtocol.updateDomainSeparator(); + assertEq(looksRareProtocol.chainId(), newChainId); + assertEq( + looksRareProtocol.domainSeparator(), + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256("LooksRareProtocol"), + keccak256(bytes("2")), + newChainId, + address(looksRareProtocol) + ) + ) + ); + } + + function testCannotTradeIfDomainSeparatorHasBeenUpdated(uint64 newChainId) public { + vm.assume(newChainId != block.chainid); + + _setUpUsers(); + + // ChainId update + vm.chainId(newChainId); + + // Owner updates the domain separator + vm.prank(_owner); + looksRareProtocol.updateDomainSeparator(); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Mint asset + mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + vm.prank(takerUser); + vm.expectRevert(SignatureEOAInvalid.selector); + looksRareProtocol.executeTakerBid{ value: makerAsk.price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testCannotTradeIfChainIdHasChanged(uint64 newChainId) public { + vm.assume(newChainId != block.chainid); + + _setUpUsers(); + + // ChainId update + vm.chainId(newChainId); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Mint asset + mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + vm.prank(takerUser); + vm.expectRevert(ILooksRareProtocol.ChainIdInvalid.selector); + looksRareProtocol.executeTakerBid{ value: makerAsk.price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testUpdateDomainSeparatorSameDomainSeparator() public asPrankedUser(_owner) { + vm.expectRevert(SameDomainSeparator.selector); + looksRareProtocol.updateDomainSeparator(); + } + + function testUpdateDomainSeparatorNotOwner() public { + vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); + looksRareProtocol.updateDomainSeparator(); + } +} diff --git a/contracts/test/foundry/marketplace/ExecutionManager.t.sol b/contracts/test/foundry/marketplace/ExecutionManager.t.sol new file mode 100644 index 00000000..edc413af --- /dev/null +++ b/contracts/test/foundry/marketplace/ExecutionManager.t.sol @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; + +// Libraries and interfaces +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; + +// Shared errors +import { OrderInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { MAKER_ORDER_INVALID_STANDARD_SALE, STRATEGY_INVALID_QUOTE_TYPE, STRATEGY_INVALID_QUOTE_TYPE, STRATEGY_NOT_ACTIVE, START_TIME_GREATER_THAN_END_TIME, TOO_LATE_TO_EXECUTE_ORDER, TOO_EARLY_TO_EXECUTE_ORDER } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManager { + function setUp() public { + _setUp(); + } + + function testUpdateCreatorFeeManager() public asPrankedUser(_owner) { + vm.expectEmit(true, false, false, true); + emit NewCreatorFeeManager(address(1)); + looksRareProtocol.updateCreatorFeeManager(address(1)); + assertEq(address(looksRareProtocol.creatorFeeManager()), address(1)); + } + + function testUpdateCreatorFeeManagerNotOwner() public { + vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); + looksRareProtocol.updateCreatorFeeManager(address(1)); + } + + function testUpdateMaxCreatorFeeBp(uint16 newMaxCreatorFeeBp) public asPrankedUser(_owner) { + vm.assume(newMaxCreatorFeeBp <= 2_500); + vm.expectEmit(true, false, false, true); + emit NewMaxCreatorFeeBp(newMaxCreatorFeeBp); + looksRareProtocol.updateMaxCreatorFeeBp(newMaxCreatorFeeBp); + assertEq(looksRareProtocol.maxCreatorFeeBp(), newMaxCreatorFeeBp); + } + + function testUpdateMaxCreatorFeeBpNotOwner() public { + vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); + looksRareProtocol.updateMaxCreatorFeeBp(uint16(2_500)); + } + + function testUpdateMaxCreatorFeeBpTooHigh(uint16 newMaxCreatorFeeBp) public asPrankedUser(_owner) { + vm.assume(newMaxCreatorFeeBp > 2_500); + vm.expectRevert(CreatorFeeBpTooHigh.selector); + looksRareProtocol.updateMaxCreatorFeeBp(newMaxCreatorFeeBp); + } + + function testUpdateProtocolFeeRecipient() public asPrankedUser(_owner) { + vm.expectEmit(true, false, false, true); + emit NewProtocolFeeRecipient(address(1)); + looksRareProtocol.updateProtocolFeeRecipient(address(1)); + assertEq(looksRareProtocol.protocolFeeRecipient(), address(1)); + } + + function testUpdateProtocolFeeRecipientCannotBeNullAddress() public asPrankedUser(_owner) { + vm.expectRevert(IExecutionManager.NewProtocolFeeRecipientCannotBeNullAddress.selector); + looksRareProtocol.updateProtocolFeeRecipient(address(0)); + } + + function testUpdateProtocolFeeRecipientNotOwner() public { + vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); + looksRareProtocol.updateProtocolFeeRecipient(address(1)); + } + + function testCannotValidateOrderIfTooEarlyToExecute(uint256 timestamp) public asPrankedUser(takerUser) { + // 300 because because it is deducted by 5 minutes + 1 second + vm.assume(timestamp > 300 && timestamp < type(uint256).max); + // Change timestamp to avoid underflow issues + vm.warp(timestamp); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + makerBid.startTime = block.timestamp; + makerBid.endTime = block.timestamp + 1 seconds; + + // Maker bid is valid if its start time is within 5 minutes into the future + vm.warp(makerBid.startTime - 5 minutes); + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + _assertMakerOrderReturnValidationCode(makerBid, signature, TOO_EARLY_TO_EXECUTE_ORDER); + + // Maker bid is invalid if its start time is not within 5 minutes into the future + vm.warp(makerBid.startTime - 5 minutes - 1 seconds); + vm.expectRevert(OutsideOfTimeRange.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCannotValidateOrderIfTooLateToExecute(uint256 timestamp) public asPrankedUser(takerUser) { + vm.assume(timestamp > 0 && timestamp < type(uint256).max); + // Change timestamp to avoid underflow issues + vm.warp(timestamp); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + makerBid.startTime = block.timestamp - 1 seconds; + makerBid.endTime = block.timestamp; + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + vm.warp(block.timestamp); + _assertMakerOrderReturnValidationCode(makerBid, signature, TOO_LATE_TO_EXECUTE_ORDER); + + vm.warp(block.timestamp + 1 seconds); + vm.expectRevert(OutsideOfTimeRange.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCannotValidateOrderIfStartTimeLaterThanEndTime(uint256 timestamp) public asPrankedUser(takerUser) { + vm.assume(timestamp < type(uint256).max); + // Change timestamp to avoid underflow issues + vm.warp(timestamp); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + makerBid.startTime = block.timestamp + 1 seconds; + makerBid.endTime = block.timestamp; + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerBid, signature, START_TIME_GREATER_THAN_END_TIME); + + vm.expectRevert(OutsideOfTimeRange.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCannotValidateOrderIfMakerBidItemIdsIsEmpty() public { + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + uint256[] memory itemIds = new uint256[](0); + makerBid.itemIds = itemIds; + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_INVALID_STANDARD_SALE); + + vm.expectRevert(OrderInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCannotValidateOrderIfMakerBidItemIdsLengthMismatch( + uint256 makerBidItemIdsLength + ) public asPrankedUser(takerUser) { + vm.assume(makerBidItemIdsLength > 1 && makerBidItemIdsLength < 100_000); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + uint256[] memory itemIds = new uint256[](makerBidItemIdsLength); + makerBid.itemIds = itemIds; + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_INVALID_STANDARD_SALE); + + vm.expectRevert(OrderInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCannotValidateOrderIfMakerAskItemIdsIsEmpty() public asPrankedUser(takerUser) { + vm.deal(takerUser, 100 ether); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + + // Change maker itemIds array to make its length equal to 0 + uint256[] memory itemIds = new uint256[](0); + makerAsk.itemIds = itemIds; + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_INVALID_STANDARD_SALE); + + vm.expectRevert(OrderInvalid.selector); + looksRareProtocol.executeTakerBid{ value: makerAsk.price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testCannotValidateOrderIfMakerAskItemIdsLengthMismatch( + uint256 makerAskItemIdsLength + ) public asPrankedUser(takerUser) { + vm.deal(takerUser, 100 ether); + + vm.assume(makerAskItemIdsLength > 1 && makerAskItemIdsLength < 100_000); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + + uint256[] memory itemIds = new uint256[](makerAskItemIdsLength); + makerAsk.itemIds = itemIds; + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_INVALID_STANDARD_SALE); + + vm.expectRevert(OrderInvalid.selector); + looksRareProtocol.executeTakerBid{ value: makerAsk.price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + // TODO check is we need this test and replace the chainlink floor strategy + // function testCannotExecuteTransactionIfMakerBidWithStrategyForMakerAsk() public { + // _setUpUsers(); + + // vm.prank(_owner); + // StrategyChainlinkFloor strategy = new StrategyChainlinkFloor(_owner, address(weth)); + + // bool isMakerBid = true; + // vm.prank(_owner); + // looksRareProtocol.addStrategy( + // 250, + // 250, + // 300, + // StrategyChainlinkFloor.executeBasisPointsDiscountCollectionOfferStrategyWithTakerAsk.selector, + // isMakerBid, + // address(strategy) + // ); + + // (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + // _createMockMakerAskAndTakerBid(address(mockERC721)); + // makerAsk.strategyId = 1; // Fake strategy + + // bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // // Mint asset + // mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + // _assertMakerOrderReturnValidationCode(makerAsk, signature, STRATEGY_INVALID_QUOTE_TYPE); + + // vm.prank(takerUser); + // vm.expectRevert(IExecutionManager.NoSelectorForStrategy.selector); + // looksRareProtocol.executeTakerBid{value: makerAsk.price}( + // takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE + // ); + // } + + // TODO check is we need this test and replace the chainlink floor strategy + // function testCannotExecuteTransactionIfMakerAskWithStrategyForMakerBid() public { + // _setUpUsers(); + + // vm.prank(_owner); + // StrategyChainlinkFloor strategy = new StrategyChainlinkFloor(_owner, address(weth)); + + // bool isMakerBid = false; + // vm.prank(_owner); + // // All parameters are random, including the selector and the implementation + // looksRareProtocol.addStrategy( + // 250, + // 250, + // 300, + // StrategyChainlinkFloor.executeFixedPremiumStrategyWithTakerBid.selector, + // isMakerBid, + // address(strategy) + // ); + + // (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + // _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); + // makerBid.strategyId = 1; // Fake strategy + + // bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // // Mint asset to ask user + // mockERC721.mint(takerUser, makerBid.itemIds[0]); + + // _assertMakerOrderReturnValidationCode(makerBid, signature, STRATEGY_INVALID_QUOTE_TYPE); + + // vm.prank(takerUser); + // vm.expectRevert(IExecutionManager.NoSelectorForStrategy.selector); + // looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + // } +} diff --git a/contracts/test/foundry/marketplace/GasGriefing.t.sol b/contracts/test/foundry/marketplace/GasGriefing.t.sol new file mode 100644 index 00000000..31852b5a --- /dev/null +++ b/contracts/test/foundry/marketplace/GasGriefing.t.sol @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries and interfaces +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { WETH } from "solmate/src/tokens/WETH.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Mocks and other utils +import { GasGriefer } from "./utils/GasGriefer.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract GasGriefingTest is ProtocolBase { + uint256 private constant price = 1 ether; // Fixed price of sale + address private gasGriefer; + + // WETH events + event Deposit(address indexed from, uint256 amount); + event Transfer(address indexed from, address indexed to, uint256 amount); + + function setUp() public { + _setUp(); + gasGriefer = address(new GasGriefer()); + _setUpUser(gasGriefer); + _setUpUser(takerUser); + } + + function testTakerBidGasGriefing() public { + _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + makerAsk.signer = gasGriefer; + + // Mint asset + mockERC721.mint(gasGriefer, makerAsk.itemIds[0]); + + bytes memory signature; + + uint256 sellerProceed = (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; + + vm.expectEmit(true, true, false, true); + emit Deposit(address(looksRareProtocol), sellerProceed); + + vm.expectEmit(true, true, true, true); + emit Transfer(address(looksRareProtocol), gasGriefer, sellerProceed); + + vm.prank(takerUser); + // Execute taker bid transaction + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + // Taker user has received the asset + assertEq(mockERC721.ownerOf(makerAsk.itemIds[0]), takerUser); + // Taker bid user pays the whole price + assertEq(address(takerUser).balance, _initialETHBalanceUser - price); + // Maker ask user receives 99.5% of the whole price + assertEq(weth.balanceOf(gasGriefer), _initialWETHBalanceUser + sellerProceed); + // Royalty recipient receives 0.5% of the whole price + assertEq( + address(_royaltyRecipient).balance, + _initialETHBalanceRoyaltyRecipient + (price * _standardRoyaltyFee) / ONE_HUNDRED_PERCENT_IN_BP + ); + // No leftover in the balance of the contract + assertEq(address(looksRareProtocol).balance, 0); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(gasGriefer, makerAsk.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + function testThreeTakerBidsGasGriefing() public { + uint256 numberPurchases = 3; + + OrderStructs.Maker[] memory makerAsks = new OrderStructs.Maker[](numberPurchases); + OrderStructs.Taker[] memory takerBids = new OrderStructs.Taker[](numberPurchases); + bytes[] memory signatures = new bytes[](numberPurchases); + + for (uint256 i; i < numberPurchases; i++) { + // Mint asset + mockERC721.mint(gasGriefer, i); + + makerAsks[i] = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: i, + collection: address(mockERC721), + currency: ETH, + signer: gasGriefer, + price: price, // Fixed + itemId: i // (0, 1, etc.) + }); + + takerBids[i] = _genericTakerOrder(); + } + + // Other execution parameters + OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](numberPurchases); + + uint256 sellerProceedPerItem = (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; + + vm.expectEmit(true, true, false, true); + emit Deposit(address(looksRareProtocol), sellerProceedPerItem); + + vm.expectEmit(true, true, true, true); + emit Transfer(address(looksRareProtocol), gasGriefer, sellerProceedPerItem); + + vm.prank(takerUser); + // Execute taker bid transaction + looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + + for (uint256 i; i < numberPurchases; i++) { + // Taker user has received the asset + assertEq(mockERC721.ownerOf(i), takerUser); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(gasGriefer, i), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + // Taker bid user pays the whole price + assertEq(address(takerUser).balance, _initialETHBalanceUser - (numberPurchases * price)); + // Maker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq(weth.balanceOf(gasGriefer), _initialWETHBalanceUser + sellerProceedPerItem * numberPurchases); + // No leftover in the balance of the contract + assertEq(address(looksRareProtocol).balance, 0); + } +} diff --git a/contracts/test/foundry/marketplace/InitialStates.t.sol b/contracts/test/foundry/marketplace/InitialStates.t.sol new file mode 100644 index 00000000..c17f827b --- /dev/null +++ b/contracts/test/foundry/marketplace/InitialStates.t.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Interfaces +import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +contract InitialStatesTest is ProtocolBase, IStrategyManager { + function setUp() public { + _setUp(); + } + + /** + * Verify initial post-deployment states are as expected + */ + function testInitialStates() public { + assertEq(looksRareProtocol.owner(), _owner); + assertEq(looksRareProtocol.protocolFeeRecipient(), address(protocolFeeRecipient)); + assertEq(address(looksRareProtocol.transferManager()), address(transferManager)); + assertEq(looksRareProtocol.WETH(), address(weth)); + assertEq(looksRareProtocol.chainId(), block.chainid); + + bytes32 domainSeparator = looksRareProtocol.domainSeparator(); + bytes32 expectedDomainSeparator = keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256("LooksRareProtocol"), + keccak256(bytes("2")), + block.chainid, + address(looksRareProtocol) + ) + ); + assertEq(domainSeparator, expectedDomainSeparator); + + ( + bool strategyIsActive, + uint16 strategyStandardProtocolFee, + uint16 strategyMinTotalFee, + uint16 strategyMaxProtocolFee, + bytes4 strategySelector, + bool strategyIsMakerBid, + address strategyImplementation + ) = looksRareProtocol.strategyInfo(0); + + assertTrue(strategyIsActive); + assertEq(strategyStandardProtocolFee, _standardProtocolFeeBp); + assertEq(strategyMinTotalFee, _minTotalFeeBp); + assertEq(strategyMaxProtocolFee, _maxProtocolFeeBp); + assertEq(strategySelector, _EMPTY_BYTES4); + assertFalse(strategyIsMakerBid); + assertEq(strategyImplementation, address(0)); + } +} diff --git a/contracts/test/foundry/marketplace/LooksRareProtocol.t.sol b/contracts/test/foundry/marketplace/LooksRareProtocol.t.sol new file mode 100644 index 00000000..73027c4b --- /dev/null +++ b/contracts/test/foundry/marketplace/LooksRareProtocol.t.sol @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Shared errors +import { AmountInvalid, CallerInvalid, CurrencyInvalid, OrderInvalid, QuoteTypeInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { CURRENCY_NOT_ALLOWED, MAKER_ORDER_INVALID_STANDARD_SALE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Other mocks and utils +import { MockERC20 } from "../../mock/MockERC20.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract LooksRareProtocolTest is ProtocolBase { + // Fixed price of sale + uint256 private constant price = 1 ether; + + // Mock files + MockERC20 private mockERC20; + + function setUp() public { + _setUp(); + vm.prank(_owner); + mockERC20 = new MockERC20(); + } + + function testCannotTradeIfInvalidAmounts() public { + _setUpUsers(); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + + // Mint asset + mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + // 1. Amount = 0 + makerAsk.amounts[0] = 0; + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_INVALID_STANDARD_SALE); + + vm.prank(takerUser); + vm.expectRevert(OrderInvalid.selector); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + // 2. Amount > 1 for ERC721 + makerAsk.amounts[0] = 2; + + // Sign order + signature = _signMakerOrder(makerAsk, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_INVALID_STANDARD_SALE); + + vm.prank(takerUser); + vm.expectRevert(AmountInvalid.selector); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testCannotTradeIfCurrencyInvalid() public { + _setUpUsers(); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + makerAsk.currency = address(mockERC20); + + // Mint asset + mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Verify validity of maker ask order + _assertMakerOrderReturnValidationCode(makerAsk, signature, CURRENCY_NOT_ALLOWED); + + vm.prank(takerUser); + vm.expectRevert(CurrencyInvalid.selector); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + OrderStructs.Maker[] memory makerAsks = new OrderStructs.Maker[](1); + OrderStructs.Taker[] memory takerBids = new OrderStructs.Taker[](1); + bytes[] memory signatures = new bytes[](1); + OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](1); + + makerAsks[0] = makerAsk; + takerBids[0] = takerBid; + signatures[0] = signature; + + vm.prank(takerUser); + vm.expectRevert(CurrencyInvalid.selector); + looksRareProtocol.executeMultipleTakerBids{ value: price }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + true // Atomic + ); + + vm.prank(takerUser); + vm.expectRevert(CurrencyInvalid.selector); + looksRareProtocol.executeMultipleTakerBids{ value: price }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false // Non-atomic + ); + } + + function testCannotTradeIfETHIsUsedForMakerBid() public { + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + ETH + ); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Verify maker bid order + _assertMakerOrderReturnValidationCode(makerBid, signature, CURRENCY_NOT_ALLOWED); + + // Mint asset + mockERC721.mint(takerUser, makerBid.itemIds[0]); + + // Execute taker ask transaction + vm.prank(takerUser); + vm.expectRevert(CurrencyInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCannotTradeIfInvalidQuoteType() public { + // 1. QuoteType = BID but executeTakerBid + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + vm.prank(takerUser); + vm.expectRevert(QuoteTypeInvalid.selector); + looksRareProtocol.executeTakerBid(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // 2. QuoteType = ASK but executeTakerAsk + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + makerAsk.currency = address(weth); + + // Sign order + signature = _signMakerOrder(makerAsk, makerUserPK); + + vm.prank(takerUser); + vm.expectRevert(QuoteTypeInvalid.selector); + looksRareProtocol.executeTakerAsk(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testUpdateETHGasLimitForTransfer() public asPrankedUser(_owner) { + vm.expectEmit(true, false, false, true); + emit NewGasLimitETHTransfer(10_000); + looksRareProtocol.updateETHGasLimitForTransfer(10_000); + assertEq(uint256(vm.load(address(looksRareProtocol), bytes32(uint256(12)))), 10_000); + } + + function testUpdateETHGasLimitForTransferRevertsIfTooLow() public asPrankedUser(_owner) { + uint256 newGasLimitETHTransfer = 2_300; + vm.expectRevert(NewGasLimitETHTransferTooLow.selector); + looksRareProtocol.updateETHGasLimitForTransfer(newGasLimitETHTransfer - 1); + + looksRareProtocol.updateETHGasLimitForTransfer(newGasLimitETHTransfer); + assertEq(uint256(vm.load(address(looksRareProtocol), bytes32(uint256(12)))), newGasLimitETHTransfer); + } + + function testUpdateETHGasLimitForTransferNotOwner() public { + vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); + looksRareProtocol.updateETHGasLimitForTransfer(10_000); + } + + function testCannotCallRestrictedExecuteTakerBid() public { + _setUpUsers(); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + + // Mint asset + mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + vm.prank(takerUser); + vm.expectRevert(CallerInvalid.selector); + looksRareProtocol.restrictedExecuteTakerBid(takerBid, makerAsk, takerUser, _computeOrderHash(makerAsk)); + } + + /** + * Cannot execute two or more taker bids if the currencies are different + */ + function testCannotExecuteMultipleTakerBidsIfDifferentCurrenciesIsAtomic() public { + _testCannotExecuteMultipleTakerBidsIfDifferentCurrencies(true); + } + + function testCannotExecuteMultipleTakerBidsIfDifferentCurrenciesIsNonAtomic() public { + _testCannotExecuteMultipleTakerBidsIfDifferentCurrencies(false); + } + + function _testCannotExecuteMultipleTakerBidsIfDifferentCurrencies(bool isAtomic) public { + _setUpUsers(); + vm.prank(_owner); + looksRareProtocol.updateCurrencyStatus(address(mockERC20), true); + + uint256 numberPurchases = 2; + + OrderStructs.Maker[] memory makerAsks = new OrderStructs.Maker[](numberPurchases); + OrderStructs.Taker[] memory takerBids = new OrderStructs.Taker[](numberPurchases); + bytes[] memory signatures = new bytes[](numberPurchases); + + for (uint256 i; i < numberPurchases; i++) { + // Mint asset + mockERC721.mint(makerUser, i); + + makerAsks[i] = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: i, + collection: address(mockERC721), + currency: ETH, + signer: makerUser, + price: price, // Fixed + itemId: i // (0, 1, etc.) + }); + + if (i == 1) { + makerAsks[i].currency = address(mockERC20); + } + + // Sign order + signatures[i] = _signMakerOrder(makerAsks[i], makerUserPK); + + takerBids[i] = _genericTakerOrder(); + } + + // Other execution parameters + OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](numberPurchases); + + vm.prank(takerUser); + vm.expectRevert(CurrencyInvalid.selector); + looksRareProtocol.executeMultipleTakerBids{ value: price }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + isAtomic + ); + } +} diff --git a/contracts/test/foundry/marketplace/NonceInvalidation.t.sol b/contracts/test/foundry/marketplace/NonceInvalidation.t.sol new file mode 100644 index 00000000..594ec13a --- /dev/null +++ b/contracts/test/foundry/marketplace/NonceInvalidation.t.sol @@ -0,0 +1,374 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries, interfaces, errors +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { INonceManager } from "@hypercerts/marketplace/interfaces/INonceManager.sol"; +import { LengthsInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { INVALID_USER_GLOBAL_BID_NONCE, INVALID_USER_GLOBAL_ASK_NONCE, USER_SUBSET_NONCE_CANCELLED, USER_ORDER_NONCE_IN_EXECUTION_WITH_OTHER_HASH, USER_ORDER_NONCE_EXECUTED_OR_CANCELLED } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Other utils and tests +import { StrategyTestMultiFillCollectionOrder } from "./utils/StrategyTestMultiFillCollectionOrder.sol"; +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract NonceInvalidationTest is INonceManager, ProtocolBase { + uint256 private constant price = 1 ether; // Fixed price of sale + + function setUp() public { + _setUp(); + } + + /** + * Cannot execute an order if subset nonce is used + */ + function testCannotExecuteOrderIfSubsetNonceIsUsed(uint256 subsetNonce) public { + uint256 itemId = 420; + + // Mint asset + mockERC721.mint(makerUser, itemId); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + makerAsk.subsetNonce = subsetNonce; + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + uint256[] memory subsetNonces = new uint256[](1); + subsetNonces[0] = subsetNonce; + + vm.prank(makerUser); + vm.expectEmit(false, false, false, true); + emit SubsetNoncesCancelled(makerUser, subsetNonces); + looksRareProtocol.cancelSubsetNonces(subsetNonces); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, USER_SUBSET_NONCE_CANCELLED); + + vm.deal(takerUser, price); + + // Execute taker bid transaction + // Taker user actions + vm.prank(takerUser); + vm.expectRevert(NoncesInvalid.selector); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + /** + * Cannot execute an order if maker is at a different global ask nonce than signed + */ + function testCannotExecuteOrderIfInvalidUserGlobalAskNonce(uint256 userGlobalAskNonce) public { + uint256 quasiRandomNumber = 54570651553685478358117286254199992264; + vm.assume(userGlobalAskNonce < quasiRandomNumber); + // Change block number + vm.roll(1); + assertEq(quasiRandomNumber, uint256(blockhash(block.number - 1) >> 128)); + + uint256 newAskNonce = 0 + quasiRandomNumber; + + vm.prank(makerUser); + vm.expectEmit(false, false, false, true); + emit NewBidAskNonces(makerUser, 0, newAskNonce); + looksRareProtocol.incrementBidAskNonces(false, true); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + + // Mint asset + mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, INVALID_USER_GLOBAL_ASK_NONCE); + + vm.deal(takerUser, price); + + // Execute taker bid transaction + // Taker user actions + vm.prank(takerUser); + vm.expectRevert(NoncesInvalid.selector); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + /** + * Cannot execute an order if maker is at a different global bid nonce than signed + */ + function testCannotExecuteOrderIfInvalidUserGlobalBidNonce(uint256 userGlobalBidNonce) public { + uint256 quasiRandomNumber = 54570651553685478358117286254199992264; + vm.assume(userGlobalBidNonce < quasiRandomNumber); + // Change block number + vm.roll(1); + assertEq(quasiRandomNumber, uint256(blockhash(block.number - 1) >> 128)); + + uint256 newBidNonce = 0 + quasiRandomNumber; + + vm.prank(makerUser); + vm.expectEmit(false, false, false, true); + emit NewBidAskNonces(makerUser, newBidNonce, 0); + looksRareProtocol.incrementBidAskNonces(true, false); + + uint256 itemId = 420; + + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: userGlobalBidNonce, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: itemId + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerBid, signature, INVALID_USER_GLOBAL_BID_NONCE); + + // Mint asset + mockERC721.mint(takerUser, itemId); + + // Execute taker ask transaction + // Taker user actions + vm.prank(takerUser); + vm.expectRevert(NoncesInvalid.selector); + looksRareProtocol.executeTakerAsk( + _genericTakerOrder(), + makerBid, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + /** + * Cannot execute an order twice + */ + function testCannotExecuteAnOrderTwice() public { + _setUpUsers(); + _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint asset + mockERC721.mint(takerUser, makerBid.itemIds[0]); + + // Taker user actions + vm.startPrank(takerUser); + + { + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + _assertMakerOrderReturnValidationCode(makerBid, signature, USER_ORDER_NONCE_EXECUTED_OR_CANCELLED); + + // Second one fails + vm.expectRevert(NoncesInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + vm.stopPrank(); + } + + /** + * Cannot execute an order sharing the same order nonce as another that is being partially filled + */ + function testCannotExecuteAnotherOrderAtNonceIfExecutionIsInProgress(uint256 orderNonce) public { + _setUpUsers(); + + // 0. Add the new strategy + bytes4 selector = StrategyTestMultiFillCollectionOrder.executeStrategyWithTakerAsk.selector; + + StrategyTestMultiFillCollectionOrder strategyMultiFillCollectionOrder = new StrategyTestMultiFillCollectionOrder( + address(looksRareProtocol) + ); + + vm.prank(_owner); + _addStrategy(address(strategyMultiFillCollectionOrder), selector, true); + + // 1. Maker signs a message and execute a partial fill on it + uint256 amountsToFill = 4; + + uint256[] memory itemIds = new uint256[](0); + uint256[] memory amounts = new uint256[](1); + amounts[0] = amountsToFill; + + // Prepare the first order + OrderStructs.Maker memory makerBid = _createMultiItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, // Multi-fill bid offer + collectionType: CollectionType.ERC721, + orderNonce: orderNonce, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemIds: itemIds, + amounts: amounts + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // First taker user actions + { + itemIds = new uint256[](1); + amounts = new uint256[](1); + itemIds[0] = 0; + amounts[0] = 1; + + mockERC721.mint(takerUser, itemIds[0]); + + // Prepare the taker ask + OrderStructs.Taker memory takerAsk = OrderStructs.Taker(takerUser, abi.encode(itemIds, amounts)); + + vm.prank(takerUser); + + // Execute taker ask transaction + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + // 2. Second maker order is signed sharing the same order nonce as the first one + { + uint256 itemId = 420; + + itemIds = new uint256[](1); + amounts = new uint256[](1); + itemIds[0] = itemId; + amounts[0] = 1; + + // Prepare the second order + makerBid = _createMultiItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: orderNonce, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemIds: itemIds, + amounts: amounts + }); + + // Sign order + signature = _signMakerOrder(makerBid, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerBid, signature, USER_ORDER_NONCE_IN_EXECUTION_WITH_OTHER_HASH); + + // Prepare the taker ask + OrderStructs.Taker memory takerAsk = OrderStructs.Taker( + takerUser, + abi.encode(new uint256[](0), new uint256[](0)) + ); + + vm.prank(takerUser); + + // Second one fails when a taker user tries to execute + vm.expectRevert(NoncesInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + } + + function testCancelOrderNonces(uint256 nonceOne, uint256 nonceTwo) public asPrankedUser(makerUser) { + assertEq(looksRareProtocol.userOrderNonce(makerUser, nonceOne), bytes32(0)); + assertEq(looksRareProtocol.userOrderNonce(makerUser, nonceTwo), bytes32(0)); + + uint256[] memory orderNonces = new uint256[](2); + orderNonces[0] = nonceOne; + orderNonces[1] = nonceTwo; + vm.expectEmit(true, false, false, true); + emit OrderNoncesCancelled(makerUser, orderNonces); + looksRareProtocol.cancelOrderNonces(orderNonces); + + assertEq(looksRareProtocol.userOrderNonce(makerUser, nonceOne), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + assertEq(looksRareProtocol.userOrderNonce(makerUser, nonceTwo), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + /** + * Cannot execute an order if its nonce has been cancelled + */ + function testCannotExecuteAnOrderWhoseNonceIsCancelled(uint256 orderNonce) public { + _setUpUsers(); + _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); + + uint256 itemId = 0; + + uint256[] memory orderNonces = new uint256[](1); + orderNonces[0] = orderNonce; + vm.prank(makerUser); + looksRareProtocol.cancelOrderNonces(orderNonces); + + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: orderNonce, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: itemId + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertMakerOrderReturnValidationCode(makerBid, signature, USER_ORDER_NONCE_EXECUTED_OR_CANCELLED); + + // Mint asset + mockERC721.mint(takerUser, itemId); + + // Prepare the taker ask + OrderStructs.Taker memory takerAsk = OrderStructs.Taker( + takerUser, + abi.encode(new uint256[](0), new uint256[](0)) + ); + + vm.prank(takerUser); + vm.expectRevert(NoncesInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCancelNoncesRevertIfEmptyArrays() public { + uint256[] memory nonces = new uint256[](0); + + vm.expectRevert(LengthsInvalid.selector); + looksRareProtocol.cancelSubsetNonces(nonces); + + vm.expectRevert(LengthsInvalid.selector); + looksRareProtocol.cancelOrderNonces(nonces); + } +} diff --git a/contracts/test/foundry/marketplace/OrderValidatorV2A.t.sol b/contracts/test/foundry/marketplace/OrderValidatorV2A.t.sol new file mode 100644 index 00000000..604c9006 --- /dev/null +++ b/contracts/test/foundry/marketplace/OrderValidatorV2A.t.sol @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { LooksRareProtocol } from "@hypercerts/marketplace/LooksRareProtocol.sol"; +import { TransferManager } from "@hypercerts/marketplace/TransferManager.sol"; +import { CreatorFeeManagerWithRoyalties } from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; + +import { OrderValidatorV2A } from "@hypercerts/marketplace/helpers/OrderValidatorV2A.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Shared errors +import { ERC20_APPROVAL_INFERIOR_TO_PRICE, ERC721_ITEM_ID_NOT_IN_BALANCE, ERC721_NO_APPROVAL_FOR_ALL_OR_ITEM_ID, ERC1155_BALANCE_OF_DOES_NOT_EXIST, ERC1155_BALANCE_OF_ITEM_ID_INFERIOR_TO_AMOUNT, ERC1155_IS_APPROVED_FOR_ALL_DOES_NOT_EXIST, ERC1155_NO_APPROVAL_FOR_ALL, MAKER_ORDER_INVALID_STANDARD_SALE, MISSING_IS_VALID_SIGNATURE_FUNCTION_EIP1271, POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC721, POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC1155, STRATEGY_NOT_IMPLEMENTED, TRANSFER_MANAGER_APPROVAL_REVOKED_BY_OWNER_FOR_EXCHANGE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Utils +import { TestParameters } from "./utils/TestParameters.sol"; + +// Mocks +import { MockRoyaltyFeeRegistry } from "../../mock/MockRoyaltyFeeRegistry.sol"; +import { MockERC721 } from "../../mock/MockERC721.sol"; +import { MockERC1155 } from "../../mock/MockERC1155.sol"; +import { MockERC1155WithoutBalanceOfBatch } from "../../mock/MockERC1155WithoutBalanceOfBatch.sol"; +import { MockERC1155WithoutAnyBalanceOf } from "../../mock/MockERC1155WithoutAnyBalanceOf.sol"; +import { MockERC1155WithoutIsApprovedForAll } from "../../mock/MockERC1155WithoutIsApprovedForAll.sol"; +import { MockERC721SupportsNoInterface } from "../../mock/MockERC721SupportsNoInterface.sol"; +import { MockERC1155SupportsNoInterface } from "../../mock/MockERC1155SupportsNoInterface.sol"; +import { MockERC20 } from "../../mock/MockERC20.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +/** + * @dev Not everything is tested in this file. Most tests live in other files + * with the assert functions living in ProtocolBase.t.sol. + */ +contract OrderValidatorV2ATest is TestParameters { + CreatorFeeManagerWithRoyalties private creatorFeeManager; + LooksRareProtocol private looksRareProtocol; + MockRoyaltyFeeRegistry private royaltyFeeRegistry; + OrderValidatorV2A private orderValidator; + TransferManager private transferManager; + + function setUp() public { + transferManager = new TransferManager(address(this)); + looksRareProtocol = new LooksRareProtocol( + address(this), + address(this), + address(transferManager), + 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + ); + royaltyFeeRegistry = new MockRoyaltyFeeRegistry(address(this), 9_500); + creatorFeeManager = new CreatorFeeManagerWithRoyalties(address(royaltyFeeRegistry)); + looksRareProtocol.updateCreatorFeeManager(address(creatorFeeManager)); + looksRareProtocol.updateCurrencyStatus(ETH, true); + orderValidator = new OrderValidatorV2A(address(looksRareProtocol)); + } + + function testDeriveProtocolParameters() public { + orderValidator.deriveProtocolParameters(); + assertEq( + orderValidator.domainSeparator(), + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256("LooksRareProtocol"), + keccak256(bytes("2")), + block.chainid, + address(looksRareProtocol) + ) + ) + ); + + assertEq(address(orderValidator.creatorFeeManager()), address(creatorFeeManager)); + assertEq(orderValidator.maxCreatorFeeBp(), 1_000); + } + + function testMakerAskStrategyNotImplemented() public { + OrderStructs.Maker memory makerAsk; + makerAsk.quoteType = QuoteType.Ask; + makerAsk.strategyId = 1; + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerAsk, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[0], STRATEGY_NOT_IMPLEMENTED); + } + + function testMakerBidStrategyNotImplemented() public { + OrderStructs.Maker memory makerBid; + makerBid.quoteType = QuoteType.Bid; + address currency = address(1); // it cannot be 0 + looksRareProtocol.updateCurrencyStatus(currency, true); + makerBid.currency = currency; + makerBid.strategyId = 1; + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerBid, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[0], STRATEGY_NOT_IMPLEMENTED); + } + + function testMakerAskLooksRareProtocolIsNotAWhitelistedOperator() public { + OrderStructs.Maker memory makerAsk; + makerAsk.quoteType = QuoteType.Ask; + makerAsk.signer = makerUser; + makerAsk.collectionType = CollectionType.ERC721; + makerAsk.collection = address(new MockERC721()); + + address[] memory operators = new address[](1); + operators[0] = address(orderValidator.looksRareProtocol()); + + transferManager.allowOperator(operators[0]); + + vm.prank(makerUser); + transferManager.grantApprovals(operators); + + transferManager.removeOperator(operators[0]); + + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerAsk, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[7], TRANSFER_MANAGER_APPROVAL_REVOKED_BY_OWNER_FOR_EXCHANGE); + } + + function testMakerAskWrongCollectionTypeERC721() public { + OrderStructs.Maker memory makerAsk; + makerAsk.quoteType = QuoteType.Ask; + makerAsk.collectionType = CollectionType.ERC721; + makerAsk.collection = address(new MockERC721SupportsNoInterface()); + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerAsk, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[6], POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC721); + } + + function testMakerBidWrongCollectionTypeERC721() public { + OrderStructs.Maker memory makerBid; + makerBid.quoteType = QuoteType.Bid; + makerBid.collectionType = CollectionType.ERC721; + makerBid.collection = address(new MockERC721SupportsNoInterface()); + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerBid, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[6], POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC721); + } + + function testMakerBidZeroAmount() public { + _testMakerBidERC721InvalidAmount(0); + } + + function testMakerBidERC721AmountNotEqualToOne() public { + _testMakerBidERC721InvalidAmount(2); + } + + function _testMakerBidERC721InvalidAmount(uint256 amount) public { + OrderStructs.Maker memory makerBid; + makerBid.quoteType = QuoteType.Bid; + makerBid.collectionType = CollectionType.ERC721; + makerBid.collection = address(new MockERC721()); + uint256[] memory itemIds = new uint256[](1); + itemIds[0] = amount; + makerBid.itemIds = itemIds; + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount; + makerBid.amounts = amounts; + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerBid, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[1], MAKER_ORDER_INVALID_STANDARD_SALE); + } + + function testMakerBidMissingIsValidSignature() public { + OrderStructs.Maker memory makerBid; + // This contract does not have isValidSignature implemented + makerBid.quoteType = QuoteType.Bid; + makerBid.signer = address(this); + makerBid.collectionType = CollectionType.ERC721; + makerBid.collection = address(new MockERC721()); + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerBid, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[3], MISSING_IS_VALID_SIGNATURE_FUNCTION_EIP1271); + } + + function testMakerAskWrongCollectionTypeERC1155() public { + OrderStructs.Maker memory makerAsk; + makerAsk.collectionType = CollectionType.ERC1155; + makerAsk.collection = address(new MockERC1155SupportsNoInterface()); + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerAsk, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[6], POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC1155); + } + + function testMakerBidWrongCollectionTypeERC1155() public { + OrderStructs.Maker memory makerBid; + makerBid.quoteType = QuoteType.Bid; + makerBid.collectionType = CollectionType.ERC1155; + makerBid.collection = address(new MockERC1155SupportsNoInterface()); + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerBid, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[6], POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC1155); + } + + function testMakerBidInsufficientERC20Allowance() public { + OrderStructs.Maker memory makerBid; + makerBid.quoteType = QuoteType.Bid; + MockERC20 mockERC20 = new MockERC20(); + makerBid.collectionType = CollectionType.ERC721; + makerBid.collection = address(new MockERC721()); + makerBid.signer = makerUser; + makerBid.currency = address(mockERC20); + makerBid.collectionType = CollectionType.ERC721; + makerBid.price = 1 ether; + + mockERC20.mint(makerUser, 1 ether); + + vm.startPrank(makerUser); + mockERC20.approve(address(orderValidator.looksRareProtocol()), makerBid.price - 1 wei); + vm.stopPrank(); + + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerBid, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[5], ERC20_APPROVAL_INFERIOR_TO_PRICE); + } + + function testMakerAskERC721NotAllTokensAreApproved() public { + MockERC721 mockERC721 = new MockERC721(); + mockERC721.mint(makerUser, 0); + mockERC721.mint(makerUser, 1); + + OrderStructs.Maker memory makerAsk; + makerAsk.quoteType = QuoteType.Ask; + makerAsk.collectionType = CollectionType.ERC721; + makerAsk.collection = address(mockERC721); + makerAsk.signer = makerUser; + makerAsk.collectionType = CollectionType.ERC721; + + // Only approve token 0 but not token 1, this is to test the loop + vm.prank(makerUser); + mockERC721.approve(address(transferManager), 0); + + uint256[] memory itemIds = new uint256[](2); + itemIds[0] = 0; + itemIds[1] = 1; + makerAsk.itemIds = itemIds; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1; + amounts[1] = 1; + makerAsk.amounts = amounts; + + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerAsk, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[5], ERC721_NO_APPROVAL_FOR_ALL_OR_ITEM_ID); + } + + function testMakerAskDoesNotOwnERC721() public { + OrderStructs.Maker memory makerAsk; + makerAsk.quoteType = QuoteType.Ask; + makerAsk.collectionType = CollectionType.ERC721; + MockERC721 mockERC721 = new MockERC721(); + mockERC721.mint(address(this), 0); + makerAsk.collection = address(mockERC721); + makerAsk.signer = makerUser; + makerAsk.collectionType = CollectionType.ERC721; + uint256[] memory itemIds = new uint256[](1); + makerAsk.itemIds = itemIds; + + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerAsk, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + + assertEq(validationCodes[5], ERC721_ITEM_ID_NOT_IN_BALANCE); + } + + function testMakerAskERC1155BalanceInferiorToAmountThroughBalanceOfBatch() public { + _testMakerAskERC1155BalanceInferiorToAmount(true); + } + + function testMakerAskERC1155BalanceInferiorToAmountThroughBalanceOf() public { + _testMakerAskERC1155BalanceInferiorToAmount(false); + } + + function _testMakerAskERC1155BalanceInferiorToAmount(bool revertBalanceOfBatch) public { + address collection; + if (revertBalanceOfBatch) { + MockERC1155WithoutBalanceOfBatch mockERC1155 = new MockERC1155WithoutBalanceOfBatch(); + collection = address(mockERC1155); + } else { + MockERC1155 mockERC1155 = new MockERC1155(); + collection = address(mockERC1155); + } + + OrderStructs.Maker memory makerAsk; + makerAsk.quoteType = QuoteType.Ask; + makerAsk.collectionType = CollectionType.ERC1155; + makerAsk.collection = collection; + makerAsk.signer = makerUser; + makerAsk.collectionType = CollectionType.ERC1155; + uint256[] memory itemIds = new uint256[](1); + makerAsk.itemIds = itemIds; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1; + makerAsk.amounts = amounts; + + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerAsk, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[5], ERC1155_BALANCE_OF_ITEM_ID_INFERIOR_TO_AMOUNT); + } + + function testMakerAskERC1155BalanceOfDoesNotExist() public { + MockERC1155WithoutAnyBalanceOf mockERC1155 = new MockERC1155WithoutAnyBalanceOf(); + + OrderStructs.Maker memory makerAsk; + makerAsk.quoteType = QuoteType.Ask; + makerAsk.collectionType = CollectionType.ERC1155; + makerAsk.collection = address(mockERC1155); + makerAsk.signer = makerUser; + makerAsk.collectionType = CollectionType.ERC1155; + uint256[] memory itemIds = new uint256[](1); + makerAsk.itemIds = itemIds; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1; + makerAsk.amounts = amounts; + + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerAsk, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[5], ERC1155_BALANCE_OF_DOES_NOT_EXIST); + } + + function testMakerAskERC1155IsApprovedForAllDoesNotExist() public { + MockERC1155WithoutIsApprovedForAll mockERC1155 = new MockERC1155WithoutIsApprovedForAll(); + mockERC1155.mint({ to: makerUser, tokenId: 0, amount: 1 }); + + OrderStructs.Maker memory makerAsk; + makerAsk.quoteType = QuoteType.Ask; + makerAsk.collectionType = CollectionType.ERC1155; + makerAsk.collection = address(mockERC1155); + makerAsk.signer = makerUser; + makerAsk.collectionType = CollectionType.ERC1155; + uint256[] memory itemIds = new uint256[](1); + makerAsk.itemIds = itemIds; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1; + makerAsk.amounts = amounts; + + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerAsk, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[5], ERC1155_IS_APPROVED_FOR_ALL_DOES_NOT_EXIST); + } + + function testMakerAskERC1155IsApprovedForAllReturnsFalse() public { + MockERC1155 mockERC1155 = new MockERC1155(); + mockERC1155.mint({ to: makerUser, tokenId: 0, amount: 1 }); + + OrderStructs.Maker memory makerAsk; + makerAsk.quoteType = QuoteType.Ask; + makerAsk.collectionType = CollectionType.ERC1155; + makerAsk.collection = address(mockERC1155); + makerAsk.signer = makerUser; + makerAsk.collectionType = CollectionType.ERC1155; + uint256[] memory itemIds = new uint256[](1); + makerAsk.itemIds = itemIds; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1; + makerAsk.amounts = amounts; + + uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( + makerAsk, + new bytes(65), + _EMPTY_MERKLE_TREE + ); + assertEq(validationCodes[5], ERC1155_NO_APPROVAL_FOR_ALL); + } +} diff --git a/contracts/test/foundry/marketplace/ProtocolBase.t.sol b/contracts/test/foundry/marketplace/ProtocolBase.t.sol new file mode 100644 index 00000000..92b090fd --- /dev/null +++ b/contracts/test/foundry/marketplace/ProtocolBase.t.sol @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.7; + +// WETH +import { WETH } from "solmate/src/tokens/WETH.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Core contracts +import { LooksRareProtocol, ILooksRareProtocol } from "@hypercerts/marketplace/LooksRareProtocol.sol"; +import { TransferManager } from "@hypercerts/marketplace/TransferManager.sol"; +import { ProtocolFeeRecipient } from "@hypercerts/marketplace/ProtocolFeeRecipient.sol"; + +// Other contracts +import { OrderValidatorV2A } from "@hypercerts/marketplace/helpers/OrderValidatorV2A.sol"; + +// Mock files +import { MockERC20 } from "../../mock/MockERC20.sol"; +import { MockERC721 } from "../../mock/MockERC721.sol"; +import { MockERC721WithRoyalties } from "../../mock/MockERC721WithRoyalties.sol"; +import { MockERC1155 } from "../../mock/MockERC1155.sol"; +import { MockRoyaltyFeeRegistry } from "../../mock/MockRoyaltyFeeRegistry.sol"; + +// Utils +import { MockOrderGenerator } from "./utils/MockOrderGenerator.sol"; + +contract ProtocolBase is MockOrderGenerator, ILooksRareProtocol { + address[] public operators; + + MockERC20 public looksRareToken; + MockERC721WithRoyalties public mockERC721WithRoyalties; + MockERC721 public mockERC721; + MockERC1155 public mockERC1155; + + ProtocolFeeRecipient public protocolFeeRecipient; + LooksRareProtocol public looksRareProtocol; + TransferManager public transferManager; + MockRoyaltyFeeRegistry public royaltyFeeRegistry; + OrderValidatorV2A public orderValidator; + + WETH public weth; + + function _assertMakerOrderReturnValidationCode( + OrderStructs.Maker memory makerOrder, + bytes memory signature, + uint256 expectedValidationCode + ) internal { + _assertMakerOrderReturnValidationCode(makerOrder, signature, _EMPTY_MERKLE_TREE, expectedValidationCode); + } + + function _assertMakerOrderReturnValidationCodeWithMerkleTree( + OrderStructs.Maker memory makerOrder, + bytes memory signature, + OrderStructs.MerkleTree memory merkleTree, + uint256 expectedValidationCode + ) internal { + _assertMakerOrderReturnValidationCode(makerOrder, signature, merkleTree, expectedValidationCode); + } + + function _assertMakerOrderReturnValidationCode( + OrderStructs.Maker memory makerOrder, + bytes memory signature, + OrderStructs.MerkleTree memory merkleTree, + uint256 expectedValidationCode + ) private { + OrderStructs.Maker[] memory makerOrders = new OrderStructs.Maker[](1); + makerOrders[0] = makerOrder; + + bytes[] memory signatures = new bytes[](1); + signatures[0] = signature; + + OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](1); + merkleTrees[0] = merkleTree; + + uint256[9][] memory validationCodes = orderValidator.checkMultipleMakerOrderValidities( + makerOrders, + signatures, + merkleTrees + ); + + uint256 index = expectedValidationCode / 100; + assertEq(validationCodes[0][index - 1], expectedValidationCode); + } + + function _assertValidMakerOrder(OrderStructs.Maker memory makerOrder, bytes memory signature) internal { + _assertValidMakerOrder(makerOrder, signature, _EMPTY_MERKLE_TREE); + } + + function _assertValidMakerOrderWithMerkleTree( + OrderStructs.Maker memory makerOrder, + bytes memory signature, + OrderStructs.MerkleTree memory merkleTree + ) internal { + _assertValidMakerOrder(makerOrder, signature, merkleTree); + } + + function _assertValidMakerOrder( + OrderStructs.Maker memory makerOrder, + bytes memory signature, + OrderStructs.MerkleTree memory merkleTree + ) private { + OrderStructs.Maker[] memory makerOrders = new OrderStructs.Maker[](1); + makerOrders[0] = makerOrder; + + bytes[] memory signatures = new bytes[](1); + signatures[0] = signature; + + OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](1); + merkleTrees[0] = merkleTree; + + uint256[9][] memory validationCodes = orderValidator.checkMultipleMakerOrderValidities( + makerOrders, + signatures, + merkleTrees + ); + + _assertValidationCodesAllZeroes(validationCodes); + } + + function _assertValidationCodesAllZeroes(uint256[9][] memory validationCodes) private { + for (uint256 i; i < validationCodes.length; i++) { + for (uint256 j; j < 9; j++) { + assertEq(validationCodes[i][j], 0); + } + } + } + + function _setUpUser(address user) internal asPrankedUser(user) { + // Do approvals for collections and WETH + mockERC721.setApprovalForAll(address(transferManager), true); + mockERC1155.setApprovalForAll(address(transferManager), true); + mockERC721WithRoyalties.setApprovalForAll(address(transferManager), true); + weth.approve(address(looksRareProtocol), type(uint256).max); + + // Grant approvals for transfer manager + transferManager.grantApprovals(operators); + + // Receive ETH and WETH + vm.deal(user, _initialETHBalanceUser + _initialWETHBalanceUser); + weth.deposit{ value: _initialWETHBalanceUser }(); + } + + function _setUpUsers() internal { + _setUpUser(makerUser); + _setUpUser(takerUser); + } + + function _setupRegistryRoyalties(address collection, uint256 standardRoyaltyFee) internal { + vm.prank(royaltyFeeRegistry.owner()); + royaltyFeeRegistry.updateRoyaltyInfoForCollection( + collection, + _royaltyRecipient, + _royaltyRecipient, + standardRoyaltyFee + ); + } + + function _setUp() internal { + vm.startPrank(_owner); + weth = new WETH(); + looksRareToken = new MockERC20(); + mockERC721 = new MockERC721(); + mockERC1155 = new MockERC1155(); + + transferManager = new TransferManager(_owner); + royaltyFeeRegistry = new MockRoyaltyFeeRegistry(_owner, 9500); + protocolFeeRecipient = new ProtocolFeeRecipient(0x5924A28caAF1cc016617874a2f0C3710d881f3c1, address(weth)); + looksRareProtocol = new LooksRareProtocol( + _owner, + address(protocolFeeRecipient), + address(transferManager), + address(weth) + ); + mockERC721WithRoyalties = new MockERC721WithRoyalties(_royaltyRecipient, _standardRoyaltyFee); + + // Operations + transferManager.allowOperator(address(looksRareProtocol)); + looksRareProtocol.updateCurrencyStatus(ETH, true); + looksRareProtocol.updateCurrencyStatus(address(weth), true); + + // Fetch domain separator and store it as one of the operators + _domainSeparator = looksRareProtocol.domainSeparator(); + operators.push(address(looksRareProtocol)); + + // Deploy order validator contract + orderValidator = new OrderValidatorV2A(address(looksRareProtocol)); + + // Distribute ETH and WETH to protocol owner + vm.deal(_owner, _initialETHBalanceOwner + _initialWETHBalanceOwner); + weth.deposit{ value: _initialWETHBalanceOwner }(); + vm.stopPrank(); + + // Distribute ETH and WETH to royalty recipient + vm.deal(_royaltyRecipient, _initialETHBalanceRoyaltyRecipient + _initialWETHBalanceRoyaltyRecipient); + vm.startPrank(_royaltyRecipient); + weth.deposit{ value: _initialWETHBalanceRoyaltyRecipient }(); + vm.stopPrank(); + } + + function _genericTakerOrder() internal pure returns (OrderStructs.Taker memory takerOrder) { + takerOrder = OrderStructs.Taker(takerUser, abi.encode()); + } + + function _addStrategy(address strategy, bytes4 selector, bool isMakerBid) internal { + looksRareProtocol.addStrategy( + _standardProtocolFeeBp, + _minTotalFeeBp, + _maxProtocolFeeBp, + selector, + isMakerBid, + strategy + ); + } + + function _assertStrategyAttributes( + address expectedStrategyAddress, + bytes4 expectedSelector, + bool expectedIsMakerBid + ) internal { + ( + bool strategyIsActive, + uint16 strategyStandardProtocolFee, + uint16 strategyMinTotalFee, + uint16 strategyMaxProtocolFee, + bytes4 strategySelector, + bool strategyIsMakerBid, + address strategyImplementation + ) = looksRareProtocol.strategyInfo(1); + + assertTrue(strategyIsActive); + assertEq(strategyStandardProtocolFee, _standardProtocolFeeBp); + assertEq(strategyMinTotalFee, _minTotalFeeBp); + assertEq(strategyMaxProtocolFee, _maxProtocolFeeBp); + assertEq(strategySelector, expectedSelector); + assertEq(strategyIsMakerBid, expectedIsMakerBid); + assertEq(strategyImplementation, expectedStrategyAddress); + } + + function _assertMockERC721Ownership(uint256[] memory itemIds, address owner) internal { + for (uint256 i; i < itemIds.length; i++) { + assertEq(mockERC721.ownerOf(itemIds[i]), owner); + } + } + + /** + * NOTE: It inherits from ILooksRareProtocol, so it + * needs to at least define the functions below. + */ + function executeTakerAsk( + OrderStructs.Taker calldata takerAsk, + OrderStructs.Maker calldata makerBid, + bytes calldata makerSignature, + OrderStructs.MerkleTree calldata merkleTree, + address affiliate + ) external {} + + function executeTakerBid( + OrderStructs.Taker calldata takerBid, + OrderStructs.Maker calldata makerAsk, + bytes calldata makerSignature, + OrderStructs.MerkleTree calldata merkleTree, + address affiliate + ) external payable {} + + function executeMultipleTakerBids( + OrderStructs.Taker[] calldata takerBids, + OrderStructs.Maker[] calldata makerAsks, + bytes[] calldata makerSignatures, + OrderStructs.MerkleTree[] calldata merkleTrees, + address affiliate, + bool isAtomic + ) external payable {} +} diff --git a/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol b/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol new file mode 100644 index 00000000..36f370df --- /dev/null +++ b/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IERC20 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC20.sol"; +import { IWETH } from "@looksrare/contracts-libs/contracts/interfaces/generic/IWETH.sol"; + +// Core contracts +import { ProtocolFeeRecipient } from "@hypercerts/marketplace/ProtocolFeeRecipient.sol"; + +// Other mocks and utils +import { MockERC20 } from "../../mock/MockERC20.sol"; +import { TestParameters } from "./utils/TestParameters.sol"; + +contract ProtocolFeeRecipientTest is TestParameters { + ProtocolFeeRecipient private protocolFeeRecipient; + uint256 private feeSharingSetterInitialWETHBalance; + + address private constant FEE_SHARING_SETTER = 0x5924A28caAF1cc016617874a2f0C3710d881f3c1; + uint256 private constant DUST = 0.6942 ether; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl("mainnet")); + protocolFeeRecipient = new ProtocolFeeRecipient(FEE_SHARING_SETTER, WETH_MAINNET); + feeSharingSetterInitialWETHBalance = IERC20(WETH_MAINNET).balanceOf(FEE_SHARING_SETTER); + + vm.deal(address(protocolFeeRecipient), 0); + deal(WETH_MAINNET, address(protocolFeeRecipient), 0); + } + + function test_TransferETH_NoWETHBalance_WithETHBalance() public { + _sendETHToProtocolFeeRecipient(); + + protocolFeeRecipient.transferETH(); + + assertEq(address(protocolFeeRecipient).balance, 0); + assertEq(IERC20(WETH_MAINNET).balanceOf(address(protocolFeeRecipient)), 0); + assertEq(IERC20(WETH_MAINNET).balanceOf(FEE_SHARING_SETTER), feeSharingSetterInitialWETHBalance + 1 ether); + } + + function test_TransferETH_WithWETHBalance_WithETHBalance() public { + _sendETHToProtocolFeeRecipient(); + _sendWETHToProtocolFeeRecipient(); + + protocolFeeRecipient.transferETH(); + + assertEq(address(protocolFeeRecipient).balance, 0); + assertEq(IERC20(WETH_MAINNET).balanceOf(address(protocolFeeRecipient)), 0); + assertEq( + IERC20(WETH_MAINNET).balanceOf(FEE_SHARING_SETTER), + feeSharingSetterInitialWETHBalance + 1 ether + DUST + ); + } + + function test_TransferETH_WithWETHBalance_NoETHBalance() public { + _sendWETHToProtocolFeeRecipient(); + + protocolFeeRecipient.transferETH(); + + assertEq(address(protocolFeeRecipient).balance, 0); + assertEq(IERC20(WETH_MAINNET).balanceOf(address(protocolFeeRecipient)), 0); + assertEq(IERC20(WETH_MAINNET).balanceOf(FEE_SHARING_SETTER), feeSharingSetterInitialWETHBalance + DUST); + } + + function test_TransferETH_RevertIf_NothingToTransfer() public { + vm.expectRevert(ProtocolFeeRecipient.NothingToTransfer.selector); + protocolFeeRecipient.transferETH(); + } + + function test_TransferWETH() public { + _sendWETHToProtocolFeeRecipient(); + + protocolFeeRecipient.transferERC20(WETH_MAINNET); + + assertEq(IERC20(WETH_MAINNET).balanceOf(address(protocolFeeRecipient)), 0); + assertEq(IERC20(WETH_MAINNET).balanceOf(FEE_SHARING_SETTER), feeSharingSetterInitialWETHBalance + DUST); + } + + function test_TransferWETH_RevertIf_NothingToTransfer() public { + vm.expectRevert(ProtocolFeeRecipient.NothingToTransfer.selector); + protocolFeeRecipient.transferERC20(WETH_MAINNET); + } + + function test_TransferERC20() public { + MockERC20 mockERC20 = new MockERC20(); + mockERC20.mint(address(protocolFeeRecipient), DUST); + + protocolFeeRecipient.transferERC20(address(mockERC20)); + + assertEq(mockERC20.balanceOf(address(protocolFeeRecipient)), 0); + assertEq(mockERC20.balanceOf(FEE_SHARING_SETTER), DUST); + } + + function test_TransferERC20_RevertIf_NothingToTransfer() public { + MockERC20 mockERC20 = new MockERC20(); + vm.expectRevert(ProtocolFeeRecipient.NothingToTransfer.selector); + protocolFeeRecipient.transferERC20(address(mockERC20)); + } + + function _sendETHToProtocolFeeRecipient() private { + (bool success, ) = address(protocolFeeRecipient).call{ value: 1 ether }(""); + assertTrue(success); + assertEq(address(protocolFeeRecipient).balance, 1 ether); + } + + function _sendWETHToProtocolFeeRecipient() private { + IWETH(WETH_MAINNET).deposit{ value: DUST }(); + IERC20(WETH_MAINNET).transfer(address(protocolFeeRecipient), DUST); + assertEq(IERC20(WETH_MAINNET).balanceOf(address(protocolFeeRecipient)), DUST); + } +} diff --git a/contracts/test/foundry/marketplace/Sandbox.t.sol b/contracts/test/foundry/marketplace/Sandbox.t.sol new file mode 100644 index 00000000..6e2a3e36 --- /dev/null +++ b/contracts/test/foundry/marketplace/Sandbox.t.sol @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IERC721 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC721.sol"; +import { IERC1155 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC1155.sol"; + +// Libraries and interfaces +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract SandboxTest is ProtocolBase { + error ERC721TransferFromFail(); + + // Fixed price of sale + uint256 private constant price = 1 ether; + + // Sandbox on Ethereum mainnet + address private constant SANDBOX = 0xa342f5D851E866E18ff98F351f2c6637f4478dB5; + + // Forked block number to run the tests + uint256 private constant FORKED_BLOCK_NUMBER = 16268000; + + function _transferItemIdToUser(address user) private returns (uint256 itemId) { + // @dev This user had 23 of the itemId at the forked block number + address ownerOfItemId = 0x7A9fe22691c811ea339D9B73150e6911a5343DcA; + itemId = 55464657044963196816950587289035428064568320970692304673817341489688428423171; + vm.prank(ownerOfItemId); + IERC1155(SANDBOX).safeTransferFrom(ownerOfItemId, user, itemId, 23, ""); + } + + function _setUpApprovalsForSandbox(address user) internal { + vm.prank(user); + IERC1155(SANDBOX).setApprovalForAll(address(transferManager), true); + } + + function setUp() public { + vm.createSelectFork(vm.rpcUrl("mainnet"), FORKED_BLOCK_NUMBER); + _setUp(); + _setUpUsers(); + } + + /** + * @notice Sandbox implements both ERC721 and ERC1155 interfaceIds. + * This test verifies that only collectionType = 1 works. + * It is for taker ask (matching maker bid). + */ + function testTakerAskCannotTransferSandboxWithERC721CollectionTypeButERC1155CollectionTypeWorks() public { + // Taker user is the one selling the item + _setUpApprovalsForSandbox(takerUser); + uint256 itemId = _transferItemIdToUser(takerUser); + + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, // it should be ERC1155 + orderNonce: 0, + collection: SANDBOX, + currency: address(weth), + signer: makerUser, + price: price, + itemId: itemId + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Prepare the taker ask + OrderStructs.Taker memory takerAsk = _genericTakerOrder(); + + // It should fail with collectionType = 0 + vm.expectRevert(abi.encodeWithSelector(ERC721TransferFromFail.selector)); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Adjust the collection type and sign order again + makerBid.collectionType = CollectionType.ERC1155; + signature = _signMakerOrder(makerBid, makerUserPK); + + // It shouldn't fail with collectionType = 0 + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Maker user has received the Sandbox asset + assertEq(IERC1155(SANDBOX).balanceOf(makerUser, itemId), makerBid.amounts[0]); + } + + /** + * @notice Sandbox implements both ERC721 and ERC1155 interfaceIds. + * This test verifies that only collectionType = 1 works. + * It is for taker bid (matching maker ask). + */ + function testTakerBidCannotTransferSandboxWithERC721CollectionTypeButERC1155CollectionTypeWorks() public { + // Maker user is the one selling the item + _setUpApprovalsForSandbox(makerUser); + uint256 itemId = _transferItemIdToUser(makerUser); + + OrderStructs.Maker memory makerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, // it should be ERC1155 + orderNonce: 0, + collection: SANDBOX, + currency: ETH, + signer: makerUser, + price: price, + itemId: itemId + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Prepare the taker bid + OrderStructs.Taker memory takerBid = _genericTakerOrder(); + + // It should fail with collectionType = 0 + vm.expectRevert(abi.encodeWithSelector(ERC721TransferFromFail.selector)); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + // Adjust the collection type and sign order again + makerAsk.collectionType = CollectionType.ERC1155; + signature = _signMakerOrder(makerAsk, makerUserPK); + + // It shouldn't fail with collectionType = 0 + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + // Taker user has received the Sandbox asset + assertEq(IERC1155(SANDBOX).balanceOf(takerUser, itemId), makerAsk.amounts[0]); + } +} diff --git a/contracts/test/foundry/marketplace/SignaturesEIP2098.t.sol b/contracts/test/foundry/marketplace/SignaturesEIP2098.t.sol new file mode 100644 index 00000000..9a480b0f --- /dev/null +++ b/contracts/test/foundry/marketplace/SignaturesEIP2098.t.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries, interfaces, errors +import "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract SignaturesEIP2098Test is ProtocolBase { + function setUp() public { + _setUp(); + } + + function testCanSignValidMakerAskEIP2098(uint256 price, uint256 itemId) public { + vm.assume(price <= 2 ether); + + _setUpUsers(); + _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); + + (OrderStructs.Maker memory makerAsk, ) = _createMockMakerAskAndTakerBid(address(mockERC721)); + makerAsk.price = price; + makerAsk.itemIds[0] = itemId; + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Mint asset + mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + // Adjust the signature + signature = _eip2098Signature(signature); + + // Verify validity of maker ask order + _assertValidMakerOrder(makerAsk, signature); + } + + function testCanSignValidMakerBidEIP2098(uint256 price, uint256 itemId) public { + vm.assume(price <= 2 ether); + + _setUpUsers(); + _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); + + (OrderStructs.Maker memory makerBid, ) = _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); + makerBid.price = price; + makerBid.itemIds[0] = itemId; + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Adjust the signature + signature = _eip2098Signature(signature); + + // Mint asset + mockERC721.mint(takerUser, makerBid.itemIds[0]); + + // Verify validity of maker bid order + _assertValidMakerOrder(makerBid, signature); + } +} diff --git a/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC1155.t.sol b/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC1155.t.sol new file mode 100644 index 00000000..60ef310b --- /dev/null +++ b/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC1155.t.sol @@ -0,0 +1,481 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries and interfaces +import { IReentrancyGuard } from "@looksrare/contracts-libs/contracts/interfaces/IReentrancyGuard.sol"; +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Mocks and other utils +import { ERC1271Wallet } from "./utils/ERC1271Wallet.sol"; +import { MaliciousERC1271Wallet } from "./utils/MaliciousERC1271Wallet.sol"; +import { MaliciousOnERC1155ReceivedERC1271Wallet } from "./utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol"; +import { MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet } from "./utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol"; +import { MaliciousIsValidSignatureERC1271Wallet } from "./utils/MaliciousIsValidSignatureERC1271Wallet.sol"; + +// Errors +import { SignatureERC1271Invalid } from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; +import { ERC1155SafeTransferFromFail, ERC1155SafeBatchTransferFromFail } from "@looksrare/contracts-libs/contracts/errors/LowLevelErrors.sol"; +import { SIGNATURE_INVALID_EIP1271 } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +/** + * @dev ERC1271Wallet recovers a signature's signer using ECDSA. If it matches the mock wallet's + * owner, it returns the magic value. Otherwise it returns an empty bytes4 value. + */ +contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { + uint256 private constant price = 1 ether; // Fixed price of sale + uint256 private constant itemId = 0; + bytes private constant _EMPTY_SIGNATURE = new bytes(0); + + function setUp() public { + _setUp(); + _setUpUser(takerUser); + _setupRegistryRoyalties(address(mockERC1155), _standardRoyaltyFee); + } + + function testTakerBid() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _takerBidSetup(address(wallet)); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + vm.startPrank(address(wallet)); + mockERC1155.setApprovalForAll(address(transferManager), true); + transferManager.grantApprovals(operators); + vm.stopPrank(); + + _assertValidMakerOrder(makerAsk, signature); + + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + assertEq(mockERC1155.balanceOf(takerUser, itemId), 1); + } + + function testTakerBidInvalidSignature() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _takerBidSetup(address(wallet)); + + // Signed by a different private key + bytes memory signature = _signMakerOrder(makerAsk, takerUserPK); + + vm.startPrank(address(wallet)); + mockERC1155.setApprovalForAll(address(transferManager), true); + transferManager.grantApprovals(operators); + vm.stopPrank(); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, SIGNATURE_INVALID_EIP1271); + + vm.expectRevert(SignatureERC1271Invalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testTakerBidIsInvalidSignatureReentrancy() public { + MaliciousIsValidSignatureERC1271Wallet maliciousERC1271Wallet = new MaliciousIsValidSignatureERC1271Wallet( + address(looksRareProtocol) + ); + _setUpUser(address(maliciousERC1271Wallet)); + maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerBid); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _takerBidSetup( + address(maliciousERC1271Wallet) + ); + + vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + _EMPTY_SIGNATURE, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testTakerAsk() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _takerAskSetup(address(wallet)); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Wallet needs to hold WETH and have given WETH approval + deal(address(weth), address(wallet), price); + vm.prank(address(wallet)); + weth.approve(address(looksRareProtocol), price); + + _assertValidMakerOrder(makerBid, signature); + + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + assertEq(mockERC1155.balanceOf(address(wallet), itemId), 1); + } + + function testTakerAskInvalidSignature() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _takerAskSetup(address(wallet)); + + // Signed by a different private key + bytes memory signature = _signMakerOrder(makerBid, takerUserPK); + + // Wallet needs to hold WETH and have given WETH approval + deal(address(weth), address(wallet), price); + vm.prank(address(wallet)); + weth.approve(address(looksRareProtocol), price); + + _assertMakerOrderReturnValidationCode(makerBid, signature, SIGNATURE_INVALID_EIP1271); + + vm.expectRevert(SignatureERC1271Invalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testTakerAskIsValidSignatureReentrancy() public { + MaliciousIsValidSignatureERC1271Wallet maliciousERC1271Wallet = new MaliciousIsValidSignatureERC1271Wallet( + address(looksRareProtocol) + ); + _setUpUser(address(maliciousERC1271Wallet)); + maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerAsk); + + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _takerAskSetup( + address(maliciousERC1271Wallet) + ); + + vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testTakerAskOnERC1155ReceivedReentrancy() public { + MaliciousOnERC1155ReceivedERC1271Wallet maliciousERC1271Wallet = new MaliciousOnERC1155ReceivedERC1271Wallet( + address(looksRareProtocol) + ); + _setUpUser(address(maliciousERC1271Wallet)); + + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _takerAskSetup( + address(maliciousERC1271Wallet) + ); + + maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerAsk); + + vm.expectRevert(ERC1155SafeTransferFromFail.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testBatchTakerAsk() public { + ERC1271Wallet wallet = new ERC1271Wallet(makerUser); + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _batchTakerAskSetup(address(wallet)); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Wallet needs to hold WETH and have given WETH approval + deal(address(weth), address(wallet), price); + vm.prank(address(wallet)); + weth.approve(address(looksRareProtocol), price); + + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + for (uint256 i; i < 10; i++) { + assertEq(mockERC1155.balanceOf(address(wallet), i), 1); + } + } + + function testBatchTakerAskOnERC1155BatchReceivedReentrancy() public { + MaliciousOnERC1155ReceivedERC1271Wallet maliciousERC1271Wallet = new MaliciousOnERC1155ReceivedERC1271Wallet( + address(looksRareProtocol) + ); + _setUpUser(address(maliciousERC1271Wallet)); + + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _batchTakerAskSetup( + address(maliciousERC1271Wallet) + ); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Wallet needs to hold WETH and have given WETH approval + deal(address(weth), address(maliciousERC1271Wallet), price); + vm.prank(address(maliciousERC1271Wallet)); + weth.approve(address(looksRareProtocol), price); + + maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerAsk); + + vm.expectRevert(ERC1155SafeBatchTransferFromFail.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + uint256 private constant numberOfPurchases = 3; + + function testExecuteMultipleTakerBids() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + + ( + OrderStructs.Maker[] memory makerAsks, + OrderStructs.Taker[] memory takerBids, + OrderStructs.MerkleTree[] memory merkleTrees, + bytes[] memory signatures + ) = _multipleTakerBidsSetup(address(wallet)); + + vm.startPrank(address(wallet)); + mockERC1155.setApprovalForAll(address(transferManager), true); + transferManager.grantApprovals(operators); + vm.stopPrank(); + + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberOfPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + + for (uint256 i; i < numberOfPurchases; i++) { + assertEq(mockERC1155.balanceOf(takerUser, i), 1); + } + } + + function testExecuteMultipleTakerBidsInvalidSignatures() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + + ( + OrderStructs.Maker[] memory makerAsks, + OrderStructs.Taker[] memory takerBids, + OrderStructs.MerkleTree[] memory merkleTrees, + bytes[] memory signatures + ) = _multipleTakerBidsSetup(address(wallet)); + + // Signed by a different private key + for (uint256 i; i < signatures.length; i++) { + signatures[i] = _signMakerOrder(makerAsks[i], takerUserPK); + } + + vm.startPrank(address(wallet)); + mockERC1155.setApprovalForAll(address(transferManager), true); + transferManager.grantApprovals(operators); + vm.stopPrank(); + + vm.expectRevert(SignatureERC1271Invalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberOfPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + } + + function testExecuteMultipleTakerBidsIsValidSignatureReentrancy() public { + MaliciousIsValidSignatureERC1271Wallet maliciousERC1271Wallet = new MaliciousIsValidSignatureERC1271Wallet( + address(looksRareProtocol) + ); + _setUpUser(address(maliciousERC1271Wallet)); + maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteMultipleTakerBids); + + ( + OrderStructs.Maker[] memory makerAsks, + OrderStructs.Taker[] memory takerBids, + OrderStructs.MerkleTree[] memory merkleTrees, + bytes[] memory signatures + ) = _multipleTakerBidsSetup(address(maliciousERC1271Wallet)); + + vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberOfPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + + for (uint256 i; i < numberOfPurchases - 1; i++) { + assertEq(mockERC1155.balanceOf(takerUser, i), 0); + } + } + + function testExecuteMultipleTakerBidsOnERC1155ReceivedReentrancyOnlyInTheLastCall() public { + MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet maliciousERC1271Wallet = new MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet( + takerUser + ); + _setUpUser(makerUser); + maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteMultipleTakerBids); + + ( + OrderStructs.Maker[] memory makerAsks, + OrderStructs.Taker[] memory takerBids, + OrderStructs.MerkleTree[] memory merkleTrees, + bytes[] memory signatures + ) = _multipleTakerBidsSetup(makerUser); + + // Set the NFT recipient as the ERC1271 wallet to trigger onERC1155Received + for (uint256 i; i < numberOfPurchases; i++) { + takerBids[i].recipient = address(maliciousERC1271Wallet); + } + + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberOfPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + + // First 2 purchases should go through, but the last one fails silently + for (uint256 i; i < numberOfPurchases - 1; i++) { + assertEq(mockERC1155.balanceOf(address(maliciousERC1271Wallet), i), 1); + } + assertEq(mockERC1155.balanceOf(address(maliciousERC1271Wallet), numberOfPurchases - 1), 0); + } + + function _takerBidSetup( + address signer + ) private returns (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) { + // Mint asset + mockERC1155.mint(signer, itemId, 1); + + makerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC1155, + orderNonce: 0, + collection: address(mockERC1155), + currency: ETH, + signer: signer, + price: price, + itemId: itemId + }); + + // Prepare the taker bid + takerBid = _genericTakerOrder(); + } + + function _takerAskSetup( + address signer + ) private returns (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) { + makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC1155, + orderNonce: 0, + collection: address(mockERC1155), + currency: address(weth), + signer: signer, + price: price, + itemId: itemId + }); + + // Mint asset + mockERC1155.mint(takerUser, itemId, 1); + + // Prepare the taker ask + takerAsk = _genericTakerOrder(); + } + + function _batchTakerAskSetup( + address signer + ) private returns (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) { + uint256[] memory itemIds = new uint256[](10); + uint256[] memory amounts = new uint256[](10); + + for (uint256 i; i < 10; i++) { + itemIds[i] = i; + amounts[i] = 1; + + // Mint asset + mockERC1155.mint(takerUser, i, 1); + } + + // Prepare the first order + makerBid = _createMultiItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC1155, + orderNonce: 0, + collection: address(mockERC1155), + currency: address(weth), + signer: signer, + price: price, + itemIds: itemIds, + amounts: amounts + }); + + // Prepare the taker ask + takerAsk = _genericTakerOrder(); + } + + function _multipleTakerBidsSetup( + address signer + ) + private + returns ( + OrderStructs.Maker[] memory makerAsks, + OrderStructs.Taker[] memory takerBids, + OrderStructs.MerkleTree[] memory merkleTrees, + bytes[] memory signatures + ) + { + makerAsks = new OrderStructs.Maker[](numberOfPurchases); + takerBids = new OrderStructs.Taker[](numberOfPurchases); + signatures = new bytes[](numberOfPurchases); + + for (uint256 i; i < numberOfPurchases; i++) { + // Mint asset + mockERC1155.mint(signer, i, 1); + + makerAsks[i] = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC1155, + orderNonce: i, + collection: address(mockERC1155), + currency: ETH, + signer: signer, + price: price, + itemId: i // 0, 1, etc. + }); + + signatures[i] = _signMakerOrder(makerAsks[i], makerUserPK); + + takerBids[i] = _genericTakerOrder(); + } + + // Other execution parameters + merkleTrees = new OrderStructs.MerkleTree[](numberOfPurchases); + } +} diff --git a/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC721.t.sol b/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC721.t.sol new file mode 100644 index 00000000..61df2186 --- /dev/null +++ b/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC721.t.sol @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries and interfaces +import { IReentrancyGuard } from "@looksrare/contracts-libs/contracts/interfaces/IReentrancyGuard.sol"; +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Mocks and other utils +import { ERC1271Wallet } from "./utils/ERC1271Wallet.sol"; +import { MaliciousERC1271Wallet } from "./utils/MaliciousERC1271Wallet.sol"; +import { MaliciousIsValidSignatureERC1271Wallet } from "./utils/MaliciousIsValidSignatureERC1271Wallet.sol"; + +// Errors +import { SignatureERC1271Invalid } from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; +import { SIGNATURE_INVALID_EIP1271 } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +/** + * @dev ERC1271Wallet recovers a signature's signer using ECDSA. If it matches the mock wallet's + * owner, it returns the magic value. Otherwise it returns an empty bytes4 value. + */ +contract SignaturesERC1271WalletForERC721Test is ProtocolBase { + uint256 private constant price = 1 ether; // Fixed price of sale + bytes private constant _EMPTY_SIGNATURE = new bytes(0); + + function setUp() public { + _setUp(); + _setUpUser(takerUser); + _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); + } + + function testTakerBid() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _takerBidSetup(address(wallet)); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + vm.startPrank(address(wallet)); + mockERC721.setApprovalForAll(address(transferManager), true); + transferManager.grantApprovals(operators); + vm.stopPrank(); + + _assertValidMakerOrder(makerAsk, signature); + + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + assertEq(mockERC721.ownerOf(makerAsk.itemIds[0]), takerUser); + } + + function testTakerBidInvalidSignature() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _takerBidSetup(address(wallet)); + + // Signed by a different private key + bytes memory signature = _signMakerOrder(makerAsk, takerUserPK); + + vm.startPrank(address(wallet)); + mockERC721.setApprovalForAll(address(transferManager), true); + transferManager.grantApprovals(operators); + vm.stopPrank(); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, SIGNATURE_INVALID_EIP1271); + + vm.expectRevert(SignatureERC1271Invalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testTakerBidReentrancy() public { + MaliciousIsValidSignatureERC1271Wallet maliciousERC1271Wallet = new MaliciousIsValidSignatureERC1271Wallet( + address(looksRareProtocol) + ); + _setUpUser(address(maliciousERC1271Wallet)); + maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerBid); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _takerBidSetup( + address(maliciousERC1271Wallet) + ); + + vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + _EMPTY_SIGNATURE, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testTakerAsk() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _takerAskSetup(address(wallet)); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Wallet needs to hold WETH and have given WETH approval + deal(address(weth), address(wallet), price); + vm.prank(address(wallet)); + weth.approve(address(looksRareProtocol), price); + + _assertValidMakerOrder(makerBid, signature); + + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + assertEq(mockERC721.ownerOf(makerBid.itemIds[0]), address(wallet)); + } + + function testTakerAskInvalidSignature() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _takerAskSetup(address(wallet)); + + // Signed by a different private key + bytes memory signature = _signMakerOrder(makerBid, takerUserPK); + + // Wallet needs to hold WETH and have given WETH approval + deal(address(weth), address(wallet), price); + vm.prank(address(wallet)); + weth.approve(address(looksRareProtocol), price); + + _assertMakerOrderReturnValidationCode(makerBid, signature, SIGNATURE_INVALID_EIP1271); + + vm.expectRevert(SignatureERC1271Invalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testTakerAskReentrancy() public { + MaliciousIsValidSignatureERC1271Wallet maliciousERC1271Wallet = new MaliciousIsValidSignatureERC1271Wallet( + address(looksRareProtocol) + ); + _setUpUser(address(maliciousERC1271Wallet)); + maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerAsk); + + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _takerAskSetup( + address(maliciousERC1271Wallet) + ); + + vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + uint256 private constant numberPurchases = 3; + + function testExecuteMultipleTakerBids() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + + ( + OrderStructs.Maker[] memory makerAsks, + OrderStructs.Taker[] memory takerBids, + OrderStructs.MerkleTree[] memory merkleTrees, + bytes[] memory signatures + ) = _multipleTakerBidsSetup(address(wallet)); + + vm.startPrank(address(wallet)); + mockERC721.setApprovalForAll(address(transferManager), true); + transferManager.grantApprovals(operators); + vm.stopPrank(); + + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + + for (uint256 i; i < numberPurchases; i++) { + assertEq(mockERC721.ownerOf(i), takerUser); + } + } + + function testExecuteMultipleTakerBidsInvalidSignatures() public { + ERC1271Wallet wallet = new ERC1271Wallet(address(makerUser)); + + ( + OrderStructs.Maker[] memory makerAsks, + OrderStructs.Taker[] memory takerBids, + OrderStructs.MerkleTree[] memory merkleTrees, + bytes[] memory signatures + ) = _multipleTakerBidsSetup(address(wallet)); + + // Signed by a different private key + for (uint256 i; i < signatures.length; i++) { + signatures[i] = _signMakerOrder(makerAsks[i], takerUserPK); + } + + vm.startPrank(address(wallet)); + mockERC721.setApprovalForAll(address(transferManager), true); + transferManager.grantApprovals(operators); + vm.stopPrank(); + + vm.expectRevert(SignatureERC1271Invalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + } + + function testExecuteMultipleTakerBidsReentrancy() public { + MaliciousIsValidSignatureERC1271Wallet maliciousERC1271Wallet = new MaliciousIsValidSignatureERC1271Wallet( + address(looksRareProtocol) + ); + _setUpUser(address(maliciousERC1271Wallet)); + maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteMultipleTakerBids); + + ( + OrderStructs.Maker[] memory makerAsks, + OrderStructs.Taker[] memory takerBids, + OrderStructs.MerkleTree[] memory merkleTrees, + bytes[] memory signatures + ) = _multipleTakerBidsSetup(address(maliciousERC1271Wallet)); + + vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + } + + function _takerBidSetup( + address signer + ) private returns (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) { + (makerAsk, takerBid) = _createMockMakerAskAndTakerBid(address(mockERC721)); + makerAsk.signer = signer; + // Mint asset + mockERC721.mint(signer, makerAsk.itemIds[0]); + } + + function _takerAskSetup( + address signer + ) private returns (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) { + (makerBid, takerAsk) = _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); + makerBid.signer = signer; + // Mint asset + mockERC721.mint(takerUser, makerBid.itemIds[0]); + } + + function _multipleTakerBidsSetup( + address signer + ) + private + returns ( + OrderStructs.Maker[] memory makerAsks, + OrderStructs.Taker[] memory takerBids, + OrderStructs.MerkleTree[] memory merkleTrees, + bytes[] memory signatures + ) + { + makerAsks = new OrderStructs.Maker[](numberPurchases); + takerBids = new OrderStructs.Taker[](numberPurchases); + signatures = new bytes[](numberPurchases); + + for (uint256 i; i < numberPurchases; i++) { + // Mint asset + mockERC721.mint(signer, i); + + makerAsks[i] = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: i, + collection: address(mockERC721), + currency: ETH, + signer: signer, + price: price, + itemId: i // 0, 1, etc. + }); + + signatures[i] = _signMakerOrder(makerAsks[i], makerUserPK); + + takerBids[i] = _genericTakerOrder(); + } + + // Other execution parameters + merkleTrees = new OrderStructs.MerkleTree[](numberPurchases); + } +} diff --git a/contracts/test/foundry/marketplace/SignaturesRevertions.t.sol b/contracts/test/foundry/marketplace/SignaturesRevertions.t.sol new file mode 100644 index 00000000..1861c480 --- /dev/null +++ b/contracts/test/foundry/marketplace/SignaturesRevertions.t.sol @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries, interfaces, errors +import { SignatureParameterVInvalid, SignatureParameterSInvalid, SignatureEOAInvalid, NullSignerAddress, SignatureLengthInvalid } from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import { INVALID_S_PARAMETER_EOA, INVALID_V_PARAMETER_EOA, NULL_SIGNER_EOA, INVALID_SIGNATURE_LENGTH, INVALID_SIGNER_EOA } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract SignaturesRevertionsTest is ProtocolBase { + uint256 internal constant _MAX_PRIVATE_KEY = + 115792089237316195423570985008687907852837564279074904382605163141518161494337; + + function setUp() public { + _setUp(); + } + + function testRevertIfSignatureEOAInvalid(uint256 itemId, uint256 price, uint256 randomPK) public { + // @dev Private keys 1 and 2 are used for maker/taker users + vm.assume(randomPK > 2 && randomPK < _MAX_PRIVATE_KEY); + + OrderStructs.Maker memory makerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: ETH, + signer: makerUser, + price: price, + itemId: itemId + }); + + address randomUser = vm.addr(randomPK); + _setUpUser(randomUser); + bytes memory signature = _signMakerOrder(makerAsk, randomPK); + _assertMakerOrderReturnValidationCode(makerAsk, signature, INVALID_SIGNER_EOA); + + vm.expectRevert(SignatureEOAInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid( + _genericTakerOrder(), + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testRevertIfInvalidVParameter(uint256 itemId, uint256 price, uint8 v) public { + vm.assume(v != 27 && v != 28); + + OrderStructs.Maker memory makerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: ETH, + signer: makerUser, + price: price, + itemId: itemId + }); + + // Sign but replace v by the fuzzed v + bytes32 orderHash = _computeOrderHash(makerAsk); + (, bytes32 r, bytes32 s) = vm.sign( + makerUserPK, + keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash)) + ); + bytes memory signature = abi.encodePacked(r, s, v); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, INVALID_V_PARAMETER_EOA); + + vm.expectRevert(abi.encodeWithSelector(SignatureParameterVInvalid.selector, v)); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid( + _genericTakerOrder(), + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testRevertIfInvalidSParameter(uint256 itemId, uint256 price, bytes32 s) public { + vm.assume(uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0); + + OrderStructs.Maker memory makerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: ETH, + signer: makerUser, + price: price, + itemId: itemId + }); + + // Sign but replace s by the fuzzed s + bytes32 orderHash = _computeOrderHash(makerAsk); + (uint8 v, bytes32 r, ) = vm.sign( + makerUserPK, + keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash)) + ); + bytes memory signature = abi.encodePacked(r, s, v); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, INVALID_S_PARAMETER_EOA); + + vm.expectRevert(abi.encodeWithSelector(SignatureParameterSInvalid.selector)); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid( + _genericTakerOrder(), + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testRevertIfRecoveredSignerIsNullAddress(uint256 itemId, uint256 price) public { + OrderStructs.Maker memory makerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: ETH, + signer: makerUser, + price: price, + itemId: itemId + }); + + // Sign but replace r by empty bytes32 + bytes32 orderHash = _computeOrderHash(makerAsk); + (uint8 v, , bytes32 s) = vm.sign( + makerUserPK, + keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash)) + ); + + bytes32 r; + bytes memory signature = abi.encodePacked(r, s, v); + + _assertMakerOrderReturnValidationCode(makerAsk, signature, NULL_SIGNER_EOA); + + vm.expectRevert(abi.encodeWithSelector(NullSignerAddress.selector)); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid( + _genericTakerOrder(), + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testRevertIfInvalidSignatureLength(uint256 itemId, uint256 price, uint256 length) public { + // @dev Getting OutOfGas starting from 16,776,985, probably due to memory cost + vm.assume(length != 64 && length != 65 && length < 16_776_985); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + makerAsk.itemIds[0] = itemId; + makerAsk.price = price; + + bytes memory signature = new bytes(length); + _assertMakerOrderReturnValidationCode(makerAsk, signature, INVALID_SIGNATURE_LENGTH); + + vm.expectRevert(abi.encodeWithSelector(SignatureLengthInvalid.selector, length)); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } +} diff --git a/contracts/test/foundry/marketplace/StandardTransactions.t.sol b/contracts/test/foundry/marketplace/StandardTransactions.t.sol new file mode 100644 index 00000000..3bc01b8e --- /dev/null +++ b/contracts/test/foundry/marketplace/StandardTransactions.t.sol @@ -0,0 +1,555 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries, interfaces, errors +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { LengthsInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; + +import { CreatorFeeManagerWithRoyalties } from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract StandardTransactionsTest is ProtocolBase { + error ERC721TransferFromFail(); + + uint256 private constant itemId = 420; + uint16 private constant NEW_ROYALTY_FEE = uint16(50); + + function setUp() public { + _setUp(); + CreatorFeeManagerWithRoyalties creatorFeeManager = new CreatorFeeManagerWithRoyalties( + address(royaltyFeeRegistry) + ); + vm.prank(_owner); + looksRareProtocol.updateCreatorFeeManager(address(creatorFeeManager)); + } + + /** + * One ERC721 (where royalties come from the registry) is sold through a taker bid + */ + function testTakerBidERC721WithRoyaltiesFromRegistry(uint256 price) public { + vm.assume(price <= 2 ether); + _setUpUsers(); + _setupRegistryRoyalties(address(mockERC721), NEW_ROYALTY_FEE); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + makerAsk.price = price; + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Mint asset + mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + // Verify validity of maker ask order + _assertValidMakerOrder(makerAsk, signature); + + // Arrays for events + uint256[3] memory expectedFees = _calculateExpectedFees({ price: price, royaltyFeeBp: NEW_ROYALTY_FEE }); + address[2] memory expectedRecipients; + + expectedRecipients[0] = makerUser; + expectedRecipients[1] = _royaltyRecipient; + + // Execute taker bid transaction + vm.prank(takerUser); + vm.expectEmit(true, false, false, true); + + emit TakerBid( + NonceInvalidationParameters({ + orderHash: _computeOrderHash(makerAsk), + orderNonce: makerAsk.orderNonce, + isNonceInvalidated: true + }), + takerUser, + takerUser, + makerAsk.strategyId, + makerAsk.currency, + makerAsk.collection, + makerAsk.itemIds, + makerAsk.amounts, + expectedRecipients, + expectedFees + ); + + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + _assertSuccessfulExecutionThroughETH(takerUser, makerUser, price, expectedFees); + + // No leftover in the balance of the contract + assertEq(address(looksRareProtocol).balance, 0); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerAsk.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + /** + * One ERC721 is sold through taker bid. Address zero is specified as the recipient in the taker struct. + */ + function testTakerBidERC721WithAddressZeroSpecifiedAsRecipient(uint256 price) public { + vm.assume(price <= 2 ether); + _setUpUsers(); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( + address(mockERC721) + ); + makerAsk.price = price; + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Mint asset + mockERC721.mint(makerUser, makerAsk.itemIds[0]); + + // Adjustment + takerBid.recipient = address(0); + + // Verify validity of maker ask order + _assertValidMakerOrder(makerAsk, signature); + + // Arrays for events + uint256[3] memory expectedFees = _calculateExpectedFees({ price: price, royaltyFeeBp: 0 }); + address[2] memory expectedRecipients; + + expectedRecipients[0] = makerUser; + expectedRecipients[1] = address(0); // No royalties + + // Execute taker bid transaction + vm.prank(takerUser); + vm.expectEmit(true, false, false, true); + + emit TakerBid( + NonceInvalidationParameters({ + orderHash: _computeOrderHash(makerAsk), + orderNonce: makerAsk.orderNonce, + isNonceInvalidated: true + }), + takerUser, + takerUser, + makerAsk.strategyId, + makerAsk.currency, + makerAsk.collection, + makerAsk.itemIds, + makerAsk.amounts, + expectedRecipients, + expectedFees + ); + + looksRareProtocol.executeTakerBid{ value: price }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + _assertSuccessfulExecutionThroughETH(takerUser, makerUser, price, expectedFees); + } + + /** + * One ERC721 (where royalties come from the registry) is sold through a taker ask using WETH + */ + function testTakerAskERC721WithRoyaltiesFromRegistry(uint256 price) public { + vm.assume(price <= 2 ether); + + _setUpUsers(); + _setupRegistryRoyalties(address(mockERC721), NEW_ROYALTY_FEE); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + makerBid.price = price; + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Verify maker bid order + _assertValidMakerOrder(makerBid, signature); + + // Mint asset + mockERC721.mint(takerUser, makerBid.itemIds[0]); + + // Arrays for events + uint256[3] memory expectedFees = _calculateExpectedFees({ price: price, royaltyFeeBp: NEW_ROYALTY_FEE }); + address[2] memory expectedRecipients; + + expectedRecipients[0] = takerUser; + expectedRecipients[1] = _royaltyRecipient; + + // Execute taker ask transaction + vm.prank(takerUser); + + vm.expectEmit(true, false, false, true); + + emit TakerAsk( + NonceInvalidationParameters({ + orderHash: _computeOrderHash(makerBid), + orderNonce: makerBid.orderNonce, + isNonceInvalidated: true + }), + takerUser, + makerUser, + makerBid.strategyId, + makerBid.currency, + makerBid.collection, + makerBid.itemIds, + makerBid.amounts, + expectedRecipients, + expectedFees + ); + + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + _assertSuccessfulExecutionThroughWETH(makerUser, takerUser, price, expectedFees); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + /** + * One ERC721 is sold through a taker ask using WETH. Address zero is specified as the recipient in the taker struct. + */ + function testTakerAskERC721WithAddressZeroSpecifiedAsRecipient(uint256 price) public { + vm.assume(price <= 2 ether); + _setUpUsers(); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + makerBid.price = price; + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Verify maker bid order + _assertValidMakerOrder(makerBid, signature); + + // Adjustment + takerAsk.recipient = address(0); + + // Mint asset + mockERC721.mint(takerUser, makerBid.itemIds[0]); + + // Arrays for events + uint256[3] memory expectedFees = _calculateExpectedFees({ price: price, royaltyFeeBp: 0 }); + address[2] memory expectedRecipients; + + expectedRecipients[0] = takerUser; + expectedRecipients[1] = address(0); // No royalties + + // Execute taker ask transaction + vm.prank(takerUser); + vm.expectEmit(true, false, false, true); + + emit TakerAsk( + NonceInvalidationParameters({ + orderHash: _computeOrderHash(makerBid), + orderNonce: makerBid.orderNonce, + isNonceInvalidated: true + }), + takerUser, + makerUser, + makerBid.strategyId, + makerBid.currency, + makerBid.collection, + makerBid.itemIds, + makerBid.amounts, + expectedRecipients, + expectedFees + ); + + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + _assertSuccessfulExecutionThroughWETH(makerUser, takerUser, price, expectedFees); + } + + /** + * Three ERC721 are sold through 3 taker bids in one transaction with non-atomicity. + */ + function testThreeTakerBidsERC721() public { + uint256 price = 0.015 ether; + _setUpUsers(); + + uint256 numberPurchases = 3; + + OrderStructs.Maker[] memory makerAsks = new OrderStructs.Maker[](numberPurchases); + OrderStructs.Taker[] memory takerBids = new OrderStructs.Taker[](numberPurchases); + bytes[] memory signatures = new bytes[](numberPurchases); + + for (uint256 i; i < numberPurchases; i++) { + // Mint asset + mockERC721.mint(makerUser, i); + + makerAsks[i] = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: i, + collection: address(mockERC721), + currency: ETH, + signer: makerUser, + price: price, // Fixed + itemId: i // (0, 1, etc.) + }); + + // Sign order + signatures[i] = _signMakerOrder(makerAsks[i], makerUserPK); + + takerBids[i] = _genericTakerOrder(); + } + + // Other execution parameters + OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](numberPurchases); + + // Execute taker bid transaction + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + + for (uint256 i; i < numberPurchases; i++) { + // Taker user has received the asset + assertEq(mockERC721.ownerOf(i), takerUser); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, i), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + // Taker bid user pays the whole price + assertEq(address(takerUser).balance, _initialETHBalanceUser - (numberPurchases * price)); + // Maker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq( + address(makerUser).balance, + _initialETHBalanceUser + + ((price * _sellerProceedBpWithStandardProtocolFeeBp) * numberPurchases) / + ONE_HUNDRED_PERCENT_IN_BP + ); + // No leftover in the balance of the contract + assertEq(address(looksRareProtocol).balance, 0); + } + + /** + * Transaction cannot go through if atomic, goes through if non-atomic (fund returns to buyer). + */ + function testThreeTakerBidsERC721OneFails() public { + _setUpUsers(); + + uint256 numberPurchases = 3; + uint256 faultyTokenId = numberPurchases - 1; + + OrderStructs.Maker[] memory makerAsks = new OrderStructs.Maker[](numberPurchases); + OrderStructs.Taker[] memory takerBids = new OrderStructs.Taker[](numberPurchases); + bytes[] memory signatures = new bytes[](numberPurchases); + + for (uint256 i; i < numberPurchases; i++) { + // Mint asset + mockERC721.mint(makerUser, i); + + makerAsks[i] = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: CollectionType.ERC721, + orderNonce: i, + collection: address(mockERC721), + currency: ETH, + signer: makerUser, + price: 1.4 ether, // Fixed + itemId: i // (0, 1, etc.) + }); + + // Sign order + signatures[i] = _signMakerOrder(makerAsks[i], makerUserPK); + + takerBids[i] = _genericTakerOrder(); + } + + // Transfer tokenId = 2 to random user + address randomUser = address(55); + vm.prank(makerUser); + mockERC721.transferFrom(makerUser, randomUser, faultyTokenId); + + /** + * 1. The whole purchase fails if execution is atomic + */ + { + // Other execution parameters + OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](numberPurchases); + + vm.expectRevert(abi.encodeWithSelector(ERC721TransferFromFail.selector)); + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: 1.4 ether * numberPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + true + ); + } + + /** + * 2. The whole purchase doesn't fail if execution is not-atomic + */ + { + // Other execution parameters + OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](numberPurchases); + + vm.prank(takerUser); + // Execute taker bid transaction + looksRareProtocol.executeMultipleTakerBids{ value: 1.4 ether * numberPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + } + + for (uint256 i; i < faultyTokenId; i++) { + // Taker user has received the first two assets + assertEq(mockERC721.ownerOf(i), takerUser); + // Verify the first two nonces are marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, i), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + // Taker user has not received the asset + assertEq(mockERC721.ownerOf(faultyTokenId), randomUser); + // Verify the nonce is NOT marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, faultyTokenId), bytes32(0)); + // Taker bid user pays the whole price + assertEq(address(takerUser).balance, _initialETHBalanceUser - 1 - ((numberPurchases - 1) * 1.4 ether)); + // Maker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq( + address(makerUser).balance, + _initialETHBalanceUser + + ((1.4 ether * _sellerProceedBpWithStandardProtocolFeeBp) * (numberPurchases - 1)) / + ONE_HUNDRED_PERCENT_IN_BP + ); + // 1 wei left in the balance of the contract + assertEq(address(looksRareProtocol).balance, 1); + } + + function testThreeTakerBidsERC721LengthsInvalid() public { + _setUpUsers(); + + uint256 price = 1.12121111111 ether; + uint256 numberPurchases = 3; + + OrderStructs.Taker[] memory takerBids = new OrderStructs.Taker[](numberPurchases); + bytes[] memory signatures = new bytes[](numberPurchases); + OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](numberPurchases); + + // 1. Invalid maker asks length + OrderStructs.Maker[] memory makerAsks = new OrderStructs.Maker[](numberPurchases - 1); + + vm.expectRevert(LengthsInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + + // 2. Invalid signatures length + makerAsks = new OrderStructs.Maker[](numberPurchases); + signatures = new bytes[](numberPurchases - 1); + + vm.expectRevert(LengthsInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + + // 3. Invalid merkle trees length + signatures = new bytes[](numberPurchases); + merkleTrees = new OrderStructs.MerkleTree[](numberPurchases - 1); + + vm.expectRevert(LengthsInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( + takerBids, + makerAsks, + signatures, + merkleTrees, + _EMPTY_AFFILIATE, + false + ); + } + + function _calculateExpectedFees( + uint256 price, + uint256 royaltyFeeBp + ) private pure returns (uint256[3] memory expectedFees) { + expectedFees[2] = (price * _standardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; + expectedFees[1] = (price * royaltyFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; + if (expectedFees[2] + expectedFees[1] < ((price * _minTotalFeeBp) / ONE_HUNDRED_PERCENT_IN_BP)) { + expectedFees[2] = ((price * _minTotalFeeBp) / ONE_HUNDRED_PERCENT_IN_BP) - expectedFees[1]; + } + expectedFees[0] = price - (expectedFees[1] + expectedFees[2]); + } + + function _assertSuccessfulExecutionThroughWETH( + address buyer, + address seller, + uint256 price, + uint256[3] memory expectedFees + ) private { + // Buyer has received the asset + assertEq(mockERC721.ownerOf(itemId), buyer); + // Buyer pays the whole price + assertEq(weth.balanceOf(buyer), _initialWETHBalanceUser - price); + // Seller receives 99.5% of the whole price + assertEq(weth.balanceOf(seller), _initialWETHBalanceUser + expectedFees[0]); + assertEq( + weth.balanceOf(address(protocolFeeRecipient)), + expectedFees[2], + "ProtocolFeeRecipient should receive 1.5% of the whole price" + ); + // Royalty recipient receives 0.5% of the whole price + assertEq(weth.balanceOf(_royaltyRecipient), _initialWETHBalanceRoyaltyRecipient + expectedFees[1]); + } + + function _assertSuccessfulExecutionThroughETH( + address buyer, + address seller, + uint256 price, + uint256[3] memory expectedFees + ) private { + assertEq(mockERC721.ownerOf(itemId), buyer); + // Buyer pays the whole price + assertEq(address(buyer).balance, _initialETHBalanceUser - price); + // Seller receives 99.5% of the whole price + assertEq(address(seller).balance, _initialETHBalanceUser + expectedFees[0]); + // Royalty recipient receives 0.5% of the whole price + assertEq(address(_royaltyRecipient).balance, _initialETHBalanceRoyaltyRecipient + expectedFees[1]); + } +} diff --git a/contracts/test/foundry/marketplace/StrategyManager.t.sol b/contracts/test/foundry/marketplace/StrategyManager.t.sol new file mode 100644 index 00000000..4d18eba3 --- /dev/null +++ b/contracts/test/foundry/marketplace/StrategyManager.t.sol @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Interfaces +import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; +import { IStrategy } from "@hypercerts/marketplace/interfaces/IStrategy.sol"; + +// Random strategy +import { StrategyCollectionOffer } from "@hypercerts/marketplace/executionStrategies/StrategyCollectionOffer.sol"; + +// Base test +import { ProtocolBase } from "./ProtocolBase.t.sol"; + +contract FalseBaseStrategy is IStrategy { + /** + * @inheritdoc IStrategy + */ + function isMakerOrderValid( + OrderStructs.Maker calldata, + bytes4 + ) external view override returns (bool isValid, bytes4 errorSelector) { + // + } + + /** + * @inheritdoc IStrategy + */ + function isLooksRareV2Strategy() external pure override returns (bool) { + return false; + } +} + +contract StrategyManagerTest is ProtocolBase, IStrategyManager { + function setUp() public { + _setUp(); + } + + /** + * Owner can discontinue strategy + */ + function testOwnerCanDiscontinueStrategy() public asPrankedUser(_owner) { + uint256 strategyId = 0; + uint16 standardProtocolFeeBp = 100; + uint16 minTotalFeeBp = 200; + bool isActive = false; + + vm.expectEmit(false, false, false, true); + emit StrategyUpdated(strategyId, isActive, standardProtocolFeeBp, minTotalFeeBp); + looksRareProtocol.updateStrategy(strategyId, isActive, standardProtocolFeeBp, minTotalFeeBp); + + ( + bool strategyIsActive, + uint16 strategyStandardProtocolFee, + uint16 strategyMinTotalFee, + uint16 strategyMaxProtocolFee, + bytes4 strategySelector, + bool strategyIsMakerBid, + address strategyImplementation + ) = looksRareProtocol.strategyInfo(strategyId); + + assertFalse(strategyIsActive); + assertEq(strategyStandardProtocolFee, standardProtocolFeeBp); + assertEq(strategyMinTotalFee, minTotalFeeBp); + assertEq(strategyMaxProtocolFee, _maxProtocolFeeBp); + assertEq(strategySelector, _EMPTY_BYTES4); + assertFalse(strategyIsMakerBid); + assertEq(strategyImplementation, address(0)); + } + + function testNewStrategyEventIsEmitted() public asPrankedUser(_owner) { + StrategyCollectionOffer strategy = new StrategyCollectionOffer(); + + uint256 strategyId = 1; + bytes4 selector = StrategyCollectionOffer.executeCollectionStrategyWithTakerAsk.selector; + bool isMakerBid = true; + address implementation = address(strategy); + + vm.expectEmit(true, false, false, true); + emit NewStrategy( + strategyId, + _standardProtocolFeeBp, + _minTotalFeeBp, + _maxProtocolFeeBp, + selector, + isMakerBid, + implementation + ); + + _addStrategy(implementation, selector, isMakerBid); + } + + /** + * Owner can change protocol fee information + */ + function testOwnerCanChangeStrategyProtocolFees() public asPrankedUser(_owner) { + uint256 strategyId = 0; + uint16 newStandardProtocolFeeBp = 100; + uint16 newMinTotalFeeBp = 200; + bool isActive = true; + + vm.expectEmit(false, false, false, true); + emit StrategyUpdated(strategyId, isActive, newStandardProtocolFeeBp, newMinTotalFeeBp); + looksRareProtocol.updateStrategy(strategyId, isActive, newStandardProtocolFeeBp, newMinTotalFeeBp); + + ( + bool strategyIsActive, + uint16 strategyStandardProtocolFee, + uint16 strategyMinTotalFee, + uint16 strategyMaxProtocolFee, + bytes4 strategySelector, + bool strategyIsMakerBid, + address strategyImplementation + ) = looksRareProtocol.strategyInfo(strategyId); + + assertTrue(strategyIsActive); + assertEq(strategyStandardProtocolFee, newStandardProtocolFeeBp); + assertEq(strategyMinTotalFee, newMinTotalFeeBp); + assertEq(strategyMaxProtocolFee, _maxProtocolFeeBp); + assertEq(strategySelector, _EMPTY_BYTES4); + assertFalse(strategyIsMakerBid); + assertEq(strategyImplementation, address(0)); + } + + /** + * Owner functions for strategy updates revert as expected under multiple revertion scenarios + */ + function testOwnerRevertionsForInvalidParametersUpdateStrategy() public asPrankedUser(_owner) { + ( + , + uint16 currentStandardProtocolFee, + uint16 currentMinTotalFee, + uint16 maxProtocolFeeBp, + , + , + + ) = looksRareProtocol.strategyInfo(0); + + // 1. newStandardProtocolFee is higher than maxProtocolFeeBp + uint16 newStandardProtocolFee = maxProtocolFeeBp + 1; + uint16 newMinTotalFee = currentMinTotalFee; + vm.expectRevert(StrategyProtocolFeeTooHigh.selector); + looksRareProtocol.updateStrategy(0, true, newStandardProtocolFee, newMinTotalFee); + + // 2. newMinTotalFee is higher than maxProtocolFeeBp + newStandardProtocolFee = currentStandardProtocolFee; + newMinTotalFee = maxProtocolFeeBp + 1; + vm.expectRevert(StrategyProtocolFeeTooHigh.selector); + looksRareProtocol.updateStrategy(0, true, newStandardProtocolFee, newMinTotalFee); + + // 3. It reverts if strategy doesn't exist + vm.expectRevert(StrategyNotUsed.selector); + looksRareProtocol.updateStrategy(1, true, currentStandardProtocolFee, currentMinTotalFee); + } + + /** + * Owner functions for strategy additions revert as expected under multiple revertion scenarios + */ + function testOwnerRevertionsForInvalidParametersAddStrategy() public asPrankedUser(_owner) { + uint16 standardProtocolFeeBp = 250; + uint16 minTotalFeeBp = 300; + uint16 maxProtocolFeeBp = 300; + address implementation = address(0); + + // 1. standardProtocolFeeBp is higher than maxProtocolFeeBp + maxProtocolFeeBp = standardProtocolFeeBp - 1; + vm.expectRevert(abi.encodeWithSelector(IStrategyManager.StrategyProtocolFeeTooHigh.selector)); + looksRareProtocol.addStrategy( + standardProtocolFeeBp, + minTotalFeeBp, + maxProtocolFeeBp, + _EMPTY_BYTES4, + true, + implementation + ); + + // 2. minTotalFeeBp is higher than maxProtocolFeeBp + maxProtocolFeeBp = minTotalFeeBp - 1; + vm.expectRevert(abi.encodeWithSelector(IStrategyManager.StrategyProtocolFeeTooHigh.selector)); + looksRareProtocol.addStrategy( + standardProtocolFeeBp, + minTotalFeeBp, + maxProtocolFeeBp, + _EMPTY_BYTES4, + true, + implementation + ); + + // 3. maxProtocolFeeBp is higher than _MAX_PROTOCOL_FEE + maxProtocolFeeBp = 500 + 1; + vm.expectRevert(abi.encodeWithSelector(IStrategyManager.StrategyProtocolFeeTooHigh.selector)); + looksRareProtocol.addStrategy( + standardProtocolFeeBp, + minTotalFeeBp, + maxProtocolFeeBp, + _EMPTY_BYTES4, + true, + implementation + ); + } + + function testAddStrategyNoSelector() public asPrankedUser(_owner) { + vm.expectRevert(IStrategyManager.StrategyHasNoSelector.selector); + _addStrategy(address(0), _EMPTY_BYTES4, true); + } + + function testAddStrategyNotV2Strategy() public asPrankedUser(_owner) { + bytes4 randomSelector = StrategyCollectionOffer.executeCollectionStrategyWithTakerAsk.selector; + + // 1. EOA + vm.expectRevert(); + _addStrategy(address(0), randomSelector, true); + + // 2. Invalid contract (e.g. LooksRareProtocol) + vm.expectRevert(); + _addStrategy(address(looksRareProtocol), randomSelector, true); + + // 3. Contract that implements the function but returns false + FalseBaseStrategy falseStrategy = new FalseBaseStrategy(); + + vm.expectRevert(NotV2Strategy.selector); + _addStrategy(address(falseStrategy), randomSelector, true); + } + + function testAddStrategyNotOwner() public { + vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); + _addStrategy(address(0), _EMPTY_BYTES4, true); + } + + function testUpdateStrategyNotOwner() public { + vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); + looksRareProtocol.updateStrategy(0, false, 299, 100); + } +} diff --git a/contracts/test/foundry/marketplace/TransferManager.t.sol b/contracts/test/foundry/marketplace/TransferManager.t.sol new file mode 100644 index 00000000..6d7f4643 --- /dev/null +++ b/contracts/test/foundry/marketplace/TransferManager.t.sol @@ -0,0 +1,535 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Core contracts +import { LooksRareProtocol } from "@hypercerts/marketplace/LooksRareProtocol.sol"; +import { ITransferManager, TransferManager } from "@hypercerts/marketplace/TransferManager.sol"; +import { AmountInvalid, LengthsInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; + +// Mocks and other utils +import { MockERC721 } from "../../mock/MockERC721.sol"; +import { MockERC1155 } from "../../mock/MockERC1155.sol"; +import { TestHelpers } from "./utils/TestHelpers.sol"; +import { TestParameters } from "./utils/TestParameters.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; + +contract TransferManagerTest is ITransferManager, TestHelpers, TestParameters { + address[] public operators; + MockERC721 public mockERC721; + MockERC1155 public mockERC1155; + TransferManager public transferManager; + + uint256 private constant tokenIdERC721 = 55; + uint256 private constant tokenId1ERC1155 = 1; + uint256 private constant amount1ERC1155 = 2; + uint256 private constant tokenId2ERC1155 = 2; + uint256 private constant amount2ERC1155 = 5; + + /** + * 0. Internal helper functions + */ + + function _grantApprovals(address user) private asPrankedUser(user) { + mockERC721.setApprovalForAll(address(transferManager), true); + mockERC1155.setApprovalForAll(address(transferManager), true); + address[] memory approvedOperators = new address[](1); + approvedOperators[0] = _transferrer; + + vm.expectEmit(true, false, false, true); + emit ApprovalsGranted(user, approvedOperators); + transferManager.grantApprovals(approvedOperators); + } + + function _allowOperator(address transferrer) private { + vm.prank(_owner); + vm.expectEmit(true, false, false, true); + emit OperatorAllowed(transferrer); + transferManager.allowOperator(transferrer); + } + + function setUp() public asPrankedUser(_owner) { + transferManager = new TransferManager(_owner); + mockERC721 = new MockERC721(); + mockERC1155 = new MockERC1155(); + operators.push(_transferrer); + + vm.deal(_transferrer, 100 ether); + vm.deal(_sender, 100 ether); + } + + /** + * 1. Happy cases + */ + + function testTransferSingleItemERC721() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + uint256 itemId = 500; + + vm.prank(_sender); + mockERC721.mint(_sender, itemId); + + uint256[] memory itemIds = new uint256[](1); + itemIds[0] = itemId; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1; + + vm.prank(_transferrer); + transferManager.transferItemsERC721(address(mockERC721), _sender, _recipient, itemIds, amounts); + + assertEq(mockERC721.ownerOf(itemId), _recipient); + } + + function testTransferSingleItemERC1155() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + uint256 itemId = 1; + uint256 amount = 2; + + mockERC1155.mint(_sender, itemId, amount); + + uint256[] memory itemIds = new uint256[](1); + itemIds[0] = itemId; + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount; + + vm.prank(_transferrer); + transferManager.transferItemsERC1155(address(mockERC1155), _sender, _recipient, itemIds, amounts); + + assertEq(mockERC1155.balanceOf(_recipient, itemId), amount); + } + + function testTransferBatchItemsERC721() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + uint256 tokenId1 = 1; + uint256 tokenId2 = 2; + + uint256[] memory itemIds = new uint256[](2); + itemIds[0] = tokenId1; + itemIds[1] = tokenId2; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1; + amounts[1] = 1; + + mockERC721.batchMint(_sender, itemIds); + + vm.prank(_transferrer); + transferManager.transferItemsERC721(address(mockERC721), _sender, _recipient, itemIds, amounts); + + assertEq(mockERC721.ownerOf(tokenId1), _recipient); + assertEq(mockERC721.ownerOf(tokenId2), _recipient); + } + + function testTransferBatchItemsERC1155() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + uint256 tokenId1 = 1; + uint256 amount1 = 2; + uint256 tokenId2 = 2; + uint256 amount2 = 5; + + mockERC1155.mint(_sender, tokenId1, amount1); + mockERC1155.mint(_sender, tokenId2, amount2); + + uint256[] memory itemIds = new uint256[](2); + itemIds[0] = tokenId1; + itemIds[1] = tokenId2; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = amount1; + amounts[1] = amount2; + + vm.prank(_transferrer); + transferManager.transferItemsERC1155(address(mockERC1155), _sender, _recipient, itemIds, amounts); + + assertEq(mockERC1155.balanceOf(_recipient, tokenId1), amount1); + assertEq(mockERC1155.balanceOf(_recipient, tokenId2), amount2); + } + + function testTransferBatchItemsAcrossCollectionERC721AndERC1155() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + ITransferManager.BatchTransferItem[] memory items = _generateValidBatchTransferItems(); + + vm.prank(_transferrer); + transferManager.transferBatchItemsAcrossCollections(items, _sender, _recipient); + + assertEq(mockERC721.ownerOf(tokenIdERC721), _recipient); + assertEq(mockERC1155.balanceOf(_recipient, tokenId1ERC1155), amount1ERC1155); + assertEq(mockERC1155.balanceOf(_recipient, tokenId2ERC1155), amount2ERC1155); + } + + function testTransferBatchItemsAcrossCollectionERC721AndERC1155ByOwner() public asPrankedUser(_sender) { + mockERC721.setApprovalForAll(address(transferManager), true); + mockERC1155.setApprovalForAll(address(transferManager), true); + + ITransferManager.BatchTransferItem[] memory items = _generateValidBatchTransferItems(); + + transferManager.transferBatchItemsAcrossCollections(items, _sender, _recipient); + + assertEq(mockERC721.ownerOf(tokenIdERC721), _recipient); + assertEq(mockERC1155.balanceOf(_recipient, tokenId1ERC1155), amount1ERC1155); + assertEq(mockERC1155.balanceOf(_recipient, tokenId2ERC1155), amount2ERC1155); + } + + /** + * 2. Revertion patterns + */ + function testTransferItemsERC721AmountIsNotOne(uint256 amount) public { + vm.assume(amount != 1); + + _allowOperator(_transferrer); + _grantApprovals(_sender); + + uint256 itemId = 500; + + mockERC721.mint(_sender, itemId); + + uint256[] memory itemIds = new uint256[](1); + itemIds[0] = itemId; + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount; + + vm.expectRevert(AmountInvalid.selector); + vm.prank(_transferrer); + transferManager.transferItemsERC721(address(mockERC721), _sender, _recipient, itemIds, amounts); + } + + function testTransferSingleItemERC1155AmountIsZero() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + uint256 itemId = 500; + + mockERC1155.mint(_sender, itemId, 1); + + uint256[] memory itemIds = new uint256[](1); + itemIds[0] = itemId; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + + vm.expectRevert(AmountInvalid.selector); + vm.prank(_transferrer); + transferManager.transferItemsERC1155(address(mockERC1155), _sender, _recipient, itemIds, amounts); + } + + function testTransferMultipleItemsERC1155AmountIsZero() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + uint256 itemIdOne = 500; + uint256 itemIdTwo = 501; + + mockERC1155.mint(_sender, itemIdOne, 1); + mockERC1155.mint(_sender, itemIdTwo, 1); + + uint256[] memory itemIds = new uint256[](2); + itemIds[0] = itemIdOne; + itemIds[1] = itemIdTwo; + uint256[] memory amounts = new uint256[](2); + amounts[0] = 0; + amounts[1] = 0; + + vm.expectRevert(AmountInvalid.selector); + vm.prank(_transferrer); + transferManager.transferItemsERC1155(address(mockERC1155), _sender, _recipient, itemIds, amounts); + } + + function testTransferBatchItemsAcrossCollectionZeroLength() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + ITransferManager.BatchTransferItem[] memory items = new ITransferManager.BatchTransferItem[](0); + + vm.expectRevert(LengthsInvalid.selector); + vm.prank(_transferrer); + transferManager.transferBatchItemsAcrossCollections(items, _sender, _recipient); + } + + function testCannotBatchTransferIfERC721AmountIsNotOne(uint256 amount) public { + vm.assume(amount != 1); + + _allowOperator(_transferrer); + _grantApprovals(_sender); + + ITransferManager.BatchTransferItem[] memory items = _generateValidBatchTransferItems(); + items[1].amounts[0] = amount; + + vm.expectRevert(AmountInvalid.selector); + vm.prank(_sender); + transferManager.transferBatchItemsAcrossCollections(items, _sender, _recipient); + } + + function testCannotBatchTransferIfERC1155AmountIsZero() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + ITransferManager.BatchTransferItem[] memory items = _generateValidBatchTransferItems(); + items[0].amounts[0] = 0; + + vm.expectRevert(AmountInvalid.selector); + vm.prank(_sender); + transferManager.transferBatchItemsAcrossCollections(items, _sender, _recipient); + } + + function testTransferBatchItemsAcrossCollectionPerCollectionItemIdsLengthZero() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + ITransferManager.BatchTransferItem[] memory items = _generateValidBatchTransferItems(); + items[0].itemIds = new uint256[](0); + items[0].amounts = new uint256[](0); + + vm.prank(_transferrer); + vm.expectRevert(LengthsInvalid.selector); + transferManager.transferBatchItemsAcrossCollections(items, _sender, _recipient); + } + + function testCannotTransferERC721IfOperatorApprovalsRevokedByUserOrOperatorRemovedByOwner() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + // 1. User revokes the operator + vm.prank(_sender); + vm.expectEmit(false, false, false, true); + emit ApprovalsRemoved(_sender, operators); + transferManager.revokeApprovals(operators); + + uint256 itemId = 500; + uint256[] memory itemIds = new uint256[](1); + itemIds[0] = itemId; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1; + + vm.prank(_transferrer); + vm.expectRevert(ITransferManager.TransferCallerInvalid.selector); + transferManager.transferItemsERC721(address(mockERC721), _sender, _recipient, itemIds, amounts); + + // 2. Sender grants again approvals but owner removes the operators + _grantApprovals(_sender); + vm.prank(_owner); + vm.expectEmit(false, false, false, true); + emit OperatorRemoved(_transferrer); + transferManager.removeOperator(_transferrer); + + vm.prank(_transferrer); + vm.expectRevert(ITransferManager.TransferCallerInvalid.selector); + transferManager.transferItemsERC721(address(mockERC721), _sender, _recipient, itemIds, amounts); + } + + function testCannotTransferERC1155IfOperatorApprovalsRevokedByUserOrOperatorRemovedByOwner() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + // 1. User revokes the operator + vm.prank(_sender); + vm.expectEmit(false, false, false, true); + emit ApprovalsRemoved(_sender, operators); + transferManager.revokeApprovals(operators); + + uint256 itemId = 500; + uint256[] memory itemIds = new uint256[](1); + itemIds[0] = itemId; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 5; + + vm.prank(_transferrer); + vm.expectRevert(ITransferManager.TransferCallerInvalid.selector); + transferManager.transferItemsERC1155(address(mockERC1155), _sender, _recipient, itemIds, amounts); + + // 2. Sender grants again approvals but owner removes the operators + _grantApprovals(_sender); + vm.prank(_owner); + vm.expectEmit(false, false, false, true); + emit OperatorRemoved(_transferrer); + transferManager.removeOperator(_transferrer); + + vm.prank(_transferrer); + vm.expectRevert(ITransferManager.TransferCallerInvalid.selector); + transferManager.transferItemsERC1155(address(mockERC1155), _sender, _recipient, itemIds, amounts); + } + + function testCannotBatchTransferIfOperatorApprovalsRevoked() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + // 1. User revokes the operator + vm.prank(_sender); + vm.expectEmit(false, false, false, true); + emit ApprovalsRemoved(_sender, operators); + transferManager.revokeApprovals(operators); + + ITransferManager.BatchTransferItem[] memory items = _generateValidBatchTransferItems(); + + vm.prank(_transferrer); + vm.expectRevert(ITransferManager.TransferCallerInvalid.selector); + transferManager.transferBatchItemsAcrossCollections(items, _sender, _recipient); + + // 2. Sender grants again approvals but owner removes the operators + _grantApprovals(_sender); + vm.prank(_owner); + vm.expectEmit(false, false, false, true); + emit OperatorRemoved(_transferrer); + transferManager.removeOperator(_transferrer); + + vm.prank(_transferrer); + vm.expectRevert(ITransferManager.TransferCallerInvalid.selector); + transferManager.transferBatchItemsAcrossCollections(items, _sender, _recipient); + } + + function testCannotTransferERC721OrERC1155IfArrayLengthIs0() public { + uint256[] memory emptyArrayUint256 = new uint256[](0); + + // 1. ERC721 + vm.expectRevert(LengthsInvalid.selector); + transferManager.transferItemsERC721( + address(mockERC721), + _sender, + _recipient, + emptyArrayUint256, + emptyArrayUint256 + ); + + // 2. ERC1155 length is 0 + vm.expectRevert(LengthsInvalid.selector); + transferManager.transferItemsERC1155( + address(mockERC1155), + _sender, + _recipient, + emptyArrayUint256, + emptyArrayUint256 + ); + } + + function testCannotTransferERC1155IfArrayLengthDiffers() public { + uint256[] memory itemIds = new uint256[](2); + uint256[] memory amounts = new uint256[](3); + + vm.expectRevert(LengthsInvalid.selector); + transferManager.transferItemsERC1155(address(mockERC1155), _sender, _recipient, itemIds, amounts); + } + + function testUserCannotGrantOrRevokeApprovalsIfArrayLengthIs0() public { + address[] memory emptyArrayAddresses = new address[](0); + + // 1. Grant approvals + vm.expectRevert(LengthsInvalid.selector); + transferManager.grantApprovals(emptyArrayAddresses); + + // 2. Revoke approvals + vm.expectRevert(LengthsInvalid.selector); + transferManager.revokeApprovals(emptyArrayAddresses); + } + + function testUserCannotGrantApprovalIfOperatorOperatorNotAllowed() public asPrankedUser(_owner) { + address randomOperator = address(420); + transferManager.allowOperator(randomOperator); + vm.expectRevert(ITransferManager.OperatorAlreadyAllowed.selector); + transferManager.allowOperator(randomOperator); + } + + function testAllowOperatorNotOwner() public { + vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); + transferManager.allowOperator(address(0)); + } + + function testOwnerCannotallowOperatorIfOperatorAlreadyAllowed() public asPrankedUser(_owner) { + address randomOperator = address(420); + transferManager.allowOperator(randomOperator); + vm.expectRevert(ITransferManager.OperatorAlreadyAllowed.selector); + transferManager.allowOperator(randomOperator); + } + + function testOwnerCannotRemoveOperatorIfOperatorNotAllowed() public asPrankedUser(_owner) { + address notOperator = address(420); + vm.expectRevert(ITransferManager.OperatorNotAllowed.selector); + transferManager.removeOperator(notOperator); + } + + function testUserCannotGrantApprovalsIfOperatorNotAllowed() public { + address[] memory approvedOperators = new address[](1); + approvedOperators[0] = _transferrer; + + vm.expectRevert(ITransferManager.OperatorNotAllowed.selector); + vm.prank(_sender); + transferManager.grantApprovals(approvedOperators); + } + + function testUserCannotGrantApprovalsIfOperatorAlreadyApprovedByUser() public { + _allowOperator(_transferrer); + _grantApprovals(_sender); + + address[] memory approvedOperators = new address[](1); + approvedOperators[0] = _transferrer; + + vm.expectRevert(ITransferManager.OperatorAlreadyApprovedByUser.selector); + vm.prank(_sender); + transferManager.grantApprovals(approvedOperators); + } + + function testUserCannotRevokeApprovalsIfOperatorNotApprovedByUser() public { + address[] memory approvedOperators = new address[](1); + approvedOperators[0] = _transferrer; + + vm.expectRevert(ITransferManager.OperatorNotApprovedByUser.selector); + vm.prank(_sender); + transferManager.revokeApprovals(approvedOperators); + } + + function testRemoveOperatorNotOwner() public { + vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); + transferManager.removeOperator(address(0)); + } + + function _generateValidBatchTransferItems() private returns (BatchTransferItem[] memory items) { + items = new ITransferManager.BatchTransferItem[](2); + + { + mockERC721.mint(_sender, tokenIdERC721); + mockERC1155.mint(_sender, tokenId1ERC1155, amount1ERC1155); + mockERC1155.mint(_sender, tokenId2ERC1155, amount2ERC1155); + + uint256[] memory tokenIdsERC1155 = new uint256[](2); + tokenIdsERC1155[0] = tokenId1ERC1155; + tokenIdsERC1155[1] = tokenId2ERC1155; + + uint256[] memory amountsERC1155 = new uint256[](2); + amountsERC1155[0] = amount1ERC1155; + amountsERC1155[1] = amount2ERC1155; + + uint256[] memory tokenIdsERC721 = new uint256[](1); + tokenIdsERC721[0] = tokenIdERC721; + + uint256[] memory amountsERC721 = new uint256[](1); + amountsERC721[0] = 1; + + items[0] = ITransferManager.BatchTransferItem({ + collection: address(mockERC1155), + collectionType: CollectionType.ERC1155, + itemIds: tokenIdsERC1155, + amounts: amountsERC1155 + }); + items[1] = ITransferManager.BatchTransferItem({ + collection: address(mockERC721), + collectionType: CollectionType.ERC721, + itemIds: tokenIdsERC721, + amounts: amountsERC721 + }); + } + } +} diff --git a/contracts/test/foundry/marketplace/assembly/VerifyOrderTimestampValidityEquivalence.t.sol b/contracts/test/foundry/marketplace/assembly/VerifyOrderTimestampValidityEquivalence.t.sol new file mode 100644 index 00000000..9a124211 --- /dev/null +++ b/contracts/test/foundry/marketplace/assembly/VerifyOrderTimestampValidityEquivalence.t.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { Test } from "forge-std/Test.sol"; + +// Assembly +import { OutsideOfTimeRange_error_selector, OutsideOfTimeRange_error_length, Error_selector_offset } from "@hypercerts/marketplace/constants/AssemblyConstants.sol"; + +contract NonAssemblyCode { + error OutsideOfTimeRange(); + + function run(uint256 startTime, uint256 endTime) external view returns (bool) { + if (startTime > block.timestamp || endTime < block.timestamp) revert OutsideOfTimeRange(); + return true; + } +} + +contract AssemblyCode { + function run(uint256 startTime, uint256 endTime) external view returns (bool) { + assembly { + if or(gt(startTime, timestamp()), lt(endTime, timestamp())) { + mstore(0x00, OutsideOfTimeRange_error_selector) + revert(Error_selector_offset, OutsideOfTimeRange_error_length) + } + } + return true; + } +} + +contract VerifyOrderTimestampValidityEquivalenceTest is Test { + AssemblyCode private assemblyCode; + NonAssemblyCode private nonAssemblyCode; + + function setUp() public { + assemblyCode = new AssemblyCode(); + nonAssemblyCode = new NonAssemblyCode(); + } + + /** + * @dev The gap between start and end time is always at least + * 3 seconds so that we can test the 2 boundaries as well + * as the 2 timestamps inside the boundaries + */ + function testEquivalenceWithinBoundaries(uint256 startTime, uint256 endTime) public { + vm.assume(endTime > 3 && startTime < endTime - 3); + + vm.warp(startTime); + assertTrue(assemblyCode.run(startTime, endTime)); + assertTrue(nonAssemblyCode.run(startTime, endTime)); + + vm.warp(startTime + 1); + assertTrue(assemblyCode.run(startTime, endTime)); + assertTrue(nonAssemblyCode.run(startTime, endTime)); + + vm.warp(endTime - 1); + assertTrue(assemblyCode.run(startTime, endTime)); + assertTrue(nonAssemblyCode.run(startTime, endTime)); + + vm.warp(endTime); + assertTrue(assemblyCode.run(startTime, endTime)); + assertTrue(nonAssemblyCode.run(startTime, endTime)); + } + + function testEquivalenceTooEarly(uint256 startTime, uint256 endTime) public { + vm.assume(startTime > 0 && startTime < endTime); + + vm.warp(startTime - 1); + + vm.expectRevert(NonAssemblyCode.OutsideOfTimeRange.selector); + assemblyCode.run(startTime, endTime); + + vm.expectRevert(NonAssemblyCode.OutsideOfTimeRange.selector); + nonAssemblyCode.run(startTime, endTime); + } + + function testEquivalenceTooLate(uint256 startTime, uint256 endTime) public { + vm.assume(endTime > 0 && endTime < type(uint256).max && startTime < endTime); + + vm.warp(endTime + 1); + + vm.expectRevert(NonAssemblyCode.OutsideOfTimeRange.selector); + assemblyCode.run(startTime, endTime); + + vm.expectRevert(NonAssemblyCode.OutsideOfTimeRange.selector); + nonAssemblyCode.run(startTime, endTime); + } +} diff --git a/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol b/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol new file mode 100644 index 00000000..df930c71 --- /dev/null +++ b/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol @@ -0,0 +1,483 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries and interfaces +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; + +// Errors and constants +import { AmountInvalid, BidTooLow, OrderInvalid, CurrencyInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { ChainlinkPriceInvalid, PriceNotRecentEnough } from "@hypercerts/marketplace/errors/ChainlinkErrors.sol"; +import { MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE, MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE, STRATEGY_NOT_ACTIVE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Strategies +import { StrategyChainlinkUSDDynamicAsk } from "@hypercerts/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol"; + +// Mocks and other tests +import { MockChainlinkAggregator } from "../../../../mock/MockChainlinkAggregator.sol"; +import { MockERC20 } from "../../../../mock/MockERC20.sol"; +import { ProtocolBase } from "../../ProtocolBase.t.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { + StrategyChainlinkUSDDynamicAsk public strategyUSDDynamicAsk; + bytes4 public selector = StrategyChainlinkUSDDynamicAsk.executeStrategyWithTakerBid.selector; + + // At block 15740567 + // roundId uint80 : 92233720368547793259 + // answer int256 : 126533075631 + // startedAt uint256 : 1665680123 + // updatedAt uint256 : 1665680123 + // answeredInRound uint80 : 92233720368547793259 + uint256 private constant CHAINLINK_PRICE_UPDATED_AT = 1665680123; + uint256 private constant FORKED_BLOCK_NUMBER = 15740567; + uint256 private constant LATEST_CHAINLINK_ANSWER_IN_WAD = 126533075631 * 1e10; + uint256 private constant MAXIMUM_LATENCY = 3_600 seconds; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl("mainnet"), FORKED_BLOCK_NUMBER); + _setUp(); + _setUpUsers(); + _setUpNewStrategy(); + } + + function _setUpNewStrategy() private asPrankedUser(_owner) { + strategyUSDDynamicAsk = new StrategyChainlinkUSDDynamicAsk( + _owner, + address(weth), + 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419 // Mainnet address of the Chainlink price feed + ); + _addStrategy(address(strategyUSDDynamicAsk), selector, false); + } + + function _createMakerAskAndTakerBid( + uint256 numberOfItems, + uint256 numberOfAmounts, + uint256 desiredSalePriceInUSD + ) private returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) { + uint256[] memory itemIds = new uint256[](numberOfItems); + for (uint256 i; i < numberOfItems; ) { + mockERC721.mint(makerUser, i + 1); + itemIds[i] = i + 1; + unchecked { + ++i; + } + } + + uint256[] memory amounts = new uint256[](numberOfAmounts); + for (uint256 i; i < numberOfAmounts; ) { + amounts[i] = 1; + unchecked { + ++i; + } + } + + newMakerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: 0.99 ether, + itemId: 1 + }); + + newMakerAsk.itemIds = itemIds; + newMakerAsk.amounts = amounts; + newMakerAsk.additionalParameters = abi.encode(desiredSalePriceInUSD); + + newTakerBid = OrderStructs.Taker(takerUser, abi.encode(1 ether)); + } + + function testNewStrategy() public { + _assertStrategyAttributes(address(strategyUSDDynamicAsk), selector, false); + } + + function testMaxLatency() public { + assertEq(strategyUSDDynamicAsk.maxLatency(), 3_600); + } + + function testUSDDynamicAskChainlinkPriceInvalid() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + MockChainlinkAggregator priceFeed = new MockChainlinkAggregator(); + vm.etch(CHAINLINK_ETH_USD_PRICE_FEED, address(priceFeed).code); + + MockChainlinkAggregator(CHAINLINK_ETH_USD_PRICE_FEED).setAnswer(-1); + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertFalse(isValid); + assertEq(errorSelector, ChainlinkPriceInvalid.selector); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + MockChainlinkAggregator(CHAINLINK_ETH_USD_PRICE_FEED).setAnswer(0); + (isValid, errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertFalse(isValid); + assertEq(errorSelector, ChainlinkPriceInvalid.selector); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testUSDDynamicAskUSDValueGreaterThanOrEqualToMinAcceptedEthValue() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertTrue(isValid); + assertEq(errorSelector, _EMPTY_BYTES4); + + // Execute taker bid transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Taker user has received the asset + assertEq(mockERC721.ownerOf(1), takerUser); + // Taker bid user pays the whole price + assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser - 1 ether); + // Maker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser + 0.995 ether); + } + + function testUSDDynamicAskUSDValueLessThanMinAcceptedEthValue() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: (LATEST_CHAINLINK_ANSWER_IN_WAD * 98) / 100 + }); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertTrue(isValid); + assertEq(errorSelector, _EMPTY_BYTES4); + + // Execute taker bid transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Taker user has received the asset + assertEq(mockERC721.ownerOf(1), takerUser); + + // Taker bid user pays the whole price + assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser - 0.99 ether); + // Maker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser + 0.98505 ether); + } + + // This tests that we can handle fractions + function testUSDDynamicAskUSDValueLessThanOneETH() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD / 2 + }); + + makerAsk.price = 0.49 ether; + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertTrue(isValid); + assertEq(errorSelector, _EMPTY_BYTES4); + + // Execute taker bid transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Taker user has received the asset + assertEq(mockERC721.ownerOf(1), takerUser); + + // Taker bid user pays the whole price + assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser - 0.5 ether); + // Maker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser + 0.4975 ether); + } + + function testUSDDynamicAskBidderOverpaid() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + makerAsk.currency = ETH; + // Bidder overpays by 0.1 ETH + uint256 maxPrice = 1.1 ether; + takerBid.additionalParameters = abi.encode(maxPrice); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + uint256 initialETHBalanceTakerUser = address(takerUser).balance; + uint256 initialETHBalanceMakerUser = address(makerUser).balance; + + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertTrue(isValid); + assertEq(errorSelector, _EMPTY_BYTES4); + + // Execute taker bid transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerBid{ value: maxPrice }( + takerBid, + makerAsk, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + + // Taker user has received the asset + assertEq(mockERC721.ownerOf(1), takerUser); + // Taker bid user pays the whole price, but without overpaying + assertEq(address(takerUser).balance, initialETHBalanceTakerUser - 1 ether - 1); + // Maker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq(address(makerUser).balance, initialETHBalanceMakerUser + 0.995 ether); + } + + function testOraclePriceNotRecentEnough() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + makerAsk.startTime = CHAINLINK_PRICE_UPDATED_AT; + uint256 latencyViolationTimestamp = CHAINLINK_PRICE_UPDATED_AT + MAXIMUM_LATENCY + 1 seconds; + makerAsk.endTime = latencyViolationTimestamp; + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + vm.warp(latencyViolationTimestamp); + + bytes4 errorSelector = PriceNotRecentEnough.selector; + + _assertOrderIsInvalid(makerAsk, errorSelector); + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testCannotExecuteIfNotWETHOrETH() public { + MockERC20 fakeCurrency = new MockERC20(); + vm.prank(_owner); + looksRareProtocol.updateCurrencyStatus(address(fakeCurrency), true); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + // Adjust the currency to something creative + makerAsk.currency = address(fakeCurrency); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertFalse(isValid); + assertEq(errorSelector, CurrencyInvalid.selector); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testZeroItemIdsLength() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 0, + numberOfAmounts: 0, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertFalse(isValid); + assertEq(errorSelector, OrderInvalid.selector); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testItemIdsAndAmountsLengthMismatch() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 2, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertFalse(isValid); + assertEq(errorSelector, OrderInvalid.selector); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testWrongQuoteType() public { + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: 1 ether, + itemId: 420 + }); + + (bool orderIsValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerBid, selector); + + assertFalse(orderIsValid); + assertEq(errorSelector, QuoteTypeInvalid.selector); + } + + function testZeroAmount() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + makerAsk.amounts = amounts; + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Valid, taker struct validation only happens during execution + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertFalse(isValid); + assertEq(errorSelector, OrderInvalid.selector); + + vm.prank(takerUser); + vm.expectRevert(AmountInvalid.selector); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testAmountGreaterThanOneForERC721() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 2; + makerAsk.amounts = amounts; + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Valid, taker struct validation only happens during execution + _assertOrderIsInvalid(makerAsk, OrderInvalid.selector); + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.prank(takerUser); + vm.expectRevert(AmountInvalid.selector); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testTakerBidTooLow() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + takerBid.additionalParameters = abi.encode(0.99 ether); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Valid, taker struct validation only happens during execution + _assertOrderIsValid(makerAsk); + _assertValidMakerOrder(makerAsk, signature); + + vm.expectRevert(BidTooLow.selector); + vm.prank(takerUser); + + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testInactiveStrategy() public { + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + desiredSalePriceInUSD: LATEST_CHAINLINK_ANSWER_IN_WAD + }); + + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + vm.prank(_owner); + looksRareProtocol.updateStrategy(1, false, _standardProtocolFeeBp, _minTotalFeeBp); + + _assertOrderIsValid(makerAsk); + _assertMakerOrderReturnValidationCode(makerAsk, signature, STRATEGY_NOT_ACTIVE); + + vm.expectRevert(abi.encodeWithSelector(IExecutionManager.StrategyNotAvailable.selector, 1)); + vm.prank(takerUser); + + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testInvalidSelector() public { + OrderStructs.Maker memory makerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: 2, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: 1 ether, + itemId: 420 + }); + + (bool orderIsValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, bytes4(0)); + assertFalse(orderIsValid); + assertEq(errorSelector, FunctionSelectorInvalid.selector); + } + + function _assertOrderIsInvalid(OrderStructs.Maker memory makerAsk, bytes4 expectedErrorSelector) private { + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertFalse(isValid); + assertEq(errorSelector, expectedErrorSelector); + } + + function _assertOrderIsValid(OrderStructs.Maker memory makerAsk) private { + (bool isValid, bytes4 errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); + assertTrue(isValid); + assertEq(errorSelector, _EMPTY_BYTES4); + } +} diff --git a/contracts/test/foundry/marketplace/executionStrategies/CollectionOffers.t.sol b/contracts/test/foundry/marketplace/executionStrategies/CollectionOffers.t.sol new file mode 100644 index 00000000..429bee91 --- /dev/null +++ b/contracts/test/foundry/marketplace/executionStrategies/CollectionOffers.t.sol @@ -0,0 +1,458 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Murky (third-party) library is used to compute Merkle trees in Solidity +import { Merkle } from "murky/Merkle.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Shared errors +import { AmountInvalid, OrderInvalid, FunctionSelectorInvalid, MerkleProofInvalid, QuoteTypeInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Strategies +import { StrategyCollectionOffer } from "@hypercerts/marketplace/executionStrategies/StrategyCollectionOffer.sol"; + +// Base test +import { ProtocolBase } from "../ProtocolBase.t.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract CollectionOrdersTest is ProtocolBase { + StrategyCollectionOffer public strategyCollectionOffer; + bytes4 public selectorNoProof = strategyCollectionOffer.executeCollectionStrategyWithTakerAsk.selector; + bytes4 public selectorWithProof = strategyCollectionOffer.executeCollectionStrategyWithTakerAskWithProof.selector; + + uint256 private constant price = 1 ether; // Fixed price of sale + bytes32 private constant mockMerkleRoot = bytes32(keccak256("Mock")); // Mock merkle root + + function setUp() public { + _setUp(); + _setUpNewStrategies(); + } + + function _setUpNewStrategies() private asPrankedUser(_owner) { + strategyCollectionOffer = new StrategyCollectionOffer(); + _addStrategy(address(strategyCollectionOffer), selectorNoProof, true); + _addStrategy(address(strategyCollectionOffer), selectorWithProof, true); + } + + function testNewStrategies() public { + _assertStrategyAttributes(address(strategyCollectionOffer), selectorNoProof, true); + + ( + bool strategyIsActive, + uint16 strategyStandardProtocolFee, + uint16 strategyMinTotalFee, + uint16 strategyMaxProtocolFee, + bytes4 strategySelector, + bool strategyIsMakerBid, + address strategyImplementation + ) = looksRareProtocol.strategyInfo(2); + + assertTrue(strategyIsActive); + assertEq(strategyStandardProtocolFee, _standardProtocolFeeBp); + assertEq(strategyMinTotalFee, _minTotalFeeBp); + assertEq(strategyMaxProtocolFee, _maxProtocolFeeBp); + assertEq(strategySelector, selectorWithProof); + assertTrue(strategyIsMakerBid); + assertEq(strategyImplementation, address(strategyCollectionOffer)); + } + + function testMakerBidAmountsLengthNotOne() public { + _setUpUsers(); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + // Adjust strategy for collection order and sign order + // Change array to make it bigger than expected + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1; + makerBid.strategyId = 1; + makerBid.amounts = amounts; + takerAsk.additionalParameters = abi.encode(1, 1); + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertOrderIsInvalid(makerBid, false); + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.expectRevert(OrderInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // With proof + makerBid.strategyId = 2; + makerBid.additionalParameters = abi.encode(mockMerkleRoot); + signature = _signMakerOrder(makerBid, makerUserPK); + + _assertOrderIsInvalid(makerBid, true); + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.expectRevert(OrderInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testZeroAmount() public { + _setUpUsers(); + + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( + address(mockERC721), + address(weth) + ); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + makerBid.amounts = amounts; + makerBid.strategyId = 1; + makerBid.additionalParameters = abi.encode(mockMerkleRoot); + takerAsk.additionalParameters = abi.encode(1, 1); + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertOrderIsInvalid(makerBid, false); + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.prank(takerUser); + vm.expectRevert(AmountInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + /** + * Any itemId for ERC721 (where royalties come from the registry) is sold through a collection taker ask using WETH. + * We use fuzzing to generate the tokenId that is sold. + */ + function testTakerAskCollectionOrderERC721(uint256 tokenId) public { + _setUpUsers(); + + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: 0 // Not used + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Mint asset + mockERC721.mint(takerUser, tokenId); + + // Prepare the taker ask + OrderStructs.Taker memory takerAsk = OrderStructs.Taker(takerUser, abi.encode(tokenId, 1)); + + _assertOrderIsValid(makerBid, false); + _assertValidMakerOrder(makerBid, signature); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + _assertSuccessfulTakerAsk(makerBid, tokenId); + } + + /** + * A collection offer with merkle tree criteria + */ + function testTakerAskCollectionOrderWithMerkleTreeERC721() public { + _setUpUsers(); + + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 2, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: 0 // Not used + }); + + uint256 itemIdInMerkleTree = 2; + (bytes32 merkleRoot, bytes32[] memory proof) = _mintNFTsToOwnerAndGetMerkleRootAndProof({ + owner: takerUser, + numberOfItemsInMerkleTree: 5, + itemIdInMerkleTree: itemIdInMerkleTree + }); + + makerBid.additionalParameters = abi.encode(merkleRoot); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Prepare the taker ask + OrderStructs.Taker memory takerAsk = OrderStructs.Taker(takerUser, abi.encode(itemIdInMerkleTree, proof)); + + // Verify validity of maker bid order + _assertOrderIsValid(makerBid, true); + _assertValidMakerOrder(makerBid, signature); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + _assertSuccessfulTakerAsk(makerBid, itemIdInMerkleTree); + } + + function testTakerAskCannotExecuteWithInvalidProof(uint256 itemIdSold) public { + vm.assume(itemIdSold > 5); + _setUpUsers(); + + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 2, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: 0 // Not used + }); + + (bytes32 merkleRoot, bytes32[] memory proof) = _mintNFTsToOwnerAndGetMerkleRootAndProof({ + owner: takerUser, + numberOfItemsInMerkleTree: 5, + // Doesn't matter what itemIdInMerkleTree is as we are are going to tamper with the proof + itemIdInMerkleTree: 4 + }); + makerBid.additionalParameters = abi.encode(merkleRoot); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Prepare the taker ask + proof[0] = bytes32(0); // Tamper with the proof + OrderStructs.Taker memory takerAsk = OrderStructs.Taker(takerUser, abi.encode(itemIdSold, proof)); + + // Verify validity of maker bid order + _assertOrderIsValid(makerBid, true); + _assertValidMakerOrder(makerBid, signature); + + vm.prank(takerUser); + vm.expectRevert(MerkleProofInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testInvalidAmounts() public { + _setUpUsers(); + + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: 0 + }); + + // Prepare the taker ask + OrderStructs.Taker memory takerAsk = OrderStructs.Taker(takerUser, abi.encode(5)); + + // 1. Amount is 0 (without merkle proof) + makerBid.amounts[0] = 0; + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + _assertOrderIsInvalid(makerBid, false); + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.prank(takerUser); + vm.expectRevert(AmountInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // 2. Amount is too high for ERC721 (without merkle proof) + makerBid.amounts[0] = 2; + signature = _signMakerOrder(makerBid, makerUserPK); + _assertOrderIsInvalid(makerBid, false); + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.prank(takerUser); + vm.expectRevert(AmountInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // 3. Amount is 0 (with merkle proof) + makerBid.strategyId = 2; + uint256 itemIdInMerkleTree = 5; + (bytes32 merkleRoot, bytes32[] memory proof) = _mintNFTsToOwnerAndGetMerkleRootAndProof({ + owner: takerUser, + numberOfItemsInMerkleTree: 6, + itemIdInMerkleTree: itemIdInMerkleTree + }); + + makerBid.additionalParameters = abi.encode(merkleRoot); + makerBid.amounts[0] = 0; + signature = _signMakerOrder(makerBid, makerUserPK); + + takerAsk.additionalParameters = abi.encode(itemIdInMerkleTree, proof); + + _assertOrderIsInvalid(makerBid, true); + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.prank(takerUser); + vm.expectRevert(AmountInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // 4. Amount is too high for ERC721 (with merkle proof) + makerBid.amounts[0] = 2; + signature = _signMakerOrder(makerBid, makerUserPK); + _assertOrderIsInvalid(makerBid, true); + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.prank(takerUser); + vm.expectRevert(AmountInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testMerkleRootLengthIsNot32() public { + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 2, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: 0 + }); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertOrderIsInvalid(makerBid, true); + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.prank(takerUser); + vm.expectRevert(); // It should revert without data (since the root cannot be extracted since the additionalParameters length is 0) + looksRareProtocol.executeTakerAsk( + _genericTakerOrder(), + makerBid, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + + function testInvalidSelector() public { + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 3, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: 0 + }); + + (bool orderIsValid, bytes4 errorSelector) = strategyCollectionOffer.isMakerOrderValid(makerBid, bytes4(0)); + assertFalse(orderIsValid); + assertEq(errorSelector, FunctionSelectorInvalid.selector); + } + + function testWrongQuoteType() public { + OrderStructs.Maker memory makerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: 2, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemId: 0 + }); + + (bool orderIsValid, bytes4 errorSelector) = strategyCollectionOffer.isMakerOrderValid( + makerAsk, + selectorNoProof + ); + + assertFalse(orderIsValid); + assertEq(errorSelector, QuoteTypeInvalid.selector); + } + + function _assertOrderIsValid(OrderStructs.Maker memory makerBid, bool withProof) private { + (bool orderIsValid, bytes4 errorSelector) = strategyCollectionOffer.isMakerOrderValid( + makerBid, + withProof ? selectorWithProof : selectorNoProof + ); + assertTrue(orderIsValid); + assertEq(errorSelector, _EMPTY_BYTES4); + } + + function _assertOrderIsInvalid(OrderStructs.Maker memory makerBid, bool withProof) private { + (bool orderIsValid, bytes4 errorSelector) = strategyCollectionOffer.isMakerOrderValid( + makerBid, + withProof ? selectorWithProof : selectorNoProof + ); + + assertFalse(orderIsValid); + assertEq(errorSelector, OrderInvalid.selector); + } + + function _mintNFTsToOwnerAndGetMerkleRootAndProof( + address owner, + uint256 numberOfItemsInMerkleTree, + uint256 itemIdInMerkleTree + ) private returns (bytes32 merkleRoot, bytes32[] memory proof) { + require(itemIdInMerkleTree < numberOfItemsInMerkleTree, "Invalid itemIdInMerkleTree"); + + // Initialize Merkle Tree + Merkle m = new Merkle(); + + bytes32[] memory merkleTreeIds = new bytes32[](numberOfItemsInMerkleTree); + for (uint256 i; i < numberOfItemsInMerkleTree; i++) { + mockERC721.mint(owner, i); + merkleTreeIds[i] = keccak256(abi.encodePacked(i)); + } + + // Compute merkle root + merkleRoot = m.getRoot(merkleTreeIds); + proof = m.getProof(merkleTreeIds, itemIdInMerkleTree); + + assertTrue(m.verifyProof(merkleRoot, proof, merkleTreeIds[itemIdInMerkleTree])); + } + + function _assertSuccessfulTakerAsk(OrderStructs.Maker memory makerBid, uint256 tokenId) private { + // Taker user has received the asset + assertEq(mockERC721.ownerOf(tokenId), makerUser); + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - price); + // Taker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq( + weth.balanceOf(takerUser), + _initialWETHBalanceUser + (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP + ); + // Verify the nonce is marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } +} diff --git a/contracts/test/foundry/marketplace/executionStrategies/DutchAuctionOrders.t.sol b/contracts/test/foundry/marketplace/executionStrategies/DutchAuctionOrders.t.sol new file mode 100644 index 00000000..dd8b05c6 --- /dev/null +++ b/contracts/test/foundry/marketplace/executionStrategies/DutchAuctionOrders.t.sol @@ -0,0 +1,436 @@ +/// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries and interfaces +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; + +// Shared errors +import { AmountInvalid, BidTooLow, OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { STRATEGY_NOT_ACTIVE, MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Strategies +import { StrategyDutchAuction } from "@hypercerts/marketplace/executionStrategies/StrategyDutchAuction.sol"; + +// Other tests +import { ProtocolBase } from "../ProtocolBase.t.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { + StrategyDutchAuction public strategyDutchAuction; + bytes4 public selector = StrategyDutchAuction.executeStrategyWithTakerBid.selector; + + function setUp() public { + _setUp(); + } + + function _setUpNewStrategy() private asPrankedUser(_owner) { + strategyDutchAuction = new StrategyDutchAuction(); + _addStrategy(address(strategyDutchAuction), selector, false); + } + + function _createMakerAskAndTakerBid( + uint256 numberOfItems, + uint256 numberOfAmounts, + uint256 startPrice, + uint256 endPrice, + uint256 endTime + ) private returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) { + uint256[] memory itemIds = new uint256[](numberOfItems); + for (uint256 i; i < numberOfItems; ) { + mockERC721.mint(makerUser, i + 1); + itemIds[i] = i + 1; + unchecked { + ++i; + } + } + + uint256[] memory amounts = new uint256[](numberOfAmounts); + for (uint256 i; i < numberOfAmounts; ) { + amounts[i] = 1; + unchecked { + ++i; + } + } + + newMakerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: endPrice, + itemId: 1 + }); + + newMakerAsk.itemIds = itemIds; + newMakerAsk.amounts = amounts; + + newMakerAsk.endTime = endTime; + newMakerAsk.additionalParameters = abi.encode(startPrice); + + // Using startPrice as the maxPrice + newTakerBid = OrderStructs.Taker(takerUser, abi.encode(startPrice)); + } + + function testNewStrategy() public { + _setUpNewStrategy(); + _assertStrategyAttributes(address(strategyDutchAuction), selector, false); + } + + function _fuzzAssumptions( + uint256 _startPrice, + uint256 _duration, + uint256 _decayPerSecond, + uint256 _elapsedTime + ) private returns (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) { + // Bound instead of assume to handle too many rejections + // These limits should be realistically way more than enough + // vm.assume(duration > 0 && duration <= 31_536_000); + // Assume the NFT is worth at least 0.01 USD at today's ETH price (2023-01-13 18:00:00 UTC) + // vm.assume(startPrice > 1e12 && startPrice <= 100_000 ether); + // vm.assume(decayPerSecond > 0 && decayPerSecond < startPrice); + // vm.assume(elapsedTime <= duration && startPrice > decayPerSecond * duration); + + duration = bound(_duration, 1, 31_536_600); + startPrice = bound(_startPrice, 1e12, 100_000 ether); + decayPerSecond = bound(_decayPerSecond, 1, startPrice); + + vm.assume(_elapsedTime <= duration && startPrice > decayPerSecond * duration); + elapsedTime = _elapsedTime; + } + + function _calculatePrices( + uint256 startPrice, + uint256 duration, + uint256 decayPerSecond, + uint256 elapsedTime + ) private pure returns (uint256 endPrice, uint256 executionPrice) { + endPrice = startPrice - decayPerSecond * duration; + uint256 discount = decayPerSecond * elapsedTime; + executionPrice = startPrice - discount; + } + + function testDutchAuction( + uint256 _startPrice, + uint256 _duration, + uint256 _decayPerSecond, + uint256 _elapsedTime + ) public { + (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) = _fuzzAssumptions( + _startPrice, + _duration, + _decayPerSecond, + _elapsedTime + ); + _setUpUsers(); + _setUpNewStrategy(); + + (uint256 endPrice, uint256 executionPrice) = _calculatePrices( + startPrice, + duration, + decayPerSecond, + elapsedTime + ); + + deal(address(weth), takerUser, executionPrice); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + startPrice: startPrice, + endPrice: endPrice, + endTime: block.timestamp + duration + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + _assertOrderIsValid(makerAsk); + _assertValidMakerOrder(makerAsk, signature); + + vm.warp(block.timestamp + elapsedTime); + + // Execute taker bid transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Taker user has received the asset + assertEq(mockERC721.ownerOf(1), takerUser); + + // Taker bid user pays the whole price + assertEq(weth.balanceOf(takerUser), 0, "taker balance incorrect"); + // Maker ask user receives 99.5% of the whole price (0.5% protocol) + uint256 protocolFee = (executionPrice * _standardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; + assertEq( + weth.balanceOf(makerUser), + _initialWETHBalanceUser + (executionPrice - protocolFee), + "maker balance incorrect" + ); + } + + function testStartPriceTooLow( + uint256 _startPrice, + uint256 _duration, + uint256 _decayPerSecond, + uint256 _elapsedTime + ) public { + (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) = _fuzzAssumptions( + _startPrice, + _duration, + _decayPerSecond, + _elapsedTime + ); + _setUpUsers(); + _setUpNewStrategy(); + + (uint256 endPrice, uint256 executionPrice) = _calculatePrices( + startPrice, + duration, + decayPerSecond, + elapsedTime + ); + deal(address(weth), takerUser, executionPrice); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + startPrice: startPrice, + endPrice: endPrice, + endTime: block.timestamp + duration + }); + + makerAsk.price = startPrice + 1 wei; + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + bytes4 errorSelector = _assertOrderIsInvalid(makerAsk); + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testTakerBidTooLow( + uint256 _startPrice, + uint256 _duration, + uint256 _decayPerSecond, + uint256 _elapsedTime + ) public { + (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) = _fuzzAssumptions( + _startPrice, + _duration, + _decayPerSecond, + _elapsedTime + ); + _setUpUsers(); + _setUpNewStrategy(); + + (uint256 endPrice, uint256 executionPrice) = _calculatePrices( + startPrice, + duration, + decayPerSecond, + elapsedTime + ); + deal(address(weth), takerUser, executionPrice); + + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + startPrice: startPrice, + endPrice: endPrice, + endTime: block.timestamp + duration + }); + + takerBid.additionalParameters = abi.encode(executionPrice - 1 wei); + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + // Valid, taker struct validation only happens during execution + _assertOrderIsValid(makerAsk); + _assertValidMakerOrder(makerAsk, signature); + + vm.expectRevert(BidTooLow.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testInactiveStrategy() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + startPrice: 10 ether, + endPrice: 1 ether, + endTime: block.timestamp + 1 hours + }); + + vm.prank(_owner); + looksRareProtocol.updateStrategy(1, false, _standardProtocolFeeBp, _minTotalFeeBp); + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + _assertOrderIsValid(makerAsk); + _assertMakerOrderReturnValidationCode(makerAsk, signature, STRATEGY_NOT_ACTIVE); + + vm.prank(takerUser); + vm.expectRevert(abi.encodeWithSelector(IExecutionManager.StrategyNotAvailable.selector, 1)); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testZeroItemIdsLength() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 0, + numberOfAmounts: 0, + startPrice: 10 ether, + endPrice: 1 ether, + endTime: block.timestamp + 1 hours + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + bytes4 errorSelector = _assertOrderIsInvalid(makerAsk); + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testItemIdsAndAmountsLengthMismatch() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 2, + startPrice: 10 ether, + endPrice: 1 ether, + endTime: block.timestamp + 1 hours + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + bytes4 errorSelector = _assertOrderIsInvalid(makerAsk); + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testInvalidAmounts() public { + _setUpUsers(); + _setUpNewStrategy(); + + // 1. Amount = 0 + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ + numberOfItems: 1, + numberOfAmounts: 1, + startPrice: 10 ether, + endPrice: 1 ether, + endTime: block.timestamp + 1 hours + }); + + makerAsk.amounts[0] = 0; + + // Sign order + bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); + + bytes4 errorSelector = _assertOrderIsInvalid(makerAsk); + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.expectRevert(AmountInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // 2. ERC721 amount > 1 + makerAsk.amounts[0] = 2; + signature = _signMakerOrder(makerAsk, makerUserPK); + + errorSelector = _assertOrderIsInvalid(makerAsk); + _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.prank(takerUser); + vm.expectRevert(AmountInvalid.selector); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testWrongQuoteType() public { + _setUpNewStrategy(); + + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: 1 ether, + itemId: 420 + }); + + (bool orderIsValid, bytes4 errorSelector) = strategyDutchAuction.isMakerOrderValid(makerBid, selector); + + assertFalse(orderIsValid); + assertEq(errorSelector, QuoteTypeInvalid.selector); + } + + function testInvalidSelector() public { + _setUpNewStrategy(); + + OrderStructs.Maker memory makerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: 2, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: 1 ether, + itemId: 420 + }); + + (bool orderIsValid, bytes4 errorSelector) = strategyDutchAuction.isMakerOrderValid(makerAsk, bytes4(0)); + assertFalse(orderIsValid); + assertEq(errorSelector, FunctionSelectorInvalid.selector); + } + + function _assertOrderIsValid(OrderStructs.Maker memory makerAsk) private { + (bool isValid, bytes4 errorSelector) = strategyDutchAuction.isMakerOrderValid(makerAsk, selector); + assertTrue(isValid); + assertEq(errorSelector, _EMPTY_BYTES4); + } + + function _assertOrderIsInvalid(OrderStructs.Maker memory makerAsk) private returns (bytes4) { + (bool isValid, bytes4 errorSelector) = strategyDutchAuction.isMakerOrderValid(makerAsk, selector); + assertFalse(isValid); + assertEq(errorSelector, OrderInvalid.selector); + + return errorSelector; + } +} diff --git a/contracts/test/foundry/marketplace/executionStrategies/ItemIdsRangeOrders.t.sol b/contracts/test/foundry/marketplace/executionStrategies/ItemIdsRangeOrders.t.sol new file mode 100644 index 00000000..714595d8 --- /dev/null +++ b/contracts/test/foundry/marketplace/executionStrategies/ItemIdsRangeOrders.t.sol @@ -0,0 +1,482 @@ +/// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries and interfaces +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; + +// Shared errors +import { OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { STRATEGY_NOT_ACTIVE, MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; + +// Strategies +import { StrategyItemIdsRange } from "@hypercerts/marketplace/executionStrategies/StrategyItemIdsRange.sol"; + +// Base test +import { ProtocolBase } from "../ProtocolBase.t.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { + StrategyItemIdsRange public strategyItemIdsRange; + bytes4 public selector = StrategyItemIdsRange.executeStrategyWithTakerAsk.selector; + + function setUp() public { + _setUp(); + } + + function _setUpNewStrategy() private asPrankedUser(_owner) { + strategyItemIdsRange = new StrategyItemIdsRange(); + _addStrategy(address(strategyItemIdsRange), selector, true); + } + + function _offeredAmounts(uint256 length, uint256 amount) private pure returns (uint256[] memory offeredAmounts) { + offeredAmounts = new uint256[](length); + for (uint256 i; i < length; i++) { + offeredAmounts[i] = amount; + } + } + + function _createMakerBidAndTakerAsk( + uint256 lowerBound, + uint256 upperBound + ) private returns (OrderStructs.Maker memory newMakerBid, OrderStructs.Taker memory newTakerAsk) { + uint256 mid = (lowerBound + upperBound) / 2; + + newMakerBid = _createMultiItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: 1 ether, + itemIds: new uint256[](0), + amounts: new uint256[](0) + }); + + newMakerBid.additionalParameters = abi.encode(lowerBound, upperBound, 3); + + // This way, we can test + // 1. lower bound is 0 + // 2. lower bound is > 0, and 0 is excluded + if (lowerBound > 0) { + mockERC721.mint(takerUser, lowerBound - 1); + } + + mockERC721.mint(takerUser, lowerBound); + mockERC721.mint(takerUser, mid); + mockERC721.mint(takerUser, upperBound); + mockERC721.mint(takerUser, upperBound + 1); + + uint256[] memory takerAskItemIds = new uint256[](3); + takerAskItemIds[0] = lowerBound; + takerAskItemIds[1] = mid; + takerAskItemIds[2] = upperBound; + + newTakerAsk = OrderStructs.Taker({ + recipient: takerUser, + additionalParameters: abi.encode(takerAskItemIds, _offeredAmounts({ length: 3, amount: 1 })) + }); + } + + function testNewStrategy() public { + _setUpNewStrategy(); + _assertStrategyAttributes(address(strategyItemIdsRange), selector, true); + } + + function testTokenIdsRangeERC721(uint256 lowerBound, uint256 upperBound) public { + vm.assume(lowerBound < type(uint128).max && upperBound < type(uint128).max && lowerBound + 1 < upperBound); + + uint256 mid = (lowerBound + upperBound) / 2; + + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk( + lowerBound, + upperBound + ); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertOrderIsValid(makerBid); + _assertValidMakerOrder(makerBid, signature); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Maker user has received the asset + assertEq(mockERC721.ownerOf(lowerBound), makerUser); + assertEq(mockERC721.ownerOf(mid), makerUser); + assertEq(mockERC721.ownerOf(upperBound), makerUser); + + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - 1 ether); + // Taker ask user receives 99.5% of the whole price (0.5% protocol fee) + assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser + 0.995 ether); + } + + function testTokenIdsRangeERC1155(uint256 lowerBound, uint256 upperBound) public { + vm.assume(lowerBound < type(uint128).max && upperBound < type(uint128).max && lowerBound + 1 < upperBound); + + uint256 mid = (lowerBound + upperBound) / 2; + + _setUpUsers(); + _setUpNewStrategy(); + + OrderStructs.Maker memory makerBid = _createMultiItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, + collectionType: CollectionType.ERC1155, + orderNonce: 0, + collection: address(mockERC1155), + currency: address(weth), + signer: makerUser, + price: 1 ether, + itemIds: new uint256[](0), + amounts: new uint256[](0) + }); + + makerBid.additionalParameters = abi.encode(lowerBound, upperBound, 6); + + mockERC1155.mint(takerUser, lowerBound, 2); + mockERC1155.mint(takerUser, mid, 2); + mockERC1155.mint(takerUser, upperBound, 2); + + uint256[] memory takerAskItemIds = new uint256[](3); + takerAskItemIds[0] = lowerBound; + takerAskItemIds[1] = mid; + takerAskItemIds[2] = upperBound; + + OrderStructs.Taker memory takerAsk = OrderStructs.Taker({ + recipient: takerUser, + additionalParameters: abi.encode(takerAskItemIds, _offeredAmounts({ length: 3, amount: 2 })) + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertOrderIsValid(makerBid); + _assertValidMakerOrder(makerBid, signature); + + // Execute taker ask transaction + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Maker user has received the asset + assertEq(mockERC1155.balanceOf(makerUser, lowerBound), 2); + assertEq(mockERC1155.balanceOf(makerUser, mid), 2); + assertEq(mockERC1155.balanceOf(makerUser, upperBound), 2); + + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - 1 ether); + // Taker ask user receives 99.5% of the whole price (0.5% protocol fee) + assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser + 0.995 ether); + } + + function testInvalidMakerBidAdditionalParameters() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk(5, 10); + + makerBid.additionalParameters = abi.encode(6, 9); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + vm.expectRevert(); // EVM revert + strategyItemIdsRange.isMakerOrderValid(makerBid, selector); + + vm.expectRevert(); // EVM revert + orderValidator.checkMakerOrderValidity(makerBid, signature, _EMPTY_MERKLE_TREE); + + vm.expectRevert(); // EVM revert + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testZeroDesiredAmount() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk(5, 10); + + makerBid.additionalParameters = abi.encode(5, 10, 0); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + bytes4 errorSelector = _assertOrderIsInvalid(makerBid); + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testWrongQuoteType() public { + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, ) = _createMakerBidAndTakerAsk(5, 10); + makerBid.quoteType = QuoteType.Ask; + + (bool isValid, bytes4 errorSelector) = strategyItemIdsRange.isMakerOrderValid(makerBid, selector); + + assertFalse(isValid); + assertEq(errorSelector, QuoteTypeInvalid.selector); + } + + function testTakerAskItemIdsAmountsLengthMismatch() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk(5, 10); + + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertOrderIsValid(makerBid); + _assertValidMakerOrder(makerBid, signature); + + uint256[] memory takerAskItemIds = new uint256[](3); + takerAskItemIds[0] = 5; + takerAskItemIds[1] = 7; + takerAskItemIds[2] = 10; + takerAsk.additionalParameters = abi.encode(takerAskItemIds, _offeredAmounts({ length: 4, amount: 1 })); + + vm.prank(takerUser); + vm.expectRevert(OrderInvalid.selector); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testTakerAskRevertIfAmountIsZeroOrGreaterThanOneERC721() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk(5, 10); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + uint256[] memory takerAskItemIds = new uint256[](3); + takerAskItemIds[0] = 5; + takerAskItemIds[1] = 7; + takerAskItemIds[2] = 10; + + uint256[] memory invalidAmounts = new uint256[](3); + invalidAmounts[0] = 1; + invalidAmounts[1] = 2; + invalidAmounts[2] = 2; + + takerAsk.additionalParameters = abi.encode(takerAskItemIds, invalidAmounts); + + // The maker bid order is still valid since the error comes from the taker ask amounts + _assertOrderIsValid(makerBid); + _assertValidMakerOrder(makerBid, signature); + + // It fails at 2nd item in the array (greater than 1) + vm.expectRevert(OrderInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Re-adjust the amounts + invalidAmounts[0] = 0; + invalidAmounts[1] = 1; + invalidAmounts[2] = 1; + + takerAsk.additionalParameters = abi.encode(takerAskItemIds, invalidAmounts); + + // It now fails at 1st item in the array (equal to 0) + vm.expectRevert(OrderInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testMakerBidItemIdsLowerBandHigherThanOrEqualToUpperBand() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk(5, 10); + + // lower band > upper band + makerBid.additionalParameters = abi.encode(5, 4, 1); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + bytes4 errorSelector = _assertOrderIsInvalid(makerBid); + _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); + + vm.expectRevert(errorSelector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // lower band == upper band + makerBid.additionalParameters = abi.encode(5, 5, 1); + + // Sign order + signature = _signMakerOrder(makerBid, makerUserPK); + + vm.expectRevert(OrderInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testTakerAskDuplicatedItemIds() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk(5, 10); + + uint256[] memory invalidItemIds = new uint256[](3); + invalidItemIds[0] = 5; + invalidItemIds[1] = 7; + invalidItemIds[2] = 7; + + takerAsk.additionalParameters = abi.encode(invalidItemIds, _offeredAmounts({ length: 3, amount: 1 })); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Valid, taker struct validation only happens during execution + _assertOrderIsValid(makerBid); + _assertValidMakerOrder(makerBid, signature); + + vm.expectRevert(OrderInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testTakerAskUnsortedItemIds() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk(5, 10); + + uint256[] memory invalidItemIds = new uint256[](3); + invalidItemIds[0] = 5; + invalidItemIds[1] = 10; + invalidItemIds[2] = 7; + + takerAsk.additionalParameters = abi.encode(invalidItemIds, _offeredAmounts({ length: 3, amount: 1 })); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Valid, taker struct validation only happens during execution + _assertOrderIsValid(makerBid); + _assertValidMakerOrder(makerBid, signature); + + vm.expectRevert(OrderInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testTakerAskOfferedAmountNotEqualToDesiredAmount() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk(5, 10); + + uint256[] memory itemIds = new uint256[](2); + itemIds[0] = 5; + itemIds[1] = 10; + + takerAsk.additionalParameters = abi.encode(itemIds, _offeredAmounts({ length: 2, amount: 1 })); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + // Valid, taker struct validation only happens during execution + _assertOrderIsValid(makerBid); + _assertValidMakerOrder(makerBid, signature); + + vm.expectRevert(OrderInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testTakerAskOfferedItemIdTooLow() public { + _testTakerAskOfferedItemIdOutOfRange(3, 4); + } + + function testTakerAskOfferedItemIdTooHigh() public { + _testTakerAskOfferedItemIdOutOfRange(11, 12); + } + + function _testTakerAskOfferedItemIdOutOfRange(uint256 itemIdOne, uint256 itemIdTwo) private { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk(5, 10); + uint256[] memory itemIds = new uint256[](2); + itemIds[0] = itemIdOne; + itemIds[1] = itemIdTwo; + + takerAsk.additionalParameters = abi.encode(itemIds, _offeredAmounts({ length: 2, amount: 1 })); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + _assertOrderIsValid(makerBid); + _assertValidMakerOrder(makerBid, signature); + + vm.expectRevert(OrderInvalid.selector); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testInactiveStrategy() public { + _setUpUsers(); + _setUpNewStrategy(); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk(5, 10); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + vm.prank(_owner); + looksRareProtocol.updateStrategy(1, false, _standardProtocolFeeBp, _minTotalFeeBp); + + // Valid, taker struct validation only happens during execution + _assertOrderIsValid(makerBid); + // but... the OrderValidator catches this + _assertMakerOrderReturnValidationCode(makerBid, signature, STRATEGY_NOT_ACTIVE); + + vm.expectRevert(abi.encodeWithSelector(IExecutionManager.StrategyNotAvailable.selector, 1)); + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + } + + function testInvalidSelector() public { + _setUpNewStrategy(); + + OrderStructs.Maker memory makerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 2, + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: 1 ether, + itemId: 0 + }); + + (bool orderIsValid, bytes4 errorSelector) = strategyItemIdsRange.isMakerOrderValid(makerBid, bytes4(0)); + assertFalse(orderIsValid); + assertEq(errorSelector, FunctionSelectorInvalid.selector); + } + + function _assertOrderIsValid(OrderStructs.Maker memory makerBid) private { + (bool isValid, bytes4 errorSelector) = strategyItemIdsRange.isMakerOrderValid(makerBid, selector); + assertTrue(isValid); + assertEq(errorSelector, _EMPTY_BYTES4); + } + + function _assertOrderIsInvalid(OrderStructs.Maker memory makerBid) private returns (bytes4) { + (bool isValid, bytes4 errorSelector) = strategyItemIdsRange.isMakerOrderValid(makerBid, selector); + assertFalse(isValid); + assertEq(errorSelector, OrderInvalid.selector); + return errorSelector; + } +} diff --git a/contracts/test/foundry/marketplace/executionStrategies/MultiFillCollectionOrders.t.sol b/contracts/test/foundry/marketplace/executionStrategies/MultiFillCollectionOrders.t.sol new file mode 100644 index 00000000..4e8f9f37 --- /dev/null +++ b/contracts/test/foundry/marketplace/executionStrategies/MultiFillCollectionOrders.t.sol @@ -0,0 +1,194 @@ +/// SPDX-License-Identifier: MIT +pragma solidity >=0.8.7; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Interfaces +import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; + +// Mock files and other tests +import { StrategyTestMultiFillCollectionOrder } from "../utils/StrategyTestMultiFillCollectionOrder.sol"; +import { ProtocolBase } from "../ProtocolBase.t.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract MultiFillCollectionOrdersTest is ProtocolBase, IStrategyManager { + uint256 private constant price = 1 ether; // Fixed price of sale + + bytes4 public selector = StrategyTestMultiFillCollectionOrder.executeStrategyWithTakerAsk.selector; + + StrategyTestMultiFillCollectionOrder public strategyMultiFillCollectionOrder; + + function setUp() public { + _setUp(); + } + + function _setUpNewStrategy() private asPrankedUser(_owner) { + strategyMultiFillCollectionOrder = new StrategyTestMultiFillCollectionOrder(address(looksRareProtocol)); + _addStrategy(address(strategyMultiFillCollectionOrder), selector, true); + } + + function testNewStrategy() public { + _setUpNewStrategy(); + _assertStrategyAttributes(address(strategyMultiFillCollectionOrder), selector, true); + } + + /** + * Maker bid user wants to buy 4 ERC721 items in a collection. The order can be filled in multiple parts. + * First takerUser sells 1 item. + * Second takerUser sells 3 items. + */ + function testMultiFill() public { + _setUpUsers(); + _setUpNewStrategy(); + + uint256 amountsToFill = 4; + + uint256[] memory itemIds = new uint256[](0); + uint256[] memory amounts = new uint256[](1); + amounts[0] = amountsToFill; + + OrderStructs.Maker memory makerBid = _createMultiItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, // Multi-fill bid offer + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemIds: itemIds, + amounts: amounts + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + itemIds = new uint256[](1); + amounts = new uint256[](1); + itemIds[0] = 0; + amounts[0] = 1; + + mockERC721.mint(takerUser, itemIds[0]); + + // Prepare the taker ask + OrderStructs.Taker memory takerAsk = OrderStructs.Taker(takerUser, abi.encode(itemIds, amounts)); + + // Execute the first taker ask transaction by the first taker user + vm.prank(takerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Taker user has received the asset + assertEq(mockERC721.ownerOf(0), makerUser); + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - price); + // Taker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq( + weth.balanceOf(takerUser), + _initialWETHBalanceUser + (price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP + ); + // Verify the nonce is not marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), _computeOrderHash(makerBid)); + + // Second taker user actions + address secondTakerUser = address(420); + _setUpUser(secondTakerUser); + + itemIds = new uint256[](3); + amounts = new uint256[](3); + + itemIds[0] = 1; // tokenId = 1 + itemIds[1] = 2; // tokenId = 2 + itemIds[2] = 3; // tokenId = 3 + amounts[0] = 1; + amounts[1] = 1; + amounts[2] = 1; + + mockERC721.batchMint(secondTakerUser, itemIds); + + // Prepare the taker ask + takerAsk = OrderStructs.Taker(secondTakerUser, abi.encode(itemIds, amounts)); + + // Execute a second taker ask transaction from the second taker user + vm.prank(secondTakerUser); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + + // Taker user has received the 3 assets + assertEq(mockERC721.ownerOf(1), makerUser); + assertEq(mockERC721.ownerOf(2), makerUser); + assertEq(mockERC721.ownerOf(3), makerUser); + + // Maker bid user pays the whole price + assertEq(weth.balanceOf(makerUser), _initialWETHBalanceUser - 4 * price); + // Taker ask user receives 99.5% of the whole price (0.5% protocol) + assertEq( + weth.balanceOf(secondTakerUser), + _initialWETHBalanceUser + + 3 * + ((price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP) + ); + // Verify the nonce is now marked as executed + assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); + } + + function testInactiveStrategy() public { + _setUpUsers(); + _setUpNewStrategy(); + + uint256 amountsToFill = 4; + + uint256[] memory itemIds = new uint256[](0); + uint256[] memory amounts = new uint256[](1); + amounts[0] = amountsToFill; + + OrderStructs.Maker memory makerBid = _createMultiItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: 1, // Multi-fill bid offer + collectionType: CollectionType.ERC721, + orderNonce: 0, + collection: address(mockERC721), + currency: address(weth), + signer: makerUser, + price: price, + itemIds: itemIds, + amounts: amounts + }); + + // Sign order + bytes memory signature = _signMakerOrder(makerBid, makerUserPK); + + vm.prank(_owner); + looksRareProtocol.updateStrategy(1, false, _standardProtocolFeeBp, _minTotalFeeBp); + + { + itemIds = new uint256[](1); + amounts = new uint256[](1); + itemIds[0] = 0; + amounts[0] = 1; + + mockERC721.mint(takerUser, itemIds[0]); + + // It should revert if strategy is not available + vm.prank(takerUser); + vm.expectRevert(abi.encodeWithSelector(IExecutionManager.StrategyNotAvailable.selector, 1)); + looksRareProtocol.executeTakerAsk( + _genericTakerOrder(), + makerBid, + signature, + _EMPTY_MERKLE_TREE, + _EMPTY_AFFILIATE + ); + } + } +} diff --git a/contracts/test/foundry/marketplace/utils/BytesLib.sol b/contracts/test/foundry/marketplace/utils/BytesLib.sol new file mode 100644 index 00000000..d4140def --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/BytesLib.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/* + * @title Solidity Bytes Arrays Utils + * @author Gonçalo Sá + * @notice We only copied the `slice` function from the original /~https://github.com/GNSPS/solidity-bytes-utils + * as that's the only function needed. + * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. + * The library lets you slice bytes arrays in memory. + */ +library BytesLib { + function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) { + require(_length + 31 >= _length, "slice_overflow"); + require(_bytes.length >= _start + _length, "slice_outOfBounds"); + + bytes memory tempBytes; + + assembly { + switch iszero(_length) + case 0 { + // Get a location of some free memory and store it in tempBytes as + // Solidity does for memory variables. + tempBytes := mload(0x40) + + // The first word of the slice result is potentially a partial + // word read from the original array. To read it, we calculate + // the length of that partial word and start copying that many + // bytes into the array. The first word we copy will start with + // data we don't care about, but the last `lengthmod` bytes will + // land at the beginning of the contents of the new array. When + // we're done copying, we overwrite the full first word with + // the actual length of the slice. + let lengthmod := and(_length, 31) + + // The multiplication in the next line is necessary + // because when slicing multiples of 32 bytes (lengthmod == 0) + // the following copy loop was copying the origin's length + // and then ending prematurely not copying everything it should. + let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) + let end := add(mc, _length) + + for { + // The multiplication in the next line has the same exact purpose + // as the one above. + let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) + } lt(mc, end) { + mc := add(mc, 0x20) + cc := add(cc, 0x20) + } { + mstore(mc, mload(cc)) + } + + mstore(tempBytes, _length) + + //update free-memory pointer + //allocating the array padded to 32 bytes like the compiler does now + mstore(0x40, and(add(mc, 31), not(31))) + } + //if we want a zero-length slice let's just return a zero-length array + default { + tempBytes := mload(0x40) + //zero out the 32 bytes slice we are about to return + //we need to do it because Solidity does not garbage collect + mstore(tempBytes, 0) + + mstore(0x40, add(tempBytes, 0x20)) + } + } + + return tempBytes; + } +} diff --git a/contracts/test/foundry/marketplace/utils/EIP712MerkleTree.sol b/contracts/test/foundry/marketplace/utils/EIP712MerkleTree.sol new file mode 100644 index 00000000..a17c3275 --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/EIP712MerkleTree.sol @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Forge test +import { Test } from "forge-std/Test.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Core contracts +import { LooksRareProtocol } from "@hypercerts/marketplace/LooksRareProtocol.sol"; + +// Utils +import { MerkleWithPosition } from "./MerkleWithPosition.sol"; +import { MathLib } from "./MathLib.sol"; + +// Constants +import { MAX_CALLDATA_PROOF_LENGTH } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +contract EIP712MerkleTree is Test { + using OrderStructs for OrderStructs.Maker; + + LooksRareProtocol private looksRareProtocol; + + constructor(LooksRareProtocol _looksRareProtocol) { + looksRareProtocol = _looksRareProtocol; + } + + function sign( + uint256 privateKey, + OrderStructs.Maker[] memory makerOrders, + uint256 makerOrderIndex + ) external returns (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) { + uint256 bidCount = makerOrders.length; + uint256 treeHeight = MathLib.log2(bidCount); + if (2 ** treeHeight != bidCount || treeHeight == 0) { + treeHeight += 1; + } + bytes32 batchOrderTypehash = _getBatchOrderTypehash(treeHeight); + uint256 leafCount = 2 ** treeHeight; + OrderStructs.MerkleTreeNode[] memory leaves = new OrderStructs.MerkleTreeNode[](leafCount); + + for (uint256 i; i < bidCount; i++) { + leaves[i] = OrderStructs.MerkleTreeNode({ + value: makerOrders[i].hash(), + position: i % 2 == 0 + ? OrderStructs.MerkleTreeNodePosition.Left + : OrderStructs.MerkleTreeNodePosition.Right + }); + } + + bytes32 emptyMakerOrderHash = _emptyMakerOrderHash(); + for (uint256 i = bidCount; i < leafCount; i++) { + leaves[i] = OrderStructs.MerkleTreeNode({ + value: emptyMakerOrderHash, + position: i % 2 == 0 + ? OrderStructs.MerkleTreeNodePosition.Left + : OrderStructs.MerkleTreeNodePosition.Right + }); + } + + MerkleWithPosition merkle = new MerkleWithPosition(); + OrderStructs.MerkleTreeNode[] memory proof = merkle.getProof(leaves, makerOrderIndex); + bytes32 root = merkle.getRoot(leaves); + + signature = _sign(privateKey, batchOrderTypehash, root); + merkleTree = OrderStructs.MerkleTree({ root: root, proof: proof }); + } + + function _emptyMakerOrderHash() private pure returns (bytes32 makerOrderHash) { + OrderStructs.Maker memory makerOrder; + makerOrderHash = makerOrder.hash(); + } + + function _sign( + uint256 privateKey, + bytes32 batchOrderTypehash, + bytes32 root + ) private view returns (bytes memory signature) { + bytes32 digest = keccak256(abi.encode(batchOrderTypehash, root)); + + bytes32 domainSeparator = looksRareProtocol.domainSeparator(); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign( + privateKey, + keccak256(abi.encodePacked("\x19\x01", domainSeparator, digest)) + ); + + signature = abi.encodePacked(r, s, v); + } + + function _getBatchOrderTypehash(uint256 treeHeight) private pure returns (bytes32 batchOrderTypehash) { + if (treeHeight == 1) { + batchOrderTypehash = hex"9661287f7a4aa4867db46a2453ee15bebac4e8fc25667a58718da658f15de643"; + } else if (treeHeight == 2) { + batchOrderTypehash = hex"a54ab330ea9e1dfccee2b86f3666989e7fbd479704416c757c8de8e820142a08"; + } else if (treeHeight == 3) { + batchOrderTypehash = hex"93390f5d45ede9dea305f16aec86b2472af4f823851637f1b7019ad0775cea49"; + } else if (treeHeight == 4) { + batchOrderTypehash = hex"9dda2c8358da895e43d574bb15954ce5727b22e923a2d8f28261f297bce42f0b"; + } else if (treeHeight == 5) { + batchOrderTypehash = hex"92dc717124e161262f9d10c7079e7d54dc51271893fba54aa4a0f270fecdcc98"; + } else if (treeHeight == 6) { + batchOrderTypehash = hex"ce02aee5a7a35d40d974463c4c6e5534954fb07a7e7bc966fee268a15337bfd8"; + } else if (treeHeight == 7) { + batchOrderTypehash = hex"f7a65efd167a18f7091b2bb929d687dd94503cf0a43620487055ed7d6b727559"; + } else if (treeHeight == 8) { + batchOrderTypehash = hex"def24acacad1318b664520f7c10e8bc6d1e7f6f6f7c8b031e70624ceb42266a6"; + } else if (treeHeight == 9) { + batchOrderTypehash = hex"4cb4080dc4e7bae88b4dc4307ad5117fa4f26195998a1b5f40368809d7f4c7f2"; + } else if (treeHeight == 10) { + batchOrderTypehash = hex"f8b1f864164d8d6e0b45f1399bd711223117a4ab0b057a9c2d7779e86a7c88db"; + } else if (treeHeight == 11) { + batchOrderTypehash = hex"4787f505db237e03a7193c312d5159add8a5705278e1c7dcf92ab87126cbe490"; + } else if (treeHeight == 12) { + batchOrderTypehash = hex"7a6517e5a16c56b29947b57b748aa91736987376e1a366d948e7a802a9df3431"; + } else if (treeHeight == 13) { + batchOrderTypehash = hex"35806d347e9929042ce209d143da48f100f0ff0cbdb1fde68cf13af8059d79df"; + } + } +} diff --git a/contracts/test/foundry/marketplace/utils/ERC1271Wallet.sol b/contracts/test/foundry/marketplace/utils/ERC1271Wallet.sol new file mode 100644 index 00000000..ee76287f --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/ERC1271Wallet.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { ERC1271WalletMock } from "openzeppelin-contracts/contracts/mocks/ERC1271WalletMock.sol"; + +contract ERC1271Wallet is ERC1271WalletMock { + constructor(address originalOwner) ERC1271WalletMock(originalOwner) {} + + function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) { + return this.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) external pure returns (bytes4) { + return this.onERC1155BatchReceived.selector; + } +} diff --git a/contracts/test/foundry/marketplace/utils/GasGriefer.sol b/contracts/test/foundry/marketplace/utils/GasGriefer.sol new file mode 100644 index 00000000..2589681c --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/GasGriefer.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +contract GasGriefer { + receive() external payable { + uint256 count; + while (true) { + count += 1; + } + } + + function isValidSignature(bytes32, bytes memory) external pure returns (bytes4 magicValue) { + magicValue = this.isValidSignature.selector; + } +} diff --git a/contracts/test/foundry/marketplace/utils/MaliciousERC1271Wallet.sol b/contracts/test/foundry/marketplace/utils/MaliciousERC1271Wallet.sol new file mode 100644 index 00000000..965149b3 --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/MaliciousERC1271Wallet.sol @@ -0,0 +1,68 @@ +/// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { ILooksRareProtocol } from "@hypercerts/marketplace/interfaces/ILooksRareProtocol.sol"; +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +abstract contract MaliciousERC1271Wallet { + enum FunctionToReenter { + None, + ExecuteTakerAsk, + ExecuteTakerBid, + ExecuteMultipleTakerBids + } + + ILooksRareProtocol internal immutable looksRareProtocol; + FunctionToReenter internal functionToReenter; + + constructor(address _looksRareProtocol) { + looksRareProtocol = ILooksRareProtocol(_looksRareProtocol); + } + + function setFunctionToReenter(FunctionToReenter _functionToReenter) external { + functionToReenter = _functionToReenter; + } + + function isValidSignature(bytes32, bytes calldata) external virtual returns (bytes4 magicValue) { + magicValue = this.isValidSignature.selector; + } + + function onERC1155Received(address, address, uint256, uint256, bytes calldata) external virtual returns (bytes4) { + return this.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) external virtual returns (bytes4) { + return this.onERC1155BatchReceived.selector; + } + + function _executeTakerAsk(bytes memory signature) internal { + OrderStructs.Taker memory takerAsk; + OrderStructs.Maker memory makerBid; + OrderStructs.MerkleTree memory merkleTree; + + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, merkleTree, address(this)); + } + + function _executeTakerBid(bytes memory signature) internal { + OrderStructs.Taker memory takerBid; + OrderStructs.Maker memory makerAsk; + OrderStructs.MerkleTree memory merkleTree; + + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, merkleTree, address(this)); + } + + function _executeMultipleTakerBids() internal { + OrderStructs.Taker[] memory takerBids = new OrderStructs.Taker[](2); + OrderStructs.Maker[] memory makerAsks = new OrderStructs.Maker[](2); + bytes[] memory signatures = new bytes[](2); + OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](2); + + looksRareProtocol.executeMultipleTakerBids(takerBids, makerAsks, signatures, merkleTrees, address(this), false); + } +} diff --git a/contracts/test/foundry/marketplace/utils/MaliciousIsValidSignatureERC1271Wallet.sol b/contracts/test/foundry/marketplace/utils/MaliciousIsValidSignatureERC1271Wallet.sol new file mode 100644 index 00000000..d8c557ff --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/MaliciousIsValidSignatureERC1271Wallet.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { MaliciousERC1271Wallet } from "./MaliciousERC1271Wallet.sol"; + +contract MaliciousIsValidSignatureERC1271Wallet is MaliciousERC1271Wallet { + constructor(address _looksRareProtocol) MaliciousERC1271Wallet(_looksRareProtocol) {} + + function isValidSignature(bytes32, bytes calldata signature) external override returns (bytes4 magicValue) { + if (functionToReenter == FunctionToReenter.ExecuteTakerAsk) { + _executeTakerAsk(signature); + } else if (functionToReenter == FunctionToReenter.ExecuteTakerBid) { + _executeTakerBid(signature); + } else if (functionToReenter == FunctionToReenter.ExecuteMultipleTakerBids) { + _executeMultipleTakerBids(); + } + + magicValue = this.isValidSignature.selector; + } +} diff --git a/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol b/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol new file mode 100644 index 00000000..4881535a --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { MaliciousERC1271Wallet } from "./MaliciousERC1271Wallet.sol"; + +contract MaliciousOnERC1155ReceivedERC1271Wallet is MaliciousERC1271Wallet { + constructor(address _looksRareProtocol) MaliciousERC1271Wallet(_looksRareProtocol) {} + + function onERC1155Received(address, address, uint256, uint256, bytes memory) external override returns (bytes4) { + if (functionToReenter == FunctionToReenter.ExecuteTakerAsk) { + _executeTakerAsk(new bytes(0)); + } else if (functionToReenter == FunctionToReenter.ExecuteTakerBid) { + _executeTakerBid(new bytes(0)); + } else if (functionToReenter == FunctionToReenter.ExecuteMultipleTakerBids) { + _executeMultipleTakerBids(); + } + + return this.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) external override returns (bytes4) { + if (functionToReenter == FunctionToReenter.ExecuteTakerAsk) { + _executeTakerAsk(new bytes(0)); + } else if (functionToReenter == FunctionToReenter.ExecuteTakerBid) { + _executeTakerBid(new bytes(0)); + } else if (functionToReenter == FunctionToReenter.ExecuteMultipleTakerBids) { + _executeMultipleTakerBids(); + } + + return this.onERC1155BatchReceived.selector; + } +} diff --git a/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol b/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol new file mode 100644 index 00000000..544aeb28 --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { MaliciousERC1271Wallet } from "./MaliciousERC1271Wallet.sol"; + +contract MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet is MaliciousERC1271Wallet { + uint256 private isValidSignatureEnterCount; + + constructor(address _looksRareProtocol) MaliciousERC1271Wallet(_looksRareProtocol) {} + + function onERC1155Received(address, address, uint256, uint256, bytes memory) external override returns (bytes4) { + if (++isValidSignatureEnterCount == 3) { + if (functionToReenter == FunctionToReenter.ExecuteTakerAsk) { + _executeTakerAsk(new bytes(0)); + } else if (functionToReenter == FunctionToReenter.ExecuteTakerBid) { + _executeTakerBid(new bytes(0)); + } else if (functionToReenter == FunctionToReenter.ExecuteMultipleTakerBids) { + _executeMultipleTakerBids(); + } + } + + return this.onERC1155Received.selector; + } +} diff --git a/contracts/test/foundry/marketplace/utils/MathLib.sol b/contracts/test/foundry/marketplace/utils/MathLib.sol new file mode 100644 index 00000000..f0897c30 --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/MathLib.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +/** + * @author OpenZeppelin (last updated v4.8.0) (utils/math/Math.sol) + * @dev Standard math utilities missing in the Solidity language. + */ +library MathLib { + /** + * @dev Return the log in base 2, rounded down, of a positive value. + * Returns 0 if given 0. + */ + function log2(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + unchecked { + if (value >> 128 > 0) { + value >>= 128; + result += 128; + } + if (value >> 64 > 0) { + value >>= 64; + result += 64; + } + if (value >> 32 > 0) { + value >>= 32; + result += 32; + } + if (value >> 16 > 0) { + value >>= 16; + result += 16; + } + if (value >> 8 > 0) { + value >>= 8; + result += 8; + } + if (value >> 4 > 0) { + value >>= 4; + result += 4; + } + if (value >> 2 > 0) { + value >>= 2; + result += 2; + } + if (value >> 1 > 0) { + result += 1; + } + } + return result; + } +} diff --git a/contracts/test/foundry/marketplace/utils/MerkleWithPosition.sol b/contracts/test/foundry/marketplace/utils/MerkleWithPosition.sol new file mode 100644 index 00000000..3b7cf871 --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/MerkleWithPosition.sol @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +/** + * @dev Modified from MurkyBase to add each node's position after hashing. + * hashLeafPair does not sort the nodes to match EIP-712. + */ +contract MerkleWithPosition { + /** + * + * PROOF GENERATION * + * + */ + + function getRoot(OrderStructs.MerkleTreeNode[] memory data) public pure returns (bytes32) { + require(data.length > 1, "won't generate root for single leaf"); + while (data.length > 1) { + data = hashLevel(data); + } + return data[0].value; + } + + function getProof( + OrderStructs.MerkleTreeNode[] memory data, + uint256 node + ) public pure returns (OrderStructs.MerkleTreeNode[] memory result) { + require(data.length > 1, "won't generate proof for single leaf"); + // The size of the proof is equal to the ceiling of log2(numLeaves) + result = new OrderStructs.MerkleTreeNode[](log2ceilBitMagic(data.length)); + uint256 pos = 0; + + // Two overflow risks: node, pos + // node: max array size is 2**256-1. Largest index in the array will be 1 less than that. Also, + // for dynamic arrays, size is limited to 2**64-1 + // pos: pos is bounded by log2(data.length), which should be less than type(uint256).max + while (data.length > 1) { + unchecked { + if (node & 0x1 == 1) { + result[pos] = data[node - 1]; + } else if (node + 1 == data.length) { + result[pos] = OrderStructs.MerkleTreeNode({ + value: bytes32(0), + position: OrderStructs.MerkleTreeNodePosition.Left + }); + } else { + result[pos] = data[node + 1]; + } + ++pos; + node /= 2; + } + data = hashLevel(data); + } + return result; + } + + ///@dev function is private to prevent unsafe data from being passed + function hashLevel( + OrderStructs.MerkleTreeNode[] memory data + ) private pure returns (OrderStructs.MerkleTreeNode[] memory result) { + // Function is private, and all internal callers check that data.length >=2. + // Underflow is not possible as lowest possible value for data/result index is 1 + // overflow should be safe as length is / 2 always. + unchecked { + uint256 length = data.length; + if (length & 0x1 == 1) { + result = new OrderStructs.MerkleTreeNode[](length / 2 + 1); + bytes32 hashed = hashLeafPairs(data[length - 1].value, bytes32(0)); + result[result.length - 1] = OrderStructs.MerkleTreeNode({ + value: hashed, + position: OrderStructs.MerkleTreeNodePosition.Left + }); + } else { + result = new OrderStructs.MerkleTreeNode[](length / 2); + } + // pos is upper bounded by data.length / 2, so safe even if array is at max size + uint256 pos = 0; + bool nextIsLeft = true; + for (uint256 i = 0; i < length - 1; i += 2) { + bytes32 hashed = hashLeafPairs(data[i].value, data[i + 1].value); + result[pos] = OrderStructs.MerkleTreeNode({ + value: hashed, + position: nextIsLeft + ? OrderStructs.MerkleTreeNodePosition.Left + : OrderStructs.MerkleTreeNodePosition.Right + }); + nextIsLeft = !nextIsLeft; + ++pos; + } + } + return result; + } + + /** + * + * MATH "LIBRARY" * + * + */ + + /// Original bitmagic adapted from /~https://github.com/paulrberg/prb-math/blob/main/contracts/PRBMath.sol + /// @dev Note that x assumed > 1 + function log2ceilBitMagic(uint256 x) public pure returns (uint256) { + if (x <= 1) { + return 0; + } + uint256 msb = 0; + uint256 _x = x; + if (x >= 2 ** 128) { + x >>= 128; + msb += 128; + } + if (x >= 2 ** 64) { + x >>= 64; + msb += 64; + } + if (x >= 2 ** 32) { + x >>= 32; + msb += 32; + } + if (x >= 2 ** 16) { + x >>= 16; + msb += 16; + } + if (x >= 2 ** 8) { + x >>= 8; + msb += 8; + } + if (x >= 2 ** 4) { + x >>= 4; + msb += 4; + } + if (x >= 2 ** 2) { + x >>= 2; + msb += 2; + } + if (x >= 2 ** 1) { + msb += 1; + } + + uint256 lsb = (~_x + 1) & _x; + if ((lsb == _x) && (msb > 0)) { + return msb; + } else { + return msb + 1; + } + } + + function hashLeafPairs(bytes32 left, bytes32 right) public pure returns (bytes32 _hash) { + assembly { + mstore(0x0, left) + mstore(0x20, right) + _hash := keccak256(0x0, 0x40) + } + } +} diff --git a/contracts/test/foundry/marketplace/utils/MockOrderGenerator.sol b/contracts/test/foundry/marketplace/utils/MockOrderGenerator.sol new file mode 100644 index 00000000..7f6fd135 --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/MockOrderGenerator.sol @@ -0,0 +1,147 @@ +/// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Generic interfaces +import { IERC165 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC165.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Other helpers +import { ProtocolHelpers } from "../utils/ProtocolHelpers.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract MockOrderGenerator is ProtocolHelpers { + function _createMockMakerAskAndTakerBid( + address collection + ) internal view returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) { + CollectionType collectionType = _getCollectionType(collection); + + newMakerAsk = _createSingleItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: collectionType, + orderNonce: 0, + collection: collection, + currency: ETH, + signer: makerUser, + price: 1 ether, + itemId: 420 + }); + + newTakerBid = OrderStructs.Taker(takerUser, abi.encode()); + } + + function _createMockMakerBidAndTakerAsk( + address collection, + address currency + ) internal view returns (OrderStructs.Maker memory newMakerBid, OrderStructs.Taker memory newTakerAsk) { + CollectionType collectionType = _getCollectionType(collection); + + newMakerBid = _createSingleItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: collectionType, + orderNonce: 0, + collection: collection, + currency: currency, + signer: makerUser, + price: 1 ether, + itemId: 420 + }); + + newTakerAsk = OrderStructs.Taker(takerUser, abi.encode()); + } + + function _createMockMakerAskAndTakerBidWithBundle( + address collection, + uint256 numberTokens + ) internal view returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) { + CollectionType collectionType = _getCollectionType(collection); + + (uint256[] memory itemIds, uint256[] memory amounts) = _setBundleItemIdsAndAmounts( + collectionType, + numberTokens + ); + + newMakerAsk = _createMultiItemMakerOrder({ + quoteType: QuoteType.Ask, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: collectionType, + orderNonce: 0, + collection: collection, + currency: ETH, + signer: makerUser, + price: 1 ether, + itemIds: itemIds, + amounts: amounts + }); + + newTakerBid = OrderStructs.Taker(takerUser, abi.encode()); + } + + function _createMockMakerBidAndTakerAskWithBundle( + address collection, + address currency, + uint256 numberTokens + ) internal view returns (OrderStructs.Maker memory newMakerBid, OrderStructs.Taker memory newTakerAsk) { + CollectionType collectionType = _getCollectionType(collection); + + (uint256[] memory itemIds, uint256[] memory amounts) = _setBundleItemIdsAndAmounts( + collectionType, + numberTokens + ); + + newMakerBid = _createMultiItemMakerOrder({ + quoteType: QuoteType.Bid, + globalNonce: 0, + subsetNonce: 0, + strategyId: STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY, + collectionType: collectionType, + orderNonce: 0, + collection: collection, + currency: currency, + signer: makerUser, + price: 1 ether, + itemIds: itemIds, + amounts: amounts + }); + + newTakerAsk = OrderStructs.Taker(takerUser, abi.encode()); + } + + function _getCollectionType(address collection) private view returns (CollectionType collectionType) { + collectionType = CollectionType.ERC721; + + // If ERC1155, adjust the collection type + if (IERC165(collection).supportsInterface(0xd9b67a26)) { + collectionType = CollectionType.ERC1155; + } + } + + function _setBundleItemIdsAndAmounts( + CollectionType collectionType, + uint256 numberTokens + ) private pure returns (uint256[] memory itemIds, uint256[] memory amounts) { + itemIds = new uint256[](numberTokens); + amounts = new uint256[](numberTokens); + + for (uint256 i; i < itemIds.length; i++) { + itemIds[i] = i; + if (collectionType != CollectionType.ERC1155) { + amounts[i] = 1; + } else { + amounts[i] = 1 + i; + } + } + } +} diff --git a/contracts/test/foundry/marketplace/utils/ProtocolHelpers.sol b/contracts/test/foundry/marketplace/utils/ProtocolHelpers.sol new file mode 100644 index 00000000..066bf9b3 --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/ProtocolHelpers.sol @@ -0,0 +1,109 @@ +/// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Dependencies +import { BatchOrderTypehashRegistry } from "@hypercerts/marketplace/BatchOrderTypehashRegistry.sol"; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Other tests +import { TestHelpers } from "./TestHelpers.sol"; +import { TestParameters } from "./TestParameters.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; + +contract ProtocolHelpers is TestHelpers, TestParameters { + using OrderStructs for OrderStructs.Maker; + + bytes32 internal _domainSeparator; + + receive() external payable {} + + function _createSingleItemMakerOrder( + QuoteType quoteType, + uint256 globalNonce, + uint256 subsetNonce, + uint256 strategyId, + CollectionType collectionType, + uint256 orderNonce, + address collection, + address currency, + address signer, + uint256 price, + uint256 itemId + ) internal view returns (OrderStructs.Maker memory makerOrder) { + uint256[] memory itemIds = new uint256[](1); + itemIds[0] = itemId; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1; + + makerOrder = OrderStructs.Maker({ + quoteType: quoteType, + globalNonce: globalNonce, + subsetNonce: subsetNonce, + orderNonce: orderNonce, + strategyId: strategyId, + collectionType: collectionType, + collection: collection, + currency: currency, + signer: signer, + startTime: block.timestamp, + endTime: block.timestamp + 1, + price: price, + itemIds: itemIds, + amounts: amounts, + additionalParameters: abi.encode() + }); + } + + function _createMultiItemMakerOrder( + QuoteType quoteType, + uint256 globalNonce, + uint256 subsetNonce, + uint256 strategyId, + CollectionType collectionType, + uint256 orderNonce, + address collection, + address currency, + address signer, + uint256 price, + uint256[] memory itemIds, + uint256[] memory amounts + ) internal view returns (OrderStructs.Maker memory newMakerBid) { + newMakerBid = OrderStructs.Maker({ + quoteType: quoteType, + globalNonce: globalNonce, + subsetNonce: subsetNonce, + orderNonce: orderNonce, + strategyId: strategyId, + collectionType: collectionType, + collection: collection, + currency: currency, + signer: signer, + startTime: block.timestamp, + endTime: block.timestamp + 1, + price: price, + itemIds: itemIds, + amounts: amounts, + additionalParameters: abi.encode() + }); + } + + function _signMakerOrder(OrderStructs.Maker memory maker, uint256 signerKey) internal view returns (bytes memory) { + bytes32 orderHash = _computeOrderHash(maker); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign( + signerKey, + keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash)) + ); + + return abi.encodePacked(r, s, v); + } + + function _computeOrderHash(OrderStructs.Maker memory maker) internal pure returns (bytes32) { + return maker.hash(); + } +} diff --git a/contracts/test/foundry/marketplace/utils/StrategyTestMultiFillCollectionOrder.sol b/contracts/test/foundry/marketplace/utils/StrategyTestMultiFillCollectionOrder.sol new file mode 100644 index 00000000..ea76b14c --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/StrategyTestMultiFillCollectionOrder.sol @@ -0,0 +1,77 @@ +/// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// Libraries +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +// Custom errors +import { OrderInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; + +// Base strategy contracts +import { BaseStrategy, IStrategy } from "@hypercerts/marketplace/executionStrategies/BaseStrategy.sol"; + +// Enums +import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; + +contract StrategyTestMultiFillCollectionOrder is BaseStrategy { + using OrderStructs for OrderStructs.Maker; + + // Address of the protocol + address public immutable LOOKSRARE_PROTOCOL; + + // Tracks historical fills + mapping(bytes32 => uint256) internal countItemsFilledForOrderHash; + + /** + * @notice Constructor + * @param _looksRareProtocol Address of the LooksRare protocol + */ + constructor(address _looksRareProtocol) { + LOOKSRARE_PROTOCOL = _looksRareProtocol; + } + + /** + * @notice Execute collection strategy with taker ask order + * @param takerAsk Taker ask struct (taker ask-specific parameters for the execution) + * @param makerBid Maker bid struct (maker bid-specific parameters for the execution) + */ + function executeStrategyWithTakerAsk( + OrderStructs.Taker calldata takerAsk, + OrderStructs.Maker calldata makerBid + ) external returns (uint256 price, uint256[] memory itemIds, uint256[] memory amounts, bool isNonceInvalidated) { + if (msg.sender != LOOKSRARE_PROTOCOL) revert OrderInvalid(); + // Only available for ERC721 + if (makerBid.collectionType != CollectionType.ERC721) revert OrderInvalid(); + + bytes32 orderHash = makerBid.hash(); + uint256 countItemsFilled = countItemsFilledForOrderHash[orderHash]; + uint256 countItemsFillable = makerBid.amounts[0]; + + price = makerBid.price; + (itemIds, amounts) = abi.decode(takerAsk.additionalParameters, (uint256[], uint256[])); + uint256 countItemsToFill = amounts.length; + + if ( + countItemsToFill == 0 || + makerBid.amounts.length != 1 || + itemIds.length != countItemsToFill || + countItemsFillable < countItemsToFill + countItemsFilled + ) revert OrderInvalid(); + + price *= countItemsToFill; + + if (countItemsToFill + countItemsFilled == countItemsFillable) { + delete countItemsFilledForOrderHash[orderHash]; + isNonceInvalidated = true; + } else { + countItemsFilledForOrderHash[orderHash] += countItemsToFill; + } + } + + function isMakerOrderValid( + OrderStructs.Maker calldata, + bytes4 + ) external view override returns (bool isValid, bytes4 errorSelector) { + // + } +} diff --git a/contracts/test/foundry/marketplace/utils/TestHelpers.sol b/contracts/test/foundry/marketplace/utils/TestHelpers.sol new file mode 100644 index 00000000..32f9b9b6 --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/TestHelpers.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { Test } from "forge-std/Test.sol"; +import { BytesLib } from "./BytesLib.sol"; + +abstract contract TestHelpers is Test { + using BytesLib for bytes; + + modifier asPrankedUser(address user) { + vm.startPrank(user); + _; + vm.stopPrank(); + } + + /** + * @dev Transforms a standard signature into an EIP2098 compliant signature + * @param signature The secp256k1 65-bytes signature + * @return eip2098Signature The 64-bytes EIP2098 compliant signature + */ + function _eip2098Signature(bytes memory signature) internal pure returns (bytes memory eip2098Signature) { + eip2098Signature = signature.slice(0, 64); + uint8 parityBit = uint8(eip2098Signature[32]) | ((uint8(signature[64]) % 27) << 7); + eip2098Signature[32] = bytes1(parityBit); + } +} diff --git a/contracts/test/foundry/marketplace/utils/TestParameters.sol b/contracts/test/foundry/marketplace/utils/TestParameters.sol new file mode 100644 index 00000000..cb073095 --- /dev/null +++ b/contracts/test/foundry/marketplace/utils/TestParameters.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { Test } from "forge-std/Test.sol"; +import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; + +abstract contract TestParameters is Test { + // Empty constants + OrderStructs.MerkleTree internal _EMPTY_MERKLE_TREE; + bytes4 internal constant _EMPTY_BYTES4 = bytes4(0); + address internal constant _EMPTY_AFFILIATE = address(0); + bytes32 public constant MAGIC_VALUE_ORDER_NONCE_EXECUTED = keccak256("ORDER_NONCE_EXECUTED"); + + // Addresses + address internal constant _owner = address(42); + address internal constant _sender = address(88); + address internal constant _recipient = address(90); + address internal constant _transferrer = address(100); + address internal constant _royaltyRecipient = address(22); + address internal constant _affiliate = address(2); + + // Currencies + address internal constant ETH = address(0); + address internal constant WETH_MAINNET = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + + // Generic fee parameters + uint16 internal constant _standardProtocolFeeBp = uint16(50); + uint16 internal constant _minTotalFeeBp = uint16(50); + uint16 internal constant _maxProtocolFeeBp = uint16(200); + uint16 internal constant _standardRoyaltyFee = uint16(0); + + uint256 internal constant _sellerProceedBpWithStandardProtocolFeeBp = 9_950; + + // Public/Private keys for maker/taker user + uint256 internal constant makerUserPK = 1; + uint256 internal constant takerUserPK = 2; + // it is equal to vm.addr(makerUserPK) + address internal constant makerUser = 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf; + // it is equal to vm.addr(takerUserPK) + address internal constant takerUser = 0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF; + + // Initial balances + // @dev The balances are on purpose different across users to make sure the tests are properly checking the assertion + uint256 internal constant _initialETHBalanceUser = 100 ether; + uint256 internal constant _initialWETHBalanceUser = 10 ether; + uint256 internal constant _initialETHBalanceRoyaltyRecipient = 10 ether; + uint256 internal constant _initialWETHBalanceRoyaltyRecipient = 25 ether; + uint256 internal constant _initialETHBalanceOwner = 50 ether; + uint256 internal constant _initialWETHBalanceOwner = 15 ether; + uint256 internal constant _initialETHBalanceAffiliate = 30 ether; + uint256 internal constant _initialWETHBalanceAffiliate = 12 ether; + + // Chainlink ETH/USD price feed (Ethereum mainnet) + address internal constant CHAINLINK_ETH_USD_PRICE_FEED = 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419; + + // Strategy id + uint256 internal constant STANDARD_SALE_FOR_FIXED_PRICE_STRATEGY = 0; +} diff --git a/contracts/test/foundry/AllowlistMinter.t.sol b/contracts/test/foundry/protocol/AllowlistMinter.t.sol similarity index 97% rename from contracts/test/foundry/AllowlistMinter.t.sol rename to contracts/test/foundry/protocol/AllowlistMinter.t.sol index 7ccb3aa9..8aecd6e7 100644 --- a/contracts/test/foundry/AllowlistMinter.t.sol +++ b/contracts/test/foundry/protocol/AllowlistMinter.t.sol @@ -5,8 +5,8 @@ import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; -import { AllowlistMinter } from "../../src/AllowlistMinter.sol"; -import { Errors } from "../../src/libs/Errors.sol"; +import { AllowlistMinter } from "@hypercerts/protocol/AllowlistMinter.sol"; +import { Errors } from "@hypercerts/protocol/libs/Errors.sol"; import { Merkle } from "murky/Merkle.sol"; diff --git a/contracts/test/foundry/Bitshifting.t.sol b/contracts/test/foundry/protocol/Bitshifting.t.sol similarity index 100% rename from contracts/test/foundry/Bitshifting.t.sol rename to contracts/test/foundry/protocol/Bitshifting.t.sol diff --git a/contracts/test/foundry/HypercertMinter.batchminting.t.sol b/contracts/test/foundry/protocol/HypercertMinter.batchminting.t.sol similarity index 98% rename from contracts/test/foundry/HypercertMinter.batchminting.t.sol rename to contracts/test/foundry/protocol/HypercertMinter.batchminting.t.sol index b5349919..d58f0276 100644 --- a/contracts/test/foundry/HypercertMinter.batchminting.t.sol +++ b/contracts/test/foundry/protocol/HypercertMinter.batchminting.t.sol @@ -4,11 +4,11 @@ pragma solidity ^0.8.16; import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; //solhint-disable-next-line max-line-length import { ERC1155HolderUpgradeable } from "openzeppelin-contracts-upgradeable/contracts/token/ERC1155/utils/ERC1155HolderUpgradeable.sol"; import { Merkle } from "murky/Merkle.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; contract BatchMintingHelper is Merkle, ERC1155HolderUpgradeable { event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values); diff --git a/contracts/test/foundry/HypercertMinter.pausable.t.sol b/contracts/test/foundry/protocol/HypercertMinter.pausable.t.sol similarity index 96% rename from contracts/test/foundry/HypercertMinter.pausable.t.sol rename to contracts/test/foundry/protocol/HypercertMinter.pausable.t.sol index 716c8c5f..ae849161 100644 --- a/contracts/test/foundry/HypercertMinter.pausable.t.sol +++ b/contracts/test/foundry/protocol/HypercertMinter.pausable.t.sol @@ -4,8 +4,8 @@ pragma solidity ^0.8.16; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; contract PausableTestHelper { /** diff --git a/contracts/test/foundry/HypercertMinter.t.sol b/contracts/test/foundry/protocol/HypercertMinter.t.sol similarity index 94% rename from contracts/test/foundry/HypercertMinter.t.sol rename to contracts/test/foundry/protocol/HypercertMinter.t.sol index ad15aada..86364b56 100644 --- a/contracts/test/foundry/HypercertMinter.t.sol +++ b/contracts/test/foundry/protocol/HypercertMinter.t.sol @@ -5,8 +5,8 @@ import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; import { Merkle } from "murky/Merkle.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; contract MinterTestHelper { event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits); @@ -38,7 +38,9 @@ contract MinterTestHelper { return 0; } sum = 0; - for (uint256 i = 0; i < array.length; i++) sum += array[i]; + for (uint256 i = 0; i < array.length; i++) { + sum += array[i]; + } } function buildFractions(uint256 size) public pure returns (uint256[] memory) { diff --git a/contracts/test/foundry/HypercertMinter.transfers.t.sol b/contracts/test/foundry/protocol/HypercertMinter.transfers.t.sol similarity index 95% rename from contracts/test/foundry/HypercertMinter.transfers.t.sol rename to contracts/test/foundry/protocol/HypercertMinter.transfers.t.sol index 7c74edb1..f4b3ff9b 100644 --- a/contracts/test/foundry/HypercertMinter.transfers.t.sol +++ b/contracts/test/foundry/protocol/HypercertMinter.transfers.t.sol @@ -4,9 +4,9 @@ pragma solidity ^0.8.16; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; -import { Errors } from "../../src/libs/Errors.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { Errors } from "@hypercerts/protocol/libs/Errors.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; /// @dev Testing transfer restrictions on hypercerts contract HypercertMinterTransferTest is PRBTest, StdCheats, StdUtils { diff --git a/contracts/test/foundry/PerformanceTesting.t.sol b/contracts/test/foundry/protocol/PerformanceTesting.t.sol similarity index 97% rename from contracts/test/foundry/PerformanceTesting.t.sol rename to contracts/test/foundry/protocol/PerformanceTesting.t.sol index 7ed5b2df..7b2a71d3 100644 --- a/contracts/test/foundry/PerformanceTesting.t.sol +++ b/contracts/test/foundry/protocol/PerformanceTesting.t.sol @@ -4,9 +4,9 @@ pragma solidity ^0.8.16; import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; -import { HypercertMinter } from "../../src/HypercertMinter.sol"; +import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; import { Merkle } from "murky/Merkle.sol"; -import { IHypercertToken } from "../../src/interfaces/IHypercertToken.sol"; +import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; // forge test -vv --match-path test/foundry/PerformanceTesting.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.allowances.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.allowances.t.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.allowances.t.sol rename to contracts/test/foundry/protocol/SemiFungible1155.allowances.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.burning.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.burning.t.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.burning.t.sol rename to contracts/test/foundry/protocol/SemiFungible1155.burning.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.minting.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.minting.t.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.minting.t.sol rename to contracts/test/foundry/protocol/SemiFungible1155.minting.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.t.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.t.sol rename to contracts/test/foundry/protocol/SemiFungible1155.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.transfers.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.transfers.t.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.transfers.t.sol rename to contracts/test/foundry/protocol/SemiFungible1155.transfers.t.sol diff --git a/contracts/test/foundry/SemiFungible1155.units.sol b/contracts/test/foundry/protocol/SemiFungible1155.units.sol similarity index 100% rename from contracts/test/foundry/SemiFungible1155.units.sol rename to contracts/test/foundry/protocol/SemiFungible1155.units.sol diff --git a/contracts/test/foundry/SemiFungibleHelper.sol b/contracts/test/foundry/protocol/SemiFungibleHelper.sol similarity index 98% rename from contracts/test/foundry/SemiFungibleHelper.sol rename to contracts/test/foundry/protocol/SemiFungibleHelper.sol index 3a702e8b..7555bc9d 100644 --- a/contracts/test/foundry/SemiFungibleHelper.sol +++ b/contracts/test/foundry/protocol/SemiFungibleHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { SemiFungible1155 } from "../../src/SemiFungible1155.sol"; +import { SemiFungible1155 } from "@hypercerts/protocol/SemiFungible1155.sol"; import { PRBTest } from "prb-test/PRBTest.sol"; import { StdCheats } from "forge-std/StdCheats.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; diff --git a/contracts/test/mock/MockChainlinkAggregator.sol b/contracts/test/mock/MockChainlinkAggregator.sol new file mode 100644 index 00000000..a102b079 --- /dev/null +++ b/contracts/test/mock/MockChainlinkAggregator.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract MockChainlinkAggregator { + int256 private _answer; + uint8 private _decimals = 18; + + function setDecimals(uint8 newDecimals) external { + _decimals = newDecimals; + } + + function decimals() external view returns (uint8) { + return _decimals; + } + + function setAnswer(int256 answer) external { + _answer = answer; + } + + function latestRoundData() + external + view + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + roundId = 1; + answer = _answer; + startedAt = block.timestamp; + updatedAt = block.timestamp; + answeredInRound = 1; + } +} diff --git a/contracts/test/mock/MockERC1155.sol b/contracts/test/mock/MockERC1155.sol new file mode 100644 index 00000000..d234cf30 --- /dev/null +++ b/contracts/test/mock/MockERC1155.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.7; + +import { ERC1155 } from "solmate/src/tokens/ERC1155.sol"; + +// LooksRare unopinionated libraries +import { IERC2981 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC2981.sol"; + +contract MockERC1155 is ERC1155 { + function batchMint(address to, uint256[] memory tokenIds, uint256[] memory amounts) public { + _batchMint(to, tokenIds, amounts, ""); + } + + function mint(address to, uint256 tokenId, uint256 amount) public { + _mint(to, tokenId, amount, ""); + } + + function uri(uint256) public pure override returns (string memory) { + return "uri"; + } + + function royaltyInfo(uint256, uint256) external pure returns (address, uint256) { + return (address(0), 0); + } + + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); + } +} diff --git a/contracts/test/mock/MockERC1155SupportsNoInterface.sol b/contracts/test/mock/MockERC1155SupportsNoInterface.sol new file mode 100644 index 00000000..3a233d63 --- /dev/null +++ b/contracts/test/mock/MockERC1155SupportsNoInterface.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.7; + +import { MockERC1155 } from "./MockERC1155.sol"; + +contract MockERC1155SupportsNoInterface is MockERC1155 { + function supportsInterface(bytes4) public view virtual override returns (bool) { + return false; + } +} diff --git a/contracts/test/mock/MockERC1155WithoutAnyBalanceOf.sol b/contracts/test/mock/MockERC1155WithoutAnyBalanceOf.sol new file mode 100644 index 00000000..ed4b6286 --- /dev/null +++ b/contracts/test/mock/MockERC1155WithoutAnyBalanceOf.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.7; + +import { ERC1155 } from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; + +/** + * @dev This contract has to inherit from OZ instead of Solmate because + * Solmate's implementation defines balanceOf as a public mapping + * and it cannot be overridden. + */ +contract MockERC1155WithoutAnyBalanceOf is ERC1155 { + constructor() ERC1155("https://example.com") {} + + function balanceOf(address, uint256) public view virtual override returns (uint256) { + revert("Not implemented"); + } + + function balanceOfBatch(address[] memory, uint256[] memory) public pure override returns (uint256[] memory) { + revert("Not implemented"); + } +} diff --git a/contracts/test/mock/MockERC1155WithoutBalanceOfBatch.sol b/contracts/test/mock/MockERC1155WithoutBalanceOfBatch.sol new file mode 100644 index 00000000..c8fbccb2 --- /dev/null +++ b/contracts/test/mock/MockERC1155WithoutBalanceOfBatch.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.7; + +import { MockERC1155 } from "./MockERC1155.sol"; + +contract MockERC1155WithoutBalanceOfBatch is MockERC1155 { + function balanceOfBatch(address[] calldata, uint256[] calldata) public pure override returns (uint256[] memory) { + revert("Not implemented"); + } +} diff --git a/contracts/test/mock/MockERC1155WithoutIsApprovedForAll.sol b/contracts/test/mock/MockERC1155WithoutIsApprovedForAll.sol new file mode 100644 index 00000000..7f7630dc --- /dev/null +++ b/contracts/test/mock/MockERC1155WithoutIsApprovedForAll.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.7; + +import { ERC1155 } from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; + +/** + * @dev This contract has to inherit from OZ instead of Solmate because + * Solmate's implementation defines isApprovedForAll as a public mapping + * and it cannot be overridden. + */ +contract MockERC1155WithoutIsApprovedForAll is ERC1155 { + constructor() ERC1155("https://example.com") {} + + function mint(address to, uint256 tokenId, uint256 amount) public { + _mint(to, tokenId, amount, ""); + } + + function isApprovedForAll(address, address) public view virtual override returns (bool) { + revert("Not implemented"); + } +} diff --git a/contracts/test/mock/MockERC20.sol b/contracts/test/mock/MockERC20.sol new file mode 100644 index 00000000..8ec94827 --- /dev/null +++ b/contracts/test/mock/MockERC20.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.7; + +import { ERC20 } from "solmate/src/tokens/ERC20.sol"; + +contract MockERC20 is ERC20("MockERC20", "MockERC20", 18) { + function mint(address to, uint256 amount) public { + _mint(to, amount); + } +} diff --git a/contracts/test/mock/MockERC721.sol b/contracts/test/mock/MockERC721.sol new file mode 100644 index 00000000..24c1bdc9 --- /dev/null +++ b/contracts/test/mock/MockERC721.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.7; + +import { ERC721 } from "solmate/src/tokens/ERC721.sol"; +import { IERC165 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC165.sol"; + +contract MockERC721 is ERC721("MockERC721", "MockERC721") { + function mint(address to, uint256 tokenId) public { + _mint(to, tokenId); + } + + function batchMint(address to, uint256 amount) external { + for (uint256 i; i < amount; i++) { + _mint(to, i); + } + } + + function batchMint(address to, uint256[] memory tokenIds) public { + for (uint256 i; i < tokenIds.length; i++) { + _mint(to, tokenIds[i]); + } + } + + function tokenURI(uint256) public pure override returns (string memory) { + return "tokenURI"; + } + + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return super.supportsInterface(interfaceId); + } +} diff --git a/contracts/test/mock/MockERC721SupportsNoInterface.sol b/contracts/test/mock/MockERC721SupportsNoInterface.sol new file mode 100644 index 00000000..8cd86d36 --- /dev/null +++ b/contracts/test/mock/MockERC721SupportsNoInterface.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.7; + +import { MockERC721 } from "./MockERC721.sol"; + +contract MockERC721SupportsNoInterface is MockERC721 { + function supportsInterface(bytes4) public view virtual override returns (bool) { + return false; + } +} diff --git a/contracts/test/mock/MockERC721WithRoyalties.sol b/contracts/test/mock/MockERC721WithRoyalties.sol new file mode 100644 index 00000000..0083280b --- /dev/null +++ b/contracts/test/mock/MockERC721WithRoyalties.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import { IERC165, IERC2981 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC2981.sol"; +import { MockERC721 } from "./MockERC721.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +/** + * @dev This contract allows adding a royalty basis points higher than 10,000, which + * reverts during the royaltyInfo call. The purpose is to create a scenario where + * royaltyInfo returns the correct response for some token IDs and reverts for some + * other token IDs. This can potentially happen in a bundle transaction. + */ +contract MockERC721WithRoyalties is MockERC721, IERC2981 { + address public immutable DEFAULT_ROYALTY_RECIPIENT; + uint256 public immutable DEFAULT_ROYALTY_FEE; + + mapping(uint256 => uint256) internal _royaltyFeeForTokenId; + mapping(uint256 => address) internal _royaltyRecipientForTokenId; + + constructor(address _royaltyFeeRecipient, uint256 _royaltyFee) { + DEFAULT_ROYALTY_RECIPIENT = _royaltyFeeRecipient; + DEFAULT_ROYALTY_FEE = _royaltyFee; + } + + function addCustomRoyaltyInformationForTokenId( + uint256 tokenId, + address royaltyRecipient, + uint256 royaltyFee + ) external { + _royaltyRecipientForTokenId[tokenId] = royaltyRecipient; + _royaltyFeeForTokenId[tokenId] = royaltyFee; + } + + function royaltyInfo( + uint256 tokenId, + uint256 salePrice + ) external view override returns (address royaltyRecipient, uint256 royaltyAmount) { + royaltyRecipient = _royaltyRecipientForTokenId[tokenId] == address(0) + ? DEFAULT_ROYALTY_RECIPIENT + : _royaltyRecipientForTokenId[tokenId]; + uint256 _royaltyFee = _royaltyFeeForTokenId[tokenId]; + uint256 royaltyFee = _royaltyFee == 0 ? DEFAULT_ROYALTY_FEE : _royaltyFee; + require(royaltyFee <= ONE_HUNDRED_PERCENT_IN_BP, "Royalty too high"); + royaltyAmount = (royaltyFee * salePrice) / ONE_HUNDRED_PERCENT_IN_BP; + } + + function supportsInterface(bytes4 interfaceId) public view override(MockERC721, IERC165) returns (bool) { + return interfaceId == 0x2a55205a || super.supportsInterface(interfaceId); + } +} diff --git a/contracts/test/mock/MockRoyaltyFeeRegistry.sol b/contracts/test/mock/MockRoyaltyFeeRegistry.sol new file mode 100644 index 00000000..e4ec7a1f --- /dev/null +++ b/contracts/test/mock/MockRoyaltyFeeRegistry.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +// LooksRare unopinionated libraries +import { OwnableTwoSteps } from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol"; + +// Royalty Fee Registry interface +import { IRoyaltyFeeRegistry } from "@hypercerts/marketplace/interfaces/IRoyaltyFeeRegistry.sol"; + +// Constants +import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; + +/** + * @title MockRoyaltyFeeRegistry + * @notice It is a royalty fee registry for the LooksRare exchange. + * @dev The original one used the standard Ownable library from OpenZeppelin. + */ +contract MockRoyaltyFeeRegistry is IRoyaltyFeeRegistry, OwnableTwoSteps { + struct FeeInfo { + address setter; + address receiver; + uint256 fee; + } + + // Limit (if enforced for fee royalty in basis point (10,000 = 100%) + uint256 public royaltyFeeLimit; + + mapping(address => FeeInfo) private _royaltyFeeInfoCollection; + + event NewRoyaltyFeeLimit(uint256 royaltyFeeLimit); + event RoyaltyFeeUpdate(address indexed collection, address indexed setter, address indexed receiver, uint256 fee); + + /** + * @notice Constructor + * @param _owner Owner address + * @param _royaltyFeeLimit new royalty fee limit (500 = 5%, 1,000 = 10%) + */ + constructor(address _owner, uint256 _royaltyFeeLimit) OwnableTwoSteps(_owner) { + require(_royaltyFeeLimit <= 9_500, "Owner: Royalty fee limit too high"); + royaltyFeeLimit = _royaltyFeeLimit; + } + + /** + * @notice Update royalty info for collection + * @param _royaltyFeeLimit new royalty fee limit (500 = 5%, 1,000 = 10%) + */ + function updateRoyaltyFeeLimit(uint256 _royaltyFeeLimit) external onlyOwner { + require(_royaltyFeeLimit <= 9_500, "Owner: Royalty fee limit too high"); + royaltyFeeLimit = _royaltyFeeLimit; + + emit NewRoyaltyFeeLimit(_royaltyFeeLimit); + } + + /** + * @notice Update royalty info for collection + * @param collection address of the NFT contract + * @param setter address that sets the receiver + * @param receiver receiver for the royalty fee + * @param fee fee (500 = 5%, 1,000 = 10%) + */ + function updateRoyaltyInfoForCollection( + address collection, + address setter, + address receiver, + uint256 fee + ) external onlyOwner { + require(fee <= royaltyFeeLimit, "Registry: Royalty fee too high"); + _royaltyFeeInfoCollection[collection] = FeeInfo({ setter: setter, receiver: receiver, fee: fee }); + + emit RoyaltyFeeUpdate(collection, setter, receiver, fee); + } + + /** + * @notice Calculate royalty info for a collection address and a sale gross amount + * @param collection collection address + * @param amount amount + * @return receiver address and amount received by royalty recipient + */ + function royaltyInfo(address collection, uint256 amount) external view returns (address, uint256) { + return ( + _royaltyFeeInfoCollection[collection].receiver, + (amount * _royaltyFeeInfoCollection[collection].fee) / ONE_HUNDRED_PERCENT_IN_BP + ); + } + + /** + * @notice View royalty info for a collection address + * @param collection collection address + */ + function royaltyFeeInfoCollection(address collection) external view returns (address, address, uint256) { + return ( + _royaltyFeeInfoCollection[collection].setter, + _royaltyFeeInfoCollection[collection].receiver, + _royaltyFeeInfoCollection[collection].fee + ); + } +} diff --git a/contracts/test/mock/MockSmartWallet.sol b/contracts/test/mock/MockSmartWallet.sol new file mode 100644 index 00000000..6e30673b --- /dev/null +++ b/contracts/test/mock/MockSmartWallet.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract MockSmartWallet { + address public owner; + + bytes4 internal constant MAGICVALUE = bytes4(keccak256("isValidSignature(bytes32,bytes)")); + + modifier onlyOwner() { + if (msg.sender != owner) { + revert("Unauthorized"); + } + _; + } + + constructor() { + owner = msg.sender; + } + + receive() external payable {} + + function transferOwnership(address _newOwner) external onlyOwner { + owner = _newOwner; + } + + function executeBatch(address[] calldata dest, bytes[] calldata calldata_) external onlyOwner { + if (dest.length != calldata_.length) { + revert("Invalid array length"); + } + for (uint256 i = 0; i < dest.length; ++i) { + execute(dest[i], 0, calldata_[i]); + } + } + + function isValidSignature(bytes32 _hash, bytes memory _signature) external view returns (bytes4 magicValue) { + bytes32 r; + bytes32 s; + uint8 v; + + assembly { + r := mload(add(_signature, 0x20)) + s := mload(add(_signature, 0x40)) + v := byte(0, mload(add(_signature, 0x60))) + } + address recovered = ecrecover(_hash, v, r, s); + if (recovered == address(0)) { + revert("Invalid signature"); + } + if (owner != recovered) { + revert("Invalid signer"); + } + + return MAGICVALUE; + } + + function execute(address dest, uint256 value, bytes calldata calldata_) public onlyOwner { + (bool success, bytes memory result) = dest.call{ value: value }(calldata_); + + if (!success) { + assembly { + revert(add(result, 32), mload(result)) + } + } + } +} diff --git a/contracts/tsconfig.build.json b/contracts/tsconfig.build.json index d2a57421..baa92593 100644 --- a/contracts/tsconfig.build.json +++ b/contracts/tsconfig.build.json @@ -23,10 +23,10 @@ "include": ["./src"], "files": [ "src/abi/HypercertMinter.json", - "src/types/src/AllowlistMinter.ts", - "src/types/src/HypercertMinter.ts", - "src/types/src/interfaces/IAllowlist.ts", - "src/types/src/interfaces/IHypercertToken.ts", - "src/types/src/libs/Errors.ts" + "src/types/src/protocol/AllowlistMinter.ts", + "src/types/src/protocol/HypercertMinter.ts", + "src/types/src/protocol/interfaces/IAllowlist.ts", + "src/types/src/protocol/interfaces/IHypercertToken.ts", + "src/types/src/protocol/libs/Errors.ts" ] } diff --git a/contracts/tsconfig.json b/contracts/tsconfig.json index 8d0a6cfc..b58408fb 100644 --- a/contracts/tsconfig.json +++ b/contracts/tsconfig.json @@ -24,10 +24,10 @@ "files": [ "hardhat.config.ts", "src/abi/HypercertMinter.json", - "src/types/src/AllowlistMinter.ts", - "src/types/src/HypercertMinter.ts", - "src/types/src/interfaces/IAllowlist.ts", - "src/types/src/interfaces/IHypercertToken.ts", - "src/types/src/libs/Errors.ts" + "src/types/src/protocol/AllowlistMinter.ts", + "src/types/src/protocol/HypercertMinter.ts", + "src/types/src/protocol/interfaces/IAllowlist.ts", + "src/types/src/protocol/interfaces/IHypercertToken.ts", + "src/types/src/protocol/libs/Errors.ts" ] } diff --git a/cors-proxy/src/index.ts b/cors-proxy/src/index.ts index e88e6e3d..aaa9a400 100644 --- a/cors-proxy/src/index.ts +++ b/cors-proxy/src/index.ts @@ -69,6 +69,9 @@ export default { // Rewrite request to point to API URL. This also makes the request mutable // so you can add the correct Origin header to make the API server think // that this request is not cross-site. + // TODO: Never use ts ignore + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore request = new Request(apiUrl, request); request.headers.set("Origin", new URL(apiUrl).origin); let response = await fetch(request); diff --git a/defender/package.json b/defender/package.json index f2da4c70..2d8a57f4 100644 --- a/defender/package.json +++ b/defender/package.json @@ -14,10 +14,10 @@ }, "dependencies": { "@hypercerts-org/contracts": "0.8.11", - "@openzeppelin/defender-autotask-client": "^1.48.0", - "@openzeppelin/defender-autotask-utils": "^1.48.0", - "@openzeppelin/defender-base-client": "^1.48.0", - "@openzeppelin/defender-sentinel-client": "^1.48.0", + "@openzeppelin/defender-autotask-client": "1.50.0", + "@openzeppelin/defender-autotask-utils": "1.50.0", + "@openzeppelin/defender-base-client": "1.49.0", + "@openzeppelin/defender-sentinel-client": "1.49.0", "@openzeppelin/merkle-tree": "^1.0.2", "@supabase/supabase-js": "^2.4.1", "axios": "^1.2.6", diff --git a/docs/docs/developer/api/contracts/AllowlistMinter.md b/docs/docs/developer/api/contracts/AllowlistMinter.md index 4684053c..068d0fe7 100644 --- a/docs/docs/developer/api/contracts/AllowlistMinter.md +++ b/docs/docs/developer/api/contracts/AllowlistMinter.md @@ -1,11 +1,13 @@ # AllowlistMinter -_bitbeckers_ +*bitbeckers* > Interface for hypercert token interactions This interface declares the required functionality for a hypercert tokenThis interface does not specify the underlying token type (e.g. 721 or 1155) + + ## Methods ### hasBeenClaimed @@ -14,18 +16,22 @@ This interface declares the required functionality for a hypercert tokenThis int function hasBeenClaimed(uint256, bytes32) external view returns (bool) ``` + + + + #### Parameters -| Name | Type | Description | -| ---- | ------- | ----------- | -| \_0 | uint256 | undefined | -| \_1 | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | +| _1 | bytes32 | undefined | #### Returns | Name | Type | Description | -| ---- | ---- | ----------- | -| \_0 | bool | undefined | +|---|---|---| +| _0 | bool | undefined | ### isAllowedToClaim @@ -33,19 +39,25 @@ function hasBeenClaimed(uint256, bytes32) external view returns (bool) function isAllowedToClaim(bytes32[] proof, uint256 claimID, bytes32 leaf) external view returns (bool isAllowed) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | --------- | ----------- | -| proof | bytes32[] | undefined | -| claimID | uint256 | undefined | -| leaf | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| proof | bytes32[] | undefined | +| claimID | uint256 | undefined | +| leaf | bytes32 | undefined | #### Returns -| Name | Type | Description | -| --------- | ---- | ----------- | -| isAllowed | bool | undefined | +| Name | Type | Description | +|---|---|---| +| isAllowed | bool | undefined | + + ## Events @@ -55,12 +67,16 @@ function isAllowedToClaim(bytes32[] proof, uint256 claimID, bytes32 leaf) extern event AllowlistCreated(uint256 tokenID, bytes32 root) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | -| root | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| tokenID | uint256 | undefined | +| root | bytes32 | undefined | ### LeafClaimed @@ -68,12 +84,18 @@ event AllowlistCreated(uint256 tokenID, bytes32 root) event LeafClaimed(uint256 tokenID, bytes32 leaf) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | -| leaf | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| tokenID | uint256 | undefined | +| leaf | bytes32 | undefined | + + ## Errors @@ -82,3 +104,10 @@ event LeafClaimed(uint256 tokenID, bytes32 leaf) ```solidity error DoesNotExist() ``` + + + + + + + diff --git a/docs/docs/developer/api/contracts/HypercertMinter.md b/docs/docs/developer/api/contracts/HypercertMinter.md index 012e3d60..334fc46f 100644 --- a/docs/docs/developer/api/contracts/HypercertMinter.md +++ b/docs/docs/developer/api/contracts/HypercertMinter.md @@ -1,22 +1,25 @@ # HypercertMinter -_bitbeckers_ +*bitbeckers* > Contract for managing hypercert claims and whitelists Implementation of the HypercertTokenInterface using { SemiFungible1155 } as underlying token.This contract supports whitelisted minting via { AllowlistMinter }. -_Wrapper contract to expose and chain functions._ +*Wrapper contract to expose and chain functions.* ## Methods -### \_\_SemiFungible1155_init +### __SemiFungible1155_init ```solidity function __SemiFungible1155_init() external nonpayable ``` -_see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol }_ + + +*see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol }* + ### balanceOf @@ -24,20 +27,22 @@ _see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.so function balanceOf(address account, uint256 id) external view returns (uint256) ``` -_See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address._ + + +*See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address.* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| account | address | undefined | -| id | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| id | uint256 | undefined | #### Returns -| Name | Type | Description | -| ---- | ------- | ----------- | -| \_0 | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | ### balanceOfBatch @@ -45,20 +50,22 @@ _See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address. function balanceOfBatch(address[] accounts, uint256[] ids) external view returns (uint256[]) ``` -_See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length._ + + +*See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length.* #### Parameters -| Name | Type | Description | -| -------- | --------- | ----------- | -| accounts | address[] | undefined | -| ids | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| accounts | address[] | undefined | +| ids | uint256[] | undefined | #### Returns -| Name | Type | Description | -| ---- | --------- | ----------- | -| \_0 | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | undefined | ### batchBurnFraction @@ -68,14 +75,14 @@ function batchBurnFraction(address _account, uint256[] _tokenIDs) external nonpa Burn a claimtoken -_see {IHypercertToken}_ +*see {IHypercertToken}* #### Parameters -| Name | Type | Description | -| ---------- | --------- | ----------- | -| \_account | address | undefined | -| \_tokenIDs | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| _account | address | undefined | +| _tokenIDs | uint256[] | undefined | ### batchMintClaimsFromAllowlists @@ -85,16 +92,16 @@ function batchMintClaimsFromAllowlists(address account, bytes32[][] proofs, uint Mint semi-fungible tokens representing a fraction of the claims in `claimIDs` -_Calls AllowlistMinter to verify `proofs`.Mints the `amount` of units for the hypercert stored under `claimIDs`_ +*Calls AllowlistMinter to verify `proofs`.Mints the `amount` of units for the hypercert stored under `claimIDs`* #### Parameters -| Name | Type | Description | -| -------- | ----------- | ----------- | -| account | address | undefined | -| proofs | bytes32[][] | undefined | -| claimIDs | uint256[] | undefined | -| units | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| proofs | bytes32[][] | undefined | +| claimIDs | uint256[] | undefined | +| units | uint256[] | undefined | ### burn @@ -104,15 +111,15 @@ function burn(address account, uint256 id, uint256 value) external nonpayable Burn a claimtoken; override is needed to update units/values -_see {ERC1155Burnable}_ +*see {ERC1155Burnable}* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| account | address | undefined | -| id | uint256 | undefined | -| value | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| id | uint256 | undefined | +| value | uint256 | undefined | ### burnBatch @@ -122,15 +129,15 @@ function burnBatch(address account, uint256[] ids, uint256[] values) external no Batch burn claimtokens; override is needed to update units/values -_see {ERC1155Burnable}_ +*see {ERC1155Burnable}* #### Parameters -| Name | Type | Description | -| ------- | --------- | ----------- | -| account | address | undefined | -| ids | uint256[] | undefined | -| values | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| ids | uint256[] | undefined | +| values | uint256[] | undefined | ### burnFraction @@ -140,14 +147,14 @@ function burnFraction(address _account, uint256 _tokenID) external nonpayable Burn a claimtoken -_see {IHypercertToken}_ +*see {IHypercertToken}* #### Parameters -| Name | Type | Description | -| --------- | ------- | ----------- | -| \_account | address | undefined | -| \_tokenID | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| _account | address | undefined | +| _tokenID | uint256 | undefined | ### createAllowlist @@ -157,17 +164,17 @@ function createAllowlist(address account, uint256 units, bytes32 merkleRoot, str Register a claim and the whitelist for minting token(s) belonging to that claim -_Calls SemiFungible1155 to store the claim referenced in `uri` with amount of `units`Calls AllowlistMinter to store the `merkleRoot` as proof to authorize claims_ +*Calls SemiFungible1155 to store the claim referenced in `uri` with amount of `units`Calls AllowlistMinter to store the `merkleRoot` as proof to authorize claims* #### Parameters -| Name | Type | Description | -| ------------ | ----------------------------------------- | ----------- | -| account | address | undefined | -| units | uint256 | undefined | -| merkleRoot | bytes32 | undefined | -| \_uri | string | undefined | -| restrictions | enum IHypercertToken.TransferRestrictions | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| units | uint256 | undefined | +| merkleRoot | bytes32 | undefined | +| _uri | string | undefined | +| restrictions | enum IHypercertToken.TransferRestrictions | undefined | ### hasBeenClaimed @@ -175,18 +182,22 @@ _Calls SemiFungible1155 to store the claim referenced in `uri` with amount of `u function hasBeenClaimed(uint256, bytes32) external view returns (bool) ``` + + + + #### Parameters -| Name | Type | Description | -| ---- | ------- | ----------- | -| \_0 | uint256 | undefined | -| \_1 | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | +| _1 | bytes32 | undefined | #### Returns | Name | Type | Description | -| ---- | ---- | ----------- | -| \_0 | bool | undefined | +|---|---|---| +| _0 | bool | undefined | ### initialize @@ -194,7 +205,10 @@ function hasBeenClaimed(uint256, bytes32) external view returns (bool) function initialize() external nonpayable ``` -_see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol }_ + + +*see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol }* + ### isAllowedToClaim @@ -202,19 +216,23 @@ _see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.so function isAllowedToClaim(bytes32[] proof, uint256 claimID, bytes32 leaf) external view returns (bool isAllowed) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | --------- | ----------- | -| proof | bytes32[] | undefined | -| claimID | uint256 | undefined | -| leaf | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| proof | bytes32[] | undefined | +| claimID | uint256 | undefined | +| leaf | bytes32 | undefined | #### Returns -| Name | Type | Description | -| --------- | ---- | ----------- | -| isAllowed | bool | undefined | +| Name | Type | Description | +|---|---|---| +| isAllowed | bool | undefined | ### isApprovedForAll @@ -222,20 +240,22 @@ function isAllowedToClaim(bytes32[] proof, uint256 claimID, bytes32 leaf) extern function isApprovedForAll(address account, address operator) external view returns (bool) ``` -_See {IERC1155-isApprovedForAll}._ + + +*See {IERC1155-isApprovedForAll}.* #### Parameters -| Name | Type | Description | -| -------- | ------- | ----------- | -| account | address | undefined | -| operator | address | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| operator | address | undefined | #### Returns | Name | Type | Description | -| ---- | ---- | ----------- | -| \_0 | bool | undefined | +|---|---|---| +| _0 | bool | undefined | ### mergeFractions @@ -245,14 +265,14 @@ function mergeFractions(address _account, uint256[] _fractionIDs) external nonpa Merge the value of tokens belonging to the same claim -_see {IHypercertToken}_ +*see {IHypercertToken}* #### Parameters -| Name | Type | Description | -| ------------- | --------- | ----------- | -| \_account | address | undefined | -| \_fractionIDs | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| _account | address | undefined | +| _fractionIDs | uint256[] | undefined | ### mintClaim @@ -262,16 +282,16 @@ function mintClaim(address account, uint256 units, string _uri, enum IHypercertT Mint a semi-fungible token for the impact claim referenced via `uri` -_see {IHypercertToken}_ +*see {IHypercertToken}* #### Parameters -| Name | Type | Description | -| ------------ | ----------------------------------------- | ----------- | -| account | address | undefined | -| units | uint256 | undefined | -| \_uri | string | undefined | -| restrictions | enum IHypercertToken.TransferRestrictions | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| units | uint256 | undefined | +| _uri | string | undefined | +| restrictions | enum IHypercertToken.TransferRestrictions | undefined | ### mintClaimFromAllowlist @@ -281,16 +301,16 @@ function mintClaimFromAllowlist(address account, bytes32[] proof, uint256 claimI Mint a semi-fungible token representing a fraction of the claim -_Calls AllowlistMinter to verify `proof`.Mints the `amount` of units for the hypercert stored under `claimID`_ +*Calls AllowlistMinter to verify `proof`.Mints the `amount` of units for the hypercert stored under `claimID`* #### Parameters -| Name | Type | Description | -| ------- | --------- | ----------- | -| account | address | undefined | -| proof | bytes32[] | undefined | -| claimID | uint256 | undefined | -| units | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| proof | bytes32[] | undefined | +| claimID | uint256 | undefined | +| units | uint256 | undefined | ### mintClaimWithFractions @@ -300,17 +320,17 @@ function mintClaimWithFractions(address account, uint256 units, uint256[] fracti Mint semi-fungible tokens for the impact claim referenced via `uri` -_see {IHypercertToken}_ +*see {IHypercertToken}* #### Parameters -| Name | Type | Description | -| ------------ | ----------------------------------------- | ----------- | -| account | address | undefined | -| units | uint256 | undefined | -| fractions | uint256[] | undefined | -| \_uri | string | undefined | -| restrictions | enum IHypercertToken.TransferRestrictions | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| units | uint256 | undefined | +| fractions | uint256[] | undefined | +| _uri | string | undefined | +| restrictions | enum IHypercertToken.TransferRestrictions | undefined | ### name @@ -318,11 +338,16 @@ _see {IHypercertToken}_ function name() external view returns (string) ``` + + + + + #### Returns -| Name | Type | Description | -| ---- | ------ | ----------- | -| \_0 | string | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | ### owner @@ -330,13 +355,16 @@ function name() external view returns (string) function owner() external view returns (address) ``` -_Returns the address of the current owner._ + + +*Returns the address of the current owner.* + #### Returns -| Name | Type | Description | -| ---- | ------- | ----------- | -| \_0 | address | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | ### ownerOf @@ -344,19 +372,21 @@ _Returns the address of the current owner._ function ownerOf(uint256 tokenID) external view returns (address _owner) ``` -_Returns the owner of a given token ID._ + + +*Returns the owner of a given token ID.* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------------------------- | +| Name | Type | Description | +|---|---|---| | tokenID | uint256 | The ID of the token to query. | #### Returns -| Name | Type | Description | -| ------- | ------- | -------------------------------------- | -| \_owner | address | The address of the owner of the token. | +| Name | Type | Description | +|---|---|---| +| _owner | address | The address of the owner of the token. | ### pause @@ -366,19 +396,25 @@ function pause() external nonpayable PAUSABLE + + + ### paused ```solidity function paused() external view returns (bool) ``` -_Returns true if the contract is paused, and false otherwise._ + + +*Returns true if the contract is paused, and false otherwise.* + #### Returns | Name | Type | Description | -| ---- | ---- | ----------- | -| \_0 | bool | undefined | +|---|---|---| +| _0 | bool | undefined | ### proxiableUUID @@ -386,13 +422,16 @@ _Returns true if the contract is paused, and false otherwise._ function proxiableUUID() external view returns (bytes32) ``` -_Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier._ + + +*Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.* + #### Returns -| Name | Type | Description | -| ---- | ------- | ----------- | -| \_0 | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | ### readTransferRestriction @@ -402,17 +441,19 @@ function readTransferRestriction(uint256 tokenID) external view returns (string) TRANSFER RESTRICTIONS + + #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| tokenID | uint256 | undefined | #### Returns -| Name | Type | Description | -| ---- | ------ | ----------- | -| \_0 | string | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | string | undefined | ### renounceOwnership @@ -420,7 +461,10 @@ TRANSFER RESTRICTIONS function renounceOwnership() external nonpayable ``` -_Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner._ + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + ### safeBatchTransferFrom @@ -428,17 +472,19 @@ _Leaves the contract without owner. It will not be possible to call `onlyOwner` function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] amounts, bytes data) external nonpayable ``` -_See {IERC1155-safeBatchTransferFrom}._ + + +*See {IERC1155-safeBatchTransferFrom}.* #### Parameters -| Name | Type | Description | -| ------- | --------- | ----------- | -| from | address | undefined | -| to | address | undefined | -| ids | uint256[] | undefined | -| amounts | uint256[] | undefined | -| data | bytes | undefined | +| Name | Type | Description | +|---|---|---| +| from | address | undefined | +| to | address | undefined | +| ids | uint256[] | undefined | +| amounts | uint256[] | undefined | +| data | bytes | undefined | ### safeTransferFrom @@ -446,17 +492,19 @@ _See {IERC1155-safeBatchTransferFrom}._ function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes data) external nonpayable ``` -_See {IERC1155-safeTransferFrom}._ + + +*See {IERC1155-safeTransferFrom}.* #### Parameters -| Name | Type | Description | -| ------ | ------- | ----------- | -| from | address | undefined | -| to | address | undefined | -| id | uint256 | undefined | -| amount | uint256 | undefined | -| data | bytes | undefined | +| Name | Type | Description | +|---|---|---| +| from | address | undefined | +| to | address | undefined | +| id | uint256 | undefined | +| amount | uint256 | undefined | +| data | bytes | undefined | ### setApprovalForAll @@ -464,14 +512,16 @@ _See {IERC1155-safeTransferFrom}._ function setApprovalForAll(address operator, bool approved) external nonpayable ``` -_See {IERC1155-setApprovalForAll}._ + + +*See {IERC1155-setApprovalForAll}.* #### Parameters -| Name | Type | Description | -| -------- | ------- | ----------- | -| operator | address | undefined | -| approved | bool | undefined | +| Name | Type | Description | +|---|---|---| +| operator | address | undefined | +| approved | bool | undefined | ### splitFraction @@ -481,15 +531,15 @@ function splitFraction(address _account, uint256 _tokenID, uint256[] _newFractio Split a claimtokens value into parts with summed value equal to the original -_see {IHypercertToken}_ +*see {IHypercertToken}* #### Parameters -| Name | Type | Description | -| -------------- | --------- | ----------- | -| \_account | address | undefined | -| \_tokenID | uint256 | undefined | -| \_newFractions | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| _account | address | undefined | +| _tokenID | uint256 | undefined | +| _newFractions | uint256[] | undefined | ### supportsInterface @@ -497,19 +547,21 @@ _see {IHypercertToken}_ function supportsInterface(bytes4 interfaceId) external view returns (bool) ``` -_See {IERC165-supportsInterface}._ + + +*See {IERC165-supportsInterface}.* #### Parameters -| Name | Type | Description | -| ----------- | ------ | ----------- | -| interfaceId | bytes4 | undefined | +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | #### Returns | Name | Type | Description | -| ---- | ---- | ----------- | -| \_0 | bool | undefined | +|---|---|---| +| _0 | bool | undefined | ### transferOwnership @@ -517,13 +569,15 @@ _See {IERC165-supportsInterface}._ function transferOwnership(address newOwner) external nonpayable ``` -_Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner._ + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* #### Parameters -| Name | Type | Description | -| -------- | ------- | ----------- | -| newOwner | address | undefined | +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | ### unitsOf @@ -531,20 +585,22 @@ _Transfers ownership of the contract to a new account (`newOwner`). Can only be function unitsOf(address account, uint256 tokenID) external view returns (uint256 units) ``` -_see {IHypercertToken}_ + + +*see {IHypercertToken}* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| account | address | undefined | -| tokenID | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| tokenID | uint256 | undefined | #### Returns -| Name | Type | Description | -| ----- | ------- | ----------- | -| units | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| units | uint256 | undefined | ### unitsOf @@ -552,19 +608,21 @@ _see {IHypercertToken}_ function unitsOf(uint256 tokenID) external view returns (uint256 units) ``` -_see {IHypercertToken}_ + + +*see {IHypercertToken}* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| tokenID | uint256 | undefined | #### Returns -| Name | Type | Description | -| ----- | ------- | ----------- | -| units | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| units | uint256 | undefined | ### unpause @@ -572,19 +630,26 @@ _see {IHypercertToken}_ function unpause() external nonpayable ``` + + + + + ### upgradeTo ```solidity function upgradeTo(address newImplementation) external nonpayable ``` -_Upgrade the implementation of the proxy to `newImplementation`. Calls {\_authorizeUpgrade}. Emits an {Upgraded} event._ + + +*Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.* #### Parameters -| Name | Type | Description | -| ----------------- | ------- | ----------- | -| newImplementation | address | undefined | +| Name | Type | Description | +|---|---|---| +| newImplementation | address | undefined | ### upgradeToAndCall @@ -592,14 +657,16 @@ _Upgrade the implementation of the proxy to `newImplementation`. Calls {\_author function upgradeToAndCall(address newImplementation, bytes data) external payable ``` -_Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {\_authorizeUpgrade}. Emits an {Upgraded} event._ + + +*Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.* #### Parameters -| Name | Type | Description | -| ----------------- | ------- | ----------- | -| newImplementation | address | undefined | -| data | bytes | undefined | +| Name | Type | Description | +|---|---|---| +| newImplementation | address | undefined | +| data | bytes | undefined | ### uri @@ -607,19 +674,23 @@ _Upgrade the implementation of the proxy to `newImplementation`, and subsequentl function uri(uint256 tokenID) external view returns (string _uri) ``` -_see { IHypercertMetadata}_ + + +*see { IHypercertMetadata}* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| tokenID | uint256 | undefined | #### Returns -| Name | Type | Description | -| ----- | ------ | ----------- | -| \_uri | string | undefined | +| Name | Type | Description | +|---|---|---| +| _uri | string | undefined | + + ## Events @@ -629,12 +700,16 @@ _see { IHypercertMetadata}_ event AdminChanged(address previousAdmin, address newAdmin) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------- | ------- | ----------- | -| previousAdmin | address | undefined | -| newAdmin | address | undefined | +| Name | Type | Description | +|---|---|---| +| previousAdmin | address | undefined | +| newAdmin | address | undefined | ### AllowlistCreated @@ -642,12 +717,16 @@ event AdminChanged(address previousAdmin, address newAdmin) event AllowlistCreated(uint256 tokenID, bytes32 root) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | -| root | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| tokenID | uint256 | undefined | +| root | bytes32 | undefined | ### ApprovalForAll @@ -655,13 +734,17 @@ event AllowlistCreated(uint256 tokenID, bytes32 root) event ApprovalForAll(address indexed account, address indexed operator, bool approved) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------------ | ------- | ----------- | -| account `indexed` | address | undefined | -| operator `indexed` | address | undefined | -| approved | bool | undefined | +| Name | Type | Description | +|---|---|---| +| account `indexed` | address | undefined | +| operator `indexed` | address | undefined | +| approved | bool | undefined | ### BatchValueTransfer @@ -669,14 +752,18 @@ event ApprovalForAll(address indexed account, address indexed operator, bool app event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------ | --------- | ----------- | -| claimIDs | uint256[] | undefined | -| fromTokenIDs | uint256[] | undefined | -| toTokenIDs | uint256[] | undefined | -| values | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| claimIDs | uint256[] | undefined | +| fromTokenIDs | uint256[] | undefined | +| toTokenIDs | uint256[] | undefined | +| values | uint256[] | undefined | ### BeaconUpgraded @@ -684,11 +771,15 @@ event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] t event BeaconUpgraded(address indexed beacon) ``` + + + + #### Parameters -| Name | Type | Description | -| ---------------- | ------- | ----------- | -| beacon `indexed` | address | undefined | +| Name | Type | Description | +|---|---|---| +| beacon `indexed` | address | undefined | ### ClaimStored @@ -696,13 +787,17 @@ event BeaconUpgraded(address indexed beacon) event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits) ``` + + + + #### Parameters -| Name | Type | Description | -| ----------------- | ------- | ----------- | -| claimID `indexed` | uint256 | undefined | -| uri | string | undefined | -| totalUnits | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| claimID `indexed` | uint256 | undefined | +| uri | string | undefined | +| totalUnits | uint256 | undefined | ### Initialized @@ -710,11 +805,15 @@ event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits) event Initialized(uint8 version) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | ----- | ----------- | -| version | uint8 | undefined | +| Name | Type | Description | +|---|---|---| +| version | uint8 | undefined | ### LeafClaimed @@ -722,12 +821,16 @@ event Initialized(uint8 version) event LeafClaimed(uint256 tokenID, bytes32 leaf) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | -| leaf | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| tokenID | uint256 | undefined | +| leaf | bytes32 | undefined | ### OwnershipTransferred @@ -735,12 +838,16 @@ event LeafClaimed(uint256 tokenID, bytes32 leaf) event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) ``` + + + + #### Parameters -| Name | Type | Description | -| ----------------------- | ------- | ----------- | -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### Paused @@ -748,11 +855,15 @@ event OwnershipTransferred(address indexed previousOwner, address indexed newOwn event Paused(address account) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| account | address | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | ### TransferBatch @@ -760,15 +871,19 @@ event Paused(address account) event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------------ | --------- | ----------- | -| operator `indexed` | address | undefined | -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| ids | uint256[] | undefined | -| values | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| operator `indexed` | address | undefined | +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| ids | uint256[] | undefined | +| values | uint256[] | undefined | ### TransferSingle @@ -776,15 +891,19 @@ event TransferBatch(address indexed operator, address indexed from, address inde event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------------ | ------- | ----------- | -| operator `indexed` | address | undefined | -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| id | uint256 | undefined | -| value | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| operator `indexed` | address | undefined | +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| id | uint256 | undefined | +| value | uint256 | undefined | ### URI @@ -792,12 +911,16 @@ event TransferSingle(address indexed operator, address indexed from, address ind event URI(string value, uint256 indexed id) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------ | ------- | ----------- | -| value | string | undefined | -| id `indexed` | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| value | string | undefined | +| id `indexed` | uint256 | undefined | ### Unpaused @@ -805,11 +928,15 @@ event URI(string value, uint256 indexed id) event Unpaused(address account) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| account | address | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | ### Upgraded @@ -817,11 +944,15 @@ event Unpaused(address account) event Upgraded(address indexed implementation) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------------------ | ------- | ----------- | -| implementation `indexed` | address | undefined | +| Name | Type | Description | +|---|---|---| +| implementation `indexed` | address | undefined | ### ValueTransfer @@ -829,14 +960,20 @@ event Upgraded(address indexed implementation) event ValueTransfer(uint256 claimID, uint256 fromTokenID, uint256 toTokenID, uint256 value) ``` + + + + #### Parameters -| Name | Type | Description | -| ----------- | ------- | ----------- | -| claimID | uint256 | undefined | -| fromTokenID | uint256 | undefined | -| toTokenID | uint256 | undefined | -| value | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| claimID | uint256 | undefined | +| fromTokenID | uint256 | undefined | +| toTokenID | uint256 | undefined | +| value | uint256 | undefined | + + ## Errors @@ -846,50 +983,97 @@ event ValueTransfer(uint256 claimID, uint256 fromTokenID, uint256 toTokenID, uin error AlreadyClaimed() ``` + + + + + ### ArraySize ```solidity error ArraySize() ``` + + + + + ### DoesNotExist ```solidity error DoesNotExist() ``` + + + + + ### DuplicateEntry ```solidity error DuplicateEntry() ``` + + + + + ### Invalid ```solidity error Invalid() ``` + + + + + ### NotAllowed ```solidity error NotAllowed() ``` + + + + + ### NotApprovedOrOwner ```solidity error NotApprovedOrOwner() ``` + + + + + ### TransfersNotAllowed ```solidity error TransfersNotAllowed() ``` + + + + + ### TypeMismatch ```solidity error TypeMismatch() ``` + + + + + + + diff --git a/docs/docs/developer/api/contracts/SemiFungible1155.md b/docs/docs/developer/api/contracts/SemiFungible1155.md index a4086e37..74ef6554 100644 --- a/docs/docs/developer/api/contracts/SemiFungible1155.md +++ b/docs/docs/developer/api/contracts/SemiFungible1155.md @@ -1,22 +1,25 @@ # SemiFungible1155 -_bitbeckers_ +*bitbeckers* > Contract for minting semi-fungible EIP1155 tokens Extends { Upgradeable1155 } token with semi-fungible properties and the concept of `units` -_Adds split bit strategy as described in [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155#non-fungible-tokens)_ +*Adds split bit strategy as described in [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155#non-fungible-tokens)* ## Methods -### \_\_SemiFungible1155_init +### __SemiFungible1155_init ```solidity function __SemiFungible1155_init() external nonpayable ``` -_see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol }_ + + +*see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol }* + ### balanceOf @@ -24,20 +27,22 @@ _see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.so function balanceOf(address account, uint256 id) external view returns (uint256) ``` -_See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address._ + + +*See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address.* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| account | address | undefined | -| id | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| id | uint256 | undefined | #### Returns -| Name | Type | Description | -| ---- | ------- | ----------- | -| \_0 | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | ### balanceOfBatch @@ -45,20 +50,22 @@ _See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address. function balanceOfBatch(address[] accounts, uint256[] ids) external view returns (uint256[]) ``` -_See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length._ + + +*See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length.* #### Parameters -| Name | Type | Description | -| -------- | --------- | ----------- | -| accounts | address[] | undefined | -| ids | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| accounts | address[] | undefined | +| ids | uint256[] | undefined | #### Returns -| Name | Type | Description | -| ---- | --------- | ----------- | -| \_0 | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | uint256[] | undefined | ### burn @@ -66,13 +73,17 @@ _See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have t function burn(address account, uint256 id, uint256 value) external nonpayable ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| account | address | undefined | -| id | uint256 | undefined | -| value | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| id | uint256 | undefined | +| value | uint256 | undefined | ### burnBatch @@ -80,13 +91,17 @@ function burn(address account, uint256 id, uint256 value) external nonpayable function burnBatch(address account, uint256[] ids, uint256[] values) external nonpayable ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | --------- | ----------- | -| account | address | undefined | -| ids | uint256[] | undefined | -| values | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| ids | uint256[] | undefined | +| values | uint256[] | undefined | ### isApprovedForAll @@ -94,20 +109,22 @@ function burnBatch(address account, uint256[] ids, uint256[] values) external no function isApprovedForAll(address account, address operator) external view returns (bool) ``` -_See {IERC1155-isApprovedForAll}._ + + +*See {IERC1155-isApprovedForAll}.* #### Parameters -| Name | Type | Description | -| -------- | ------- | ----------- | -| account | address | undefined | -| operator | address | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| operator | address | undefined | #### Returns | Name | Type | Description | -| ---- | ---- | ----------- | -| \_0 | bool | undefined | +|---|---|---| +| _0 | bool | undefined | ### owner @@ -115,13 +132,16 @@ _See {IERC1155-isApprovedForAll}._ function owner() external view returns (address) ``` -_Returns the address of the current owner._ + + +*Returns the address of the current owner.* + #### Returns -| Name | Type | Description | -| ---- | ------- | ----------- | -| \_0 | address | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | address | undefined | ### ownerOf @@ -129,19 +149,21 @@ _Returns the address of the current owner._ function ownerOf(uint256 tokenID) external view returns (address _owner) ``` -_Returns the owner of a given token ID._ + + +*Returns the owner of a given token ID.* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------------------------- | +| Name | Type | Description | +|---|---|---| | tokenID | uint256 | The ID of the token to query. | #### Returns -| Name | Type | Description | -| ------- | ------- | -------------------------------------- | -| \_owner | address | The address of the owner of the token. | +| Name | Type | Description | +|---|---|---| +| _owner | address | The address of the owner of the token. | ### proxiableUUID @@ -149,13 +171,16 @@ _Returns the owner of a given token ID._ function proxiableUUID() external view returns (bytes32) ``` -_Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier._ + + +*Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.* + #### Returns -| Name | Type | Description | -| ---- | ------- | ----------- | -| \_0 | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| _0 | bytes32 | undefined | ### renounceOwnership @@ -163,7 +188,10 @@ _Implementation of the ERC1822 {proxiableUUID} function. This returns the storag function renounceOwnership() external nonpayable ``` -_Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner._ + + +*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.* + ### safeBatchTransferFrom @@ -171,17 +199,19 @@ _Leaves the contract without owner. It will not be possible to call `onlyOwner` function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] amounts, bytes data) external nonpayable ``` -_See {IERC1155-safeBatchTransferFrom}._ + + +*See {IERC1155-safeBatchTransferFrom}.* #### Parameters -| Name | Type | Description | -| ------- | --------- | ----------- | -| from | address | undefined | -| to | address | undefined | -| ids | uint256[] | undefined | -| amounts | uint256[] | undefined | -| data | bytes | undefined | +| Name | Type | Description | +|---|---|---| +| from | address | undefined | +| to | address | undefined | +| ids | uint256[] | undefined | +| amounts | uint256[] | undefined | +| data | bytes | undefined | ### safeTransferFrom @@ -189,17 +219,19 @@ _See {IERC1155-safeBatchTransferFrom}._ function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes data) external nonpayable ``` -_See {IERC1155-safeTransferFrom}._ + + +*See {IERC1155-safeTransferFrom}.* #### Parameters -| Name | Type | Description | -| ------ | ------- | ----------- | -| from | address | undefined | -| to | address | undefined | -| id | uint256 | undefined | -| amount | uint256 | undefined | -| data | bytes | undefined | +| Name | Type | Description | +|---|---|---| +| from | address | undefined | +| to | address | undefined | +| id | uint256 | undefined | +| amount | uint256 | undefined | +| data | bytes | undefined | ### setApprovalForAll @@ -207,14 +239,16 @@ _See {IERC1155-safeTransferFrom}._ function setApprovalForAll(address operator, bool approved) external nonpayable ``` -_See {IERC1155-setApprovalForAll}._ + + +*See {IERC1155-setApprovalForAll}.* #### Parameters -| Name | Type | Description | -| -------- | ------- | ----------- | -| operator | address | undefined | -| approved | bool | undefined | +| Name | Type | Description | +|---|---|---| +| operator | address | undefined | +| approved | bool | undefined | ### supportsInterface @@ -222,19 +256,21 @@ _See {IERC1155-setApprovalForAll}._ function supportsInterface(bytes4 interfaceId) external view returns (bool) ``` -_See {IERC165-supportsInterface}._ + + +*See {IERC165-supportsInterface}.* #### Parameters -| Name | Type | Description | -| ----------- | ------ | ----------- | -| interfaceId | bytes4 | undefined | +| Name | Type | Description | +|---|---|---| +| interfaceId | bytes4 | undefined | #### Returns | Name | Type | Description | -| ---- | ---- | ----------- | -| \_0 | bool | undefined | +|---|---|---| +| _0 | bool | undefined | ### transferOwnership @@ -242,13 +278,15 @@ _See {IERC165-supportsInterface}._ function transferOwnership(address newOwner) external nonpayable ``` -_Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner._ + + +*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.* #### Parameters -| Name | Type | Description | -| -------- | ------- | ----------- | -| newOwner | address | undefined | +| Name | Type | Description | +|---|---|---| +| newOwner | address | undefined | ### upgradeTo @@ -256,13 +294,15 @@ _Transfers ownership of the contract to a new account (`newOwner`). Can only be function upgradeTo(address newImplementation) external nonpayable ``` -_Upgrade the implementation of the proxy to `newImplementation`. Calls {\_authorizeUpgrade}. Emits an {Upgraded} event._ + + +*Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.* #### Parameters -| Name | Type | Description | -| ----------------- | ------- | ----------- | -| newImplementation | address | undefined | +| Name | Type | Description | +|---|---|---| +| newImplementation | address | undefined | ### upgradeToAndCall @@ -270,14 +310,16 @@ _Upgrade the implementation of the proxy to `newImplementation`. Calls {\_author function upgradeToAndCall(address newImplementation, bytes data) external payable ``` -_Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {\_authorizeUpgrade}. Emits an {Upgraded} event._ + + +*Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.* #### Parameters -| Name | Type | Description | -| ----------------- | ------- | ----------- | -| newImplementation | address | undefined | -| data | bytes | undefined | +| Name | Type | Description | +|---|---|---| +| newImplementation | address | undefined | +| data | bytes | undefined | ### uri @@ -285,19 +327,23 @@ _Upgrade the implementation of the proxy to `newImplementation`, and subsequentl function uri(uint256 tokenID) external view returns (string _uri) ``` -_Returns the metadata URI for a given token ID.This function retrieves the metadata URI for the specified token ID by calling the `uri` function of the `ERC1155URIStorageUpgradeable` contract.The metadata URI is a string that points to a JSON file containing information about the token, such as its name, symbol, and image.This function always returns the URI for the basetype so that it's managed in one place._ + + +*Returns the metadata URI for a given token ID.This function retrieves the metadata URI for the specified token ID by calling the `uri` function of the `ERC1155URIStorageUpgradeable` contract.The metadata URI is a string that points to a JSON file containing information about the token, such as its name, symbol, and image.This function always returns the URI for the basetype so that it's managed in one place.* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------------------------------------------------- | +| Name | Type | Description | +|---|---|---| | tokenID | uint256 | The ID of the token to retrieve the metadata URI for. | #### Returns -| Name | Type | Description | -| ----- | ------ | -------------------------------------------- | -| \_uri | string | The metadata URI for the specified token ID. | +| Name | Type | Description | +|---|---|---| +| _uri | string | The metadata URI for the specified token ID. | + + ## Events @@ -307,12 +353,16 @@ _Returns the metadata URI for a given token ID.This function retrieves the metad event AdminChanged(address previousAdmin, address newAdmin) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------- | ------- | ----------- | -| previousAdmin | address | undefined | -| newAdmin | address | undefined | +| Name | Type | Description | +|---|---|---| +| previousAdmin | address | undefined | +| newAdmin | address | undefined | ### ApprovalForAll @@ -320,13 +370,17 @@ event AdminChanged(address previousAdmin, address newAdmin) event ApprovalForAll(address indexed account, address indexed operator, bool approved) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------------ | ------- | ----------- | -| account `indexed` | address | undefined | -| operator `indexed` | address | undefined | -| approved | bool | undefined | +| Name | Type | Description | +|---|---|---| +| account `indexed` | address | undefined | +| operator `indexed` | address | undefined | +| approved | bool | undefined | ### BatchValueTransfer @@ -334,16 +388,18 @@ event ApprovalForAll(address indexed account, address indexed operator, bool app event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values) ``` -_Emitted on transfer of `values` between `fromTokenIDs` to `toTokenIDs` of `claimIDs`_ + + +*Emitted on transfer of `values` between `fromTokenIDs` to `toTokenIDs` of `claimIDs`* #### Parameters -| Name | Type | Description | -| ------------ | --------- | ----------- | -| claimIDs | uint256[] | undefined | -| fromTokenIDs | uint256[] | undefined | -| toTokenIDs | uint256[] | undefined | -| values | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| claimIDs | uint256[] | undefined | +| fromTokenIDs | uint256[] | undefined | +| toTokenIDs | uint256[] | undefined | +| values | uint256[] | undefined | ### BeaconUpgraded @@ -351,11 +407,15 @@ _Emitted on transfer of `values` between `fromTokenIDs` to `toTokenIDs` of `clai event BeaconUpgraded(address indexed beacon) ``` + + + + #### Parameters -| Name | Type | Description | -| ---------------- | ------- | ----------- | -| beacon `indexed` | address | undefined | +| Name | Type | Description | +|---|---|---| +| beacon `indexed` | address | undefined | ### Initialized @@ -363,11 +423,15 @@ event BeaconUpgraded(address indexed beacon) event Initialized(uint8 version) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | ----- | ----------- | -| version | uint8 | undefined | +| Name | Type | Description | +|---|---|---| +| version | uint8 | undefined | ### OwnershipTransferred @@ -375,12 +439,16 @@ event Initialized(uint8 version) event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) ``` + + + + #### Parameters -| Name | Type | Description | -| ----------------------- | ------- | ----------- | -| previousOwner `indexed` | address | undefined | -| newOwner `indexed` | address | undefined | +| Name | Type | Description | +|---|---|---| +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### TransferBatch @@ -388,15 +456,19 @@ event OwnershipTransferred(address indexed previousOwner, address indexed newOwn event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------------ | --------- | ----------- | -| operator `indexed` | address | undefined | -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| ids | uint256[] | undefined | -| values | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| operator `indexed` | address | undefined | +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| ids | uint256[] | undefined | +| values | uint256[] | undefined | ### TransferSingle @@ -404,15 +476,19 @@ event TransferBatch(address indexed operator, address indexed from, address inde event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------------ | ------- | ----------- | -| operator `indexed` | address | undefined | -| from `indexed` | address | undefined | -| to `indexed` | address | undefined | -| id | uint256 | undefined | -| value | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| operator `indexed` | address | undefined | +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| id | uint256 | undefined | +| value | uint256 | undefined | ### URI @@ -420,12 +496,16 @@ event TransferSingle(address indexed operator, address indexed from, address ind event URI(string value, uint256 indexed id) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------ | ------- | ----------- | -| value | string | undefined | -| id `indexed` | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| value | string | undefined | +| id `indexed` | uint256 | undefined | ### Upgraded @@ -433,11 +513,15 @@ event URI(string value, uint256 indexed id) event Upgraded(address indexed implementation) ``` + + + + #### Parameters -| Name | Type | Description | -| ------------------------ | ------- | ----------- | -| implementation `indexed` | address | undefined | +| Name | Type | Description | +|---|---|---| +| implementation `indexed` | address | undefined | ### ValueTransfer @@ -445,13 +529,18 @@ event Upgraded(address indexed implementation) event ValueTransfer(uint256 claimID, uint256 fromTokenID, uint256 toTokenID, uint256 value) ``` -_Emitted on transfer of `value` between `fromTokenID` to `toTokenID` of the same `claimID`_ + + +*Emitted on transfer of `value` between `fromTokenID` to `toTokenID` of the same `claimID`* #### Parameters -| Name | Type | Description | -| ----------- | ------- | ----------- | -| claimID | uint256 | undefined | -| fromTokenID | uint256 | undefined | -| toTokenID | uint256 | undefined | -| value | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| claimID | uint256 | undefined | +| fromTokenID | uint256 | undefined | +| toTokenID | uint256 | undefined | +| value | uint256 | undefined | + + + diff --git a/docs/docs/developer/api/contracts/interfaces/IAllowlist.md b/docs/docs/developer/api/contracts/interfaces/IAllowlist.md index 72455b43..cbdf10e1 100644 --- a/docs/docs/developer/api/contracts/interfaces/IAllowlist.md +++ b/docs/docs/developer/api/contracts/interfaces/IAllowlist.md @@ -1,11 +1,13 @@ # IAllowlist -_bitbeckers_ +*bitbeckers* > Interface for allowlist This interface declares the required functionality for a hypercert tokenThis interface does not specify the underlying token type (e.g. 721 or 1155) + + ## Methods ### isAllowedToClaim @@ -14,16 +16,24 @@ This interface declares the required functionality for a hypercert tokenThis int function isAllowedToClaim(bytes32[] proof, uint256 tokenID, bytes32 leaf) external view returns (bool isAllowed) ``` + + + + #### Parameters -| Name | Type | Description | -| ------- | --------- | ----------- | -| proof | bytes32[] | undefined | -| tokenID | uint256 | undefined | -| leaf | bytes32 | undefined | +| Name | Type | Description | +|---|---|---| +| proof | bytes32[] | undefined | +| tokenID | uint256 | undefined | +| leaf | bytes32 | undefined | #### Returns -| Name | Type | Description | -| --------- | ---- | ----------- | -| isAllowed | bool | undefined | +| Name | Type | Description | +|---|---|---| +| isAllowed | bool | undefined | + + + + diff --git a/docs/docs/developer/api/contracts/interfaces/IHypercertToken.md b/docs/docs/developer/api/contracts/interfaces/IHypercertToken.md index 30ed6f95..3c2ecba7 100644 --- a/docs/docs/developer/api/contracts/interfaces/IHypercertToken.md +++ b/docs/docs/developer/api/contracts/interfaces/IHypercertToken.md @@ -1,11 +1,13 @@ # IHypercertToken -_bitbeckers_ +*bitbeckers* > Interface for hypercert token interactions This interface declares the required functionality for a hypercert tokenThis interface does not specify the underlying token type (e.g. 721 or 1155) + + ## Methods ### batchBurnFraction @@ -16,14 +18,14 @@ function batchBurnFraction(address account, uint256[] tokenIDs) external nonpaya Operator must be allowed by `creator` and the tokens must represent the total amount of available units. -_Function to burn the tokens at `tokenIDs` for `account`_ +*Function to burn the tokens at `tokenIDs` for `account`* #### Parameters -| Name | Type | Description | -| -------- | --------- | ----------- | -| account | address | undefined | -| tokenIDs | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| tokenIDs | uint256[] | undefined | ### burnFraction @@ -33,14 +35,14 @@ function burnFraction(address account, uint256 tokenID) external nonpayable Operator must be allowed by `creator` and the token must represent the total amount of available units. -_Function to burn the token at `tokenID` for `account`_ +*Function to burn the token at `tokenID` for `account`* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| account | address | undefined | -| tokenID | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| tokenID | uint256 | undefined | ### mergeFractions @@ -50,14 +52,14 @@ function mergeFractions(address account, uint256[] tokenIDs) external nonpayable Tokens that have been merged are burned. -_Function called to merge tokens within `tokenIDs`._ +*Function called to merge tokens within `tokenIDs`.* #### Parameters -| Name | Type | Description | -| -------- | --------- | ----------- | -| account | address | undefined | -| tokenIDs | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| tokenIDs | uint256[] | undefined | ### mintClaim @@ -65,16 +67,18 @@ _Function called to merge tokens within `tokenIDs`._ function mintClaim(address account, uint256 units, string uri, enum IHypercertToken.TransferRestrictions restrictions) external nonpayable ``` -_Function called to store a claim referenced via `uri` with a maximum number of fractions `units`._ + + +*Function called to store a claim referenced via `uri` with a maximum number of fractions `units`.* #### Parameters -| Name | Type | Description | -| ------------ | ----------------------------------------- | ----------- | -| account | address | undefined | -| units | uint256 | undefined | -| uri | string | undefined | -| restrictions | enum IHypercertToken.TransferRestrictions | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| units | uint256 | undefined | +| uri | string | undefined | +| restrictions | enum IHypercertToken.TransferRestrictions | undefined | ### mintClaimWithFractions @@ -82,17 +86,19 @@ _Function called to store a claim referenced via `uri` with a maximum number of function mintClaimWithFractions(address account, uint256 units, uint256[] fractions, string uri, enum IHypercertToken.TransferRestrictions restrictions) external nonpayable ``` -_Function called to store a claim referenced via `uri` with a set of `fractions`.Fractions are internally summed to total units._ + + +*Function called to store a claim referenced via `uri` with a set of `fractions`.Fractions are internally summed to total units.* #### Parameters -| Name | Type | Description | -| ------------ | ----------------------------------------- | ----------- | -| account | address | undefined | -| units | uint256 | undefined | -| fractions | uint256[] | undefined | -| uri | string | undefined | -| restrictions | enum IHypercertToken.TransferRestrictions | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| units | uint256 | undefined | +| fractions | uint256[] | undefined | +| uri | string | undefined | +| restrictions | enum IHypercertToken.TransferRestrictions | undefined | ### splitFraction @@ -102,15 +108,15 @@ function splitFraction(address account, uint256 tokenID, uint256[] _values) exte The sum of `values` must equal the current value of `_tokenID`. -_Function called to split `tokenID` owned by `account` into units declared in `values`._ +*Function called to split `tokenID` owned by `account` into units declared in `values`.* #### Parameters -| Name | Type | Description | -| -------- | --------- | ----------- | -| account | address | undefined | -| tokenID | uint256 | undefined | -| \_values | uint256[] | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| tokenID | uint256 | undefined | +| _values | uint256[] | undefined | ### unitsOf @@ -118,20 +124,22 @@ _Function called to split `tokenID` owned by `account` into units declared in `v function unitsOf(address account, uint256 tokenID) external view returns (uint256 units) ``` -_Returns the `units` held by `account` of a (fractional) token at `claimID`If `tokenID` is a base type, the total amount of `units` held by `account` for the claim is returned.If `tokenID` is a fractional token, the `units` held by `account` the token is returned_ + + +*Returns the `units` held by `account` of a (fractional) token at `claimID`If `tokenID` is a base type, the total amount of `units` held by `account` for the claim is returned.If `tokenID` is a fractional token, the `units` held by `account` the token is returned* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| account | address | undefined | -| tokenID | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| account | address | undefined | +| tokenID | uint256 | undefined | #### Returns -| Name | Type | Description | -| ----- | ------- | ----------- | -| units | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| units | uint256 | undefined | ### unitsOf @@ -139,19 +147,21 @@ _Returns the `units` held by `account` of a (fractional) token at `claimID`If `t function unitsOf(uint256 tokenID) external view returns (uint256 units) ``` -_Returns the `units` held by a (fractional) token at `claimID`If `tokenID` is a base type, the total amount of `units` for the claim is returned.If `tokenID` is a fractional token, the `units` held by the token is returned_ + + +*Returns the `units` held by a (fractional) token at `claimID`If `tokenID` is a base type, the total amount of `units` for the claim is returned.If `tokenID` is a fractional token, the `units` held by the token is returned* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| tokenID | uint256 | undefined | #### Returns -| Name | Type | Description | -| ----- | ------- | ----------- | -| units | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| units | uint256 | undefined | ### uri @@ -159,19 +169,23 @@ _Returns the `units` held by a (fractional) token at `claimID`If `tokenID` is a function uri(uint256 tokenID) external view returns (string metadata) ``` -_Returns the `uri` for metadata of the claim represented by `tokenID`Metadata must conform to { Hypercert Metadata } spec (based on ERC1155 Metadata)_ + + +*Returns the `uri` for metadata of the claim represented by `tokenID`Metadata must conform to { Hypercert Metadata } spec (based on ERC1155 Metadata)* #### Parameters -| Name | Type | Description | -| ------- | ------- | ----------- | -| tokenID | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| tokenID | uint256 | undefined | #### Returns -| Name | Type | Description | -| -------- | ------ | ----------- | -| metadata | string | undefined | +| Name | Type | Description | +|---|---|---| +| metadata | string | undefined | + + ## Events @@ -181,12 +195,17 @@ _Returns the `uri` for metadata of the claim represented by `tokenID`Metadata mu event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits) ``` -_Emitted when token with tokenID `claimID` is stored, with external data reference via `uri`._ + + +*Emitted when token with tokenID `claimID` is stored, with external data reference via `uri`.* #### Parameters -| Name | Type | Description | -| ----------------- | ------- | ----------- | -| claimID `indexed` | uint256 | undefined | -| uri | string | undefined | -| totalUnits | uint256 | undefined | +| Name | Type | Description | +|---|---|---| +| claimID `indexed` | uint256 | undefined | +| uri | string | undefined | +| totalUnits | uint256 | undefined | + + + diff --git a/docs/docs/developer/api/contracts/libs/Errors.md b/docs/docs/developer/api/contracts/libs/Errors.md index 93fe0124..52031321 100644 --- a/docs/docs/developer/api/contracts/libs/Errors.md +++ b/docs/docs/developer/api/contracts/libs/Errors.md @@ -1,6 +1,14 @@ # Errors -_bitbeckers_ +*bitbeckers* + + + + + + + + ## Errors @@ -10,50 +18,97 @@ _bitbeckers_ error AlreadyClaimed() ``` + + + + + ### ArraySize ```solidity error ArraySize() ``` + + + + + ### DoesNotExist ```solidity error DoesNotExist() ``` + + + + + ### DuplicateEntry ```solidity error DuplicateEntry() ``` + + + + + ### Invalid ```solidity error Invalid() ``` + + + + + ### NotAllowed ```solidity error NotAllowed() ``` + + + + + ### NotApprovedOrOwner ```solidity error NotApprovedOrOwner() ``` + + + + + ### TransfersNotAllowed ```solidity error TransfersNotAllowed() ``` + + + + + ### TypeMismatch ```solidity error TypeMismatch() ``` + + + + + + + diff --git a/graph/abis/HypercertTrader.json b/graph/abis/HypercertTrader.json deleted file mode 100644 index 1f114e5e..00000000 --- a/graph/abis/HypercertTrader.json +++ /dev/null @@ -1,656 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "InvalidBuy", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "InvalidOffer", - "type": "error" - }, - { - "inputs": [], - "name": "NotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "creator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "hypercertContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "fractionID", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "offerID", - "type": "uint256" - } - ], - "name": "OfferCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "offerer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "hypercertContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "fractionID", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "offerID", - "type": "uint256" - } - ], - "name": "OfferCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "seller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "buyer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "hypercertContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fractionID", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "unitsBought", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tokenAmountPerUnit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "offerID", - "type": "uint256" - } - ], - "name": "Trade", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "offerIDs", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "unitAmounts", - "type": "uint256[]" - }, - { - "internalType": "address[]", - "name": "buyTokens", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "tokenAmountsPerUnit", - "type": "uint256[]" - } - ], - "name": "batchBuyUnits", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "offerID", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unitAmount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "buyToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenAmountPerUnit", - "type": "uint256" - } - ], - "name": "buyUnits", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "offerID", - "type": "uint256" - } - ], - "name": "cancelOffer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "hypercertContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fractionID", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unitsForSale", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minUnitsPerTrade", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxUnitsPerTrade", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minimumAmountPerUnit", - "type": "uint256" - } - ], - "internalType": "struct IHypercertTrader.AcceptedToken[]", - "name": "acceptedTokens", - "type": "tuple[]" - } - ], - "name": "createOffer", - "outputs": [ - { - "internalType": "uint256", - "name": "offerID", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "offerID", - "type": "uint256" - } - ], - "name": "getOffer", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "offerer", - "type": "address" - }, - { - "internalType": "address", - "name": "hypercertContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fractionID", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unitsAvailable", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minUnitsPerTrade", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxUnitsPerTrade", - "type": "uint256" - }, - { - "internalType": "enum IHypercertTrader.OfferType", - "name": "offerType", - "type": "uint8" - }, - { - "internalType": "enum IHypercertTrader.OfferStatus", - "name": "status", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minimumAmountPerUnit", - "type": "uint256" - } - ], - "internalType": "struct IHypercertTrader.AcceptedToken[]", - "name": "acceptedTokens", - "type": "tuple[]" - } - ], - "internalType": "struct IHypercertTrader.Offer", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "offers", - "outputs": [ - { - "internalType": "address", - "name": "offerer", - "type": "address" - }, - { - "internalType": "address", - "name": "hypercertContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fractionID", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unitsAvailable", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minUnitsPerTrade", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxUnitsPerTrade", - "type": "uint256" - }, - { - "internalType": "enum IHypercertTrader.OfferType", - "name": "offerType", - "type": "uint8" - }, - { - "internalType": "enum IHypercertTrader.OfferStatus", - "name": "status", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proxiableUUID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "totalUnitsForSale", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - } - ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/graph/generated/HypercertTrader/HypercertTrader.ts b/graph/generated/HypercertTrader/HypercertTrader.ts deleted file mode 100644 index 36aef88f..00000000 --- a/graph/generated/HypercertTrader/HypercertTrader.ts +++ /dev/null @@ -1,954 +0,0 @@ -// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. - -import { - ethereum, - JSONValue, - TypedMap, - Entity, - Bytes, - Address, - BigInt, -} from "@graphprotocol/graph-ts"; - -export class AdminChanged extends ethereum.Event { - get params(): AdminChanged__Params { - return new AdminChanged__Params(this); - } -} - -export class AdminChanged__Params { - _event: AdminChanged; - - constructor(event: AdminChanged) { - this._event = event; - } - - get previousAdmin(): Address { - return this._event.parameters[0].value.toAddress(); - } - - get newAdmin(): Address { - return this._event.parameters[1].value.toAddress(); - } -} - -export class BeaconUpgraded extends ethereum.Event { - get params(): BeaconUpgraded__Params { - return new BeaconUpgraded__Params(this); - } -} - -export class BeaconUpgraded__Params { - _event: BeaconUpgraded; - - constructor(event: BeaconUpgraded) { - this._event = event; - } - - get beacon(): Address { - return this._event.parameters[0].value.toAddress(); - } -} - -export class Initialized extends ethereum.Event { - get params(): Initialized__Params { - return new Initialized__Params(this); - } -} - -export class Initialized__Params { - _event: Initialized; - - constructor(event: Initialized) { - this._event = event; - } - - get version(): i32 { - return this._event.parameters[0].value.toI32(); - } -} - -export class OfferCancelled extends ethereum.Event { - get params(): OfferCancelled__Params { - return new OfferCancelled__Params(this); - } -} - -export class OfferCancelled__Params { - _event: OfferCancelled; - - constructor(event: OfferCancelled) { - this._event = event; - } - - get creator(): Address { - return this._event.parameters[0].value.toAddress(); - } - - get hypercertContract(): Address { - return this._event.parameters[1].value.toAddress(); - } - - get fractionID(): BigInt { - return this._event.parameters[2].value.toBigInt(); - } - - get offerID(): BigInt { - return this._event.parameters[3].value.toBigInt(); - } -} - -export class OfferCreated extends ethereum.Event { - get params(): OfferCreated__Params { - return new OfferCreated__Params(this); - } -} - -export class OfferCreated__Params { - _event: OfferCreated; - - constructor(event: OfferCreated) { - this._event = event; - } - - get offerer(): Address { - return this._event.parameters[0].value.toAddress(); - } - - get hypercertContract(): Address { - return this._event.parameters[1].value.toAddress(); - } - - get fractionID(): BigInt { - return this._event.parameters[2].value.toBigInt(); - } - - get offerID(): BigInt { - return this._event.parameters[3].value.toBigInt(); - } -} - -export class OwnershipTransferred extends ethereum.Event { - get params(): OwnershipTransferred__Params { - return new OwnershipTransferred__Params(this); - } -} - -export class OwnershipTransferred__Params { - _event: OwnershipTransferred; - - constructor(event: OwnershipTransferred) { - this._event = event; - } - - get previousOwner(): Address { - return this._event.parameters[0].value.toAddress(); - } - - get newOwner(): Address { - return this._event.parameters[1].value.toAddress(); - } -} - -export class Paused extends ethereum.Event { - get params(): Paused__Params { - return new Paused__Params(this); - } -} - -export class Paused__Params { - _event: Paused; - - constructor(event: Paused) { - this._event = event; - } - - get account(): Address { - return this._event.parameters[0].value.toAddress(); - } -} - -export class Trade extends ethereum.Event { - get params(): Trade__Params { - return new Trade__Params(this); - } -} - -export class Trade__Params { - _event: Trade; - - constructor(event: Trade) { - this._event = event; - } - - get seller(): Address { - return this._event.parameters[0].value.toAddress(); - } - - get buyer(): Address { - return this._event.parameters[1].value.toAddress(); - } - - get hypercertContract(): Address { - return this._event.parameters[2].value.toAddress(); - } - - get fractionID(): BigInt { - return this._event.parameters[3].value.toBigInt(); - } - - get unitsBought(): BigInt { - return this._event.parameters[4].value.toBigInt(); - } - - get buyToken(): Address { - return this._event.parameters[5].value.toAddress(); - } - - get tokenAmountPerUnit(): BigInt { - return this._event.parameters[6].value.toBigInt(); - } - - get offerID(): BigInt { - return this._event.parameters[7].value.toBigInt(); - } -} - -export class Unpaused extends ethereum.Event { - get params(): Unpaused__Params { - return new Unpaused__Params(this); - } -} - -export class Unpaused__Params { - _event: Unpaused; - - constructor(event: Unpaused) { - this._event = event; - } - - get account(): Address { - return this._event.parameters[0].value.toAddress(); - } -} - -export class Upgraded extends ethereum.Event { - get params(): Upgraded__Params { - return new Upgraded__Params(this); - } -} - -export class Upgraded__Params { - _event: Upgraded; - - constructor(event: Upgraded) { - this._event = event; - } - - get implementation(): Address { - return this._event.parameters[0].value.toAddress(); - } -} - -export class HypercertTrader__getOfferResultValue0Struct extends ethereum.Tuple { - get offerer(): Address { - return this[0].toAddress(); - } - - get hypercertContract(): Address { - return this[1].toAddress(); - } - - get fractionID(): BigInt { - return this[2].toBigInt(); - } - - get unitsAvailable(): BigInt { - return this[3].toBigInt(); - } - - get minUnitsPerTrade(): BigInt { - return this[4].toBigInt(); - } - - get maxUnitsPerTrade(): BigInt { - return this[5].toBigInt(); - } - - get offerType(): i32 { - return this[6].toI32(); - } - - get status(): i32 { - return this[7].toI32(); - } - - get acceptedTokens(): Array { - return this[8].toTupleArray(); - } -} - -export class HypercertTrader__getOfferResultValue0AcceptedTokensStruct extends ethereum.Tuple { - get token(): Address { - return this[0].toAddress(); - } - - get minimumAmountPerUnit(): BigInt { - return this[1].toBigInt(); - } -} - -export class HypercertTrader__offersResult { - value0: Address; - value1: Address; - value2: BigInt; - value3: BigInt; - value4: BigInt; - value5: BigInt; - value6: i32; - value7: i32; - - constructor( - value0: Address, - value1: Address, - value2: BigInt, - value3: BigInt, - value4: BigInt, - value5: BigInt, - value6: i32, - value7: i32, - ) { - this.value0 = value0; - this.value1 = value1; - this.value2 = value2; - this.value3 = value3; - this.value4 = value4; - this.value5 = value5; - this.value6 = value6; - this.value7 = value7; - } - - toMap(): TypedMap { - let map = new TypedMap(); - map.set("value0", ethereum.Value.fromAddress(this.value0)); - map.set("value1", ethereum.Value.fromAddress(this.value1)); - map.set("value2", ethereum.Value.fromUnsignedBigInt(this.value2)); - map.set("value3", ethereum.Value.fromUnsignedBigInt(this.value3)); - map.set("value4", ethereum.Value.fromUnsignedBigInt(this.value4)); - map.set("value5", ethereum.Value.fromUnsignedBigInt(this.value5)); - map.set( - "value6", - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(this.value6)), - ); - map.set( - "value7", - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(this.value7)), - ); - return map; - } - - getOfferer(): Address { - return this.value0; - } - - getHypercertContract(): Address { - return this.value1; - } - - getFractionID(): BigInt { - return this.value2; - } - - getUnitsAvailable(): BigInt { - return this.value3; - } - - getMinUnitsPerTrade(): BigInt { - return this.value4; - } - - getMaxUnitsPerTrade(): BigInt { - return this.value5; - } - - getOfferType(): i32 { - return this.value6; - } - - getStatus(): i32 { - return this.value7; - } -} - -export class HypercertTrader extends ethereum.SmartContract { - static bind(address: Address): HypercertTrader { - return new HypercertTrader("HypercertTrader", address); - } - - getOffer(offerID: BigInt): HypercertTrader__getOfferResultValue0Struct { - let result = super.call( - "getOffer", - "getOffer(uint256):((address,address,uint256,uint256,uint256,uint256,uint8,uint8,(address,uint256)[]))", - [ethereum.Value.fromUnsignedBigInt(offerID)], - ); - - return changetype( - result[0].toTuple(), - ); - } - - try_getOffer( - offerID: BigInt, - ): ethereum.CallResult { - let result = super.tryCall( - "getOffer", - "getOffer(uint256):((address,address,uint256,uint256,uint256,uint256,uint8,uint8,(address,uint256)[]))", - [ethereum.Value.fromUnsignedBigInt(offerID)], - ); - if (result.reverted) { - return new ethereum.CallResult(); - } - let value = result.value; - return ethereum.CallResult.fromValue( - changetype( - value[0].toTuple(), - ), - ); - } - - offers(param0: BigInt): HypercertTrader__offersResult { - let result = super.call( - "offers", - "offers(uint256):(address,address,uint256,uint256,uint256,uint256,uint8,uint8)", - [ethereum.Value.fromUnsignedBigInt(param0)], - ); - - return new HypercertTrader__offersResult( - result[0].toAddress(), - result[1].toAddress(), - result[2].toBigInt(), - result[3].toBigInt(), - result[4].toBigInt(), - result[5].toBigInt(), - result[6].toI32(), - result[7].toI32(), - ); - } - - try_offers( - param0: BigInt, - ): ethereum.CallResult { - let result = super.tryCall( - "offers", - "offers(uint256):(address,address,uint256,uint256,uint256,uint256,uint8,uint8)", - [ethereum.Value.fromUnsignedBigInt(param0)], - ); - if (result.reverted) { - return new ethereum.CallResult(); - } - let value = result.value; - return ethereum.CallResult.fromValue( - new HypercertTrader__offersResult( - value[0].toAddress(), - value[1].toAddress(), - value[2].toBigInt(), - value[3].toBigInt(), - value[4].toBigInt(), - value[5].toBigInt(), - value[6].toI32(), - value[7].toI32(), - ), - ); - } - - owner(): Address { - let result = super.call("owner", "owner():(address)", []); - - return result[0].toAddress(); - } - - try_owner(): ethereum.CallResult
{ - let result = super.tryCall("owner", "owner():(address)", []); - if (result.reverted) { - return new ethereum.CallResult(); - } - let value = result.value; - return ethereum.CallResult.fromValue(value[0].toAddress()); - } - - paused(): boolean { - let result = super.call("paused", "paused():(bool)", []); - - return result[0].toBoolean(); - } - - try_paused(): ethereum.CallResult { - let result = super.tryCall("paused", "paused():(bool)", []); - if (result.reverted) { - return new ethereum.CallResult(); - } - let value = result.value; - return ethereum.CallResult.fromValue(value[0].toBoolean()); - } - - proxiableUUID(): Bytes { - let result = super.call("proxiableUUID", "proxiableUUID():(bytes32)", []); - - return result[0].toBytes(); - } - - try_proxiableUUID(): ethereum.CallResult { - let result = super.tryCall( - "proxiableUUID", - "proxiableUUID():(bytes32)", - [], - ); - if (result.reverted) { - return new ethereum.CallResult(); - } - let value = result.value; - return ethereum.CallResult.fromValue(value[0].toBytes()); - } - - totalUnitsForSale(param0: Address, param1: BigInt): BigInt { - let result = super.call( - "totalUnitsForSale", - "totalUnitsForSale(address,uint256):(uint256)", - [ - ethereum.Value.fromAddress(param0), - ethereum.Value.fromUnsignedBigInt(param1), - ], - ); - - return result[0].toBigInt(); - } - - try_totalUnitsForSale( - param0: Address, - param1: BigInt, - ): ethereum.CallResult { - let result = super.tryCall( - "totalUnitsForSale", - "totalUnitsForSale(address,uint256):(uint256)", - [ - ethereum.Value.fromAddress(param0), - ethereum.Value.fromUnsignedBigInt(param1), - ], - ); - if (result.reverted) { - return new ethereum.CallResult(); - } - let value = result.value; - return ethereum.CallResult.fromValue(value[0].toBigInt()); - } -} - -export class ConstructorCall extends ethereum.Call { - get inputs(): ConstructorCall__Inputs { - return new ConstructorCall__Inputs(this); - } - - get outputs(): ConstructorCall__Outputs { - return new ConstructorCall__Outputs(this); - } -} - -export class ConstructorCall__Inputs { - _call: ConstructorCall; - - constructor(call: ConstructorCall) { - this._call = call; - } -} - -export class ConstructorCall__Outputs { - _call: ConstructorCall; - - constructor(call: ConstructorCall) { - this._call = call; - } -} - -export class BatchBuyUnitsCall extends ethereum.Call { - get inputs(): BatchBuyUnitsCall__Inputs { - return new BatchBuyUnitsCall__Inputs(this); - } - - get outputs(): BatchBuyUnitsCall__Outputs { - return new BatchBuyUnitsCall__Outputs(this); - } -} - -export class BatchBuyUnitsCall__Inputs { - _call: BatchBuyUnitsCall; - - constructor(call: BatchBuyUnitsCall) { - this._call = call; - } - - get recipient(): Address { - return this._call.inputValues[0].value.toAddress(); - } - - get offerIDs(): Array { - return this._call.inputValues[1].value.toBigIntArray(); - } - - get unitAmounts(): Array { - return this._call.inputValues[2].value.toBigIntArray(); - } - - get buyTokens(): Array
{ - return this._call.inputValues[3].value.toAddressArray(); - } - - get tokenAmountsPerUnit(): Array { - return this._call.inputValues[4].value.toBigIntArray(); - } -} - -export class BatchBuyUnitsCall__Outputs { - _call: BatchBuyUnitsCall; - - constructor(call: BatchBuyUnitsCall) { - this._call = call; - } -} - -export class BuyUnitsCall extends ethereum.Call { - get inputs(): BuyUnitsCall__Inputs { - return new BuyUnitsCall__Inputs(this); - } - - get outputs(): BuyUnitsCall__Outputs { - return new BuyUnitsCall__Outputs(this); - } -} - -export class BuyUnitsCall__Inputs { - _call: BuyUnitsCall; - - constructor(call: BuyUnitsCall) { - this._call = call; - } - - get recipient(): Address { - return this._call.inputValues[0].value.toAddress(); - } - - get offerID(): BigInt { - return this._call.inputValues[1].value.toBigInt(); - } - - get unitAmount(): BigInt { - return this._call.inputValues[2].value.toBigInt(); - } - - get buyToken(): Address { - return this._call.inputValues[3].value.toAddress(); - } - - get tokenAmountPerUnit(): BigInt { - return this._call.inputValues[4].value.toBigInt(); - } -} - -export class BuyUnitsCall__Outputs { - _call: BuyUnitsCall; - - constructor(call: BuyUnitsCall) { - this._call = call; - } -} - -export class CancelOfferCall extends ethereum.Call { - get inputs(): CancelOfferCall__Inputs { - return new CancelOfferCall__Inputs(this); - } - - get outputs(): CancelOfferCall__Outputs { - return new CancelOfferCall__Outputs(this); - } -} - -export class CancelOfferCall__Inputs { - _call: CancelOfferCall; - - constructor(call: CancelOfferCall) { - this._call = call; - } - - get offerID(): BigInt { - return this._call.inputValues[0].value.toBigInt(); - } -} - -export class CancelOfferCall__Outputs { - _call: CancelOfferCall; - - constructor(call: CancelOfferCall) { - this._call = call; - } -} - -export class CreateOfferCall extends ethereum.Call { - get inputs(): CreateOfferCall__Inputs { - return new CreateOfferCall__Inputs(this); - } - - get outputs(): CreateOfferCall__Outputs { - return new CreateOfferCall__Outputs(this); - } -} - -export class CreateOfferCall__Inputs { - _call: CreateOfferCall; - - constructor(call: CreateOfferCall) { - this._call = call; - } - - get hypercertContract(): Address { - return this._call.inputValues[0].value.toAddress(); - } - - get fractionID(): BigInt { - return this._call.inputValues[1].value.toBigInt(); - } - - get unitsForSale(): BigInt { - return this._call.inputValues[2].value.toBigInt(); - } - - get minUnitsPerTrade(): BigInt { - return this._call.inputValues[3].value.toBigInt(); - } - - get maxUnitsPerTrade(): BigInt { - return this._call.inputValues[4].value.toBigInt(); - } - - get acceptedTokens(): Array { - return this._call.inputValues[5].value.toTupleArray(); - } -} - -export class CreateOfferCall__Outputs { - _call: CreateOfferCall; - - constructor(call: CreateOfferCall) { - this._call = call; - } - - get offerID(): BigInt { - return this._call.outputValues[0].value.toBigInt(); - } -} - -export class CreateOfferCallAcceptedTokensStruct extends ethereum.Tuple { - get token(): Address { - return this[0].toAddress(); - } - - get minimumAmountPerUnit(): BigInt { - return this[1].toBigInt(); - } -} - -export class InitializeCall extends ethereum.Call { - get inputs(): InitializeCall__Inputs { - return new InitializeCall__Inputs(this); - } - - get outputs(): InitializeCall__Outputs { - return new InitializeCall__Outputs(this); - } -} - -export class InitializeCall__Inputs { - _call: InitializeCall; - - constructor(call: InitializeCall) { - this._call = call; - } -} - -export class InitializeCall__Outputs { - _call: InitializeCall; - - constructor(call: InitializeCall) { - this._call = call; - } -} - -export class PauseCall extends ethereum.Call { - get inputs(): PauseCall__Inputs { - return new PauseCall__Inputs(this); - } - - get outputs(): PauseCall__Outputs { - return new PauseCall__Outputs(this); - } -} - -export class PauseCall__Inputs { - _call: PauseCall; - - constructor(call: PauseCall) { - this._call = call; - } -} - -export class PauseCall__Outputs { - _call: PauseCall; - - constructor(call: PauseCall) { - this._call = call; - } -} - -export class RenounceOwnershipCall extends ethereum.Call { - get inputs(): RenounceOwnershipCall__Inputs { - return new RenounceOwnershipCall__Inputs(this); - } - - get outputs(): RenounceOwnershipCall__Outputs { - return new RenounceOwnershipCall__Outputs(this); - } -} - -export class RenounceOwnershipCall__Inputs { - _call: RenounceOwnershipCall; - - constructor(call: RenounceOwnershipCall) { - this._call = call; - } -} - -export class RenounceOwnershipCall__Outputs { - _call: RenounceOwnershipCall; - - constructor(call: RenounceOwnershipCall) { - this._call = call; - } -} - -export class TransferOwnershipCall extends ethereum.Call { - get inputs(): TransferOwnershipCall__Inputs { - return new TransferOwnershipCall__Inputs(this); - } - - get outputs(): TransferOwnershipCall__Outputs { - return new TransferOwnershipCall__Outputs(this); - } -} - -export class TransferOwnershipCall__Inputs { - _call: TransferOwnershipCall; - - constructor(call: TransferOwnershipCall) { - this._call = call; - } - - get newOwner(): Address { - return this._call.inputValues[0].value.toAddress(); - } -} - -export class TransferOwnershipCall__Outputs { - _call: TransferOwnershipCall; - - constructor(call: TransferOwnershipCall) { - this._call = call; - } -} - -export class UnpauseCall extends ethereum.Call { - get inputs(): UnpauseCall__Inputs { - return new UnpauseCall__Inputs(this); - } - - get outputs(): UnpauseCall__Outputs { - return new UnpauseCall__Outputs(this); - } -} - -export class UnpauseCall__Inputs { - _call: UnpauseCall; - - constructor(call: UnpauseCall) { - this._call = call; - } -} - -export class UnpauseCall__Outputs { - _call: UnpauseCall; - - constructor(call: UnpauseCall) { - this._call = call; - } -} - -export class UpgradeToCall extends ethereum.Call { - get inputs(): UpgradeToCall__Inputs { - return new UpgradeToCall__Inputs(this); - } - - get outputs(): UpgradeToCall__Outputs { - return new UpgradeToCall__Outputs(this); - } -} - -export class UpgradeToCall__Inputs { - _call: UpgradeToCall; - - constructor(call: UpgradeToCall) { - this._call = call; - } - - get newImplementation(): Address { - return this._call.inputValues[0].value.toAddress(); - } -} - -export class UpgradeToCall__Outputs { - _call: UpgradeToCall; - - constructor(call: UpgradeToCall) { - this._call = call; - } -} - -export class UpgradeToAndCallCall extends ethereum.Call { - get inputs(): UpgradeToAndCallCall__Inputs { - return new UpgradeToAndCallCall__Inputs(this); - } - - get outputs(): UpgradeToAndCallCall__Outputs { - return new UpgradeToAndCallCall__Outputs(this); - } -} - -export class UpgradeToAndCallCall__Inputs { - _call: UpgradeToAndCallCall; - - constructor(call: UpgradeToAndCallCall) { - this._call = call; - } - - get newImplementation(): Address { - return this._call.inputValues[0].value.toAddress(); - } - - get data(): Bytes { - return this._call.inputValues[1].value.toBytes(); - } -} - -export class UpgradeToAndCallCall__Outputs { - _call: UpgradeToAndCallCall; - - constructor(call: UpgradeToAndCallCall) { - this._call = call; - } -} diff --git a/graph/networks.json b/graph/networks.json index 477c6127..28925338 100644 --- a/graph/networks.json +++ b/graph/networks.json @@ -9,10 +9,6 @@ "HypercertMinter": { "address": "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", "startBlock": 8537999 - }, - "HypercertTrader": { - "address": "0x689587461AA3103D3D7975c5e4B352Ab711C14C2", - "startBlock": 9638007 } }, "optimism": { diff --git a/graph/src/hypercert-trader.ts b/graph/src/hypercert-trader.ts deleted file mode 100644 index 5c06f969..00000000 --- a/graph/src/hypercert-trader.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { - OfferCancelled as OfferCancelledEvent, - OfferCreated as OfferCreatedEvent, - Trade as TradeEvent, -} from "../generated/HypercertTrader/HypercertTrader"; -import { Trade } from "../generated/schema"; -import { getOrCreateOffer, getOrCreateOfferByID } from "./utils"; -import { log, BigInt } from "@graphprotocol/graph-ts"; - -export function handleOfferCancelled(event: OfferCancelledEvent): void { - const offer = getOrCreateOfferByID( - event.params.hypercertContract, - event.params.fractionID, - event.params.offerID, - ); - - if (!offer) { - return; - } - - offer.status = "Cancelled"; - - offer.save(); -} - -export function handleOfferCreated(event: OfferCreatedEvent): void { - const offer = getOrCreateOffer( - event.params.hypercertContract, - event.address, - event.params.fractionID, - event.params.offerID, - ); - - offer.save(); -} - -export function handleTrade(event: TradeEvent): void { - const offer = getOrCreateOfferByID( - event.params.hypercertContract, - event.params.fractionID, - event.params.offerID, - ); - - if (!offer) { - log.error("Offer with ID {} not found", [ - event.params.offerID.toHexString(), - ]); - return; - } - - const tradeID = offer.id.concat(event.transaction.hash.toHexString()); - - let trade = Trade.load(tradeID); - - if (trade == null) { - trade = new Trade(tradeID); - - trade.buyer = event.params.buyer; - trade.offerID = offer.id; - trade.unitsSold = event.params.unitsBought; - trade.token = event.params.buyToken.toHexString(); - trade.amountPerUnit = event.params.tokenAmountPerUnit; - - trade.offerID = offer.id; - } - - offer.unitsAvailable = offer.unitsAvailable.minus(event.params.unitsBought); - if (offer.unitsAvailable.equals(BigInt.fromI32(0))) { - offer.status = "Fulfilled"; - } - - trade.save(); -} diff --git a/graph/src/utils.ts b/graph/src/utils.ts index 42b51fc5..2828cc15 100644 --- a/graph/src/utils.ts +++ b/graph/src/utils.ts @@ -1,5 +1,4 @@ import { HypercertMinter } from "../generated/HypercertMinter/HypercertMinter"; -import { HypercertTrader } from "../generated/HypercertTrader/HypercertTrader"; import { AcceptedToken, Allowlist, diff --git a/graph/subgraph.yaml b/graph/subgraph.yaml index 3c469f83..6b664dde 100644 --- a/graph/subgraph.yaml +++ b/graph/subgraph.yaml @@ -44,27 +44,3 @@ dataSources: - event: BatchValueTransfer(uint256[],uint256[],uint256[],uint256[]) handler: handleBatchValueTransfer file: ./src/hypercert-minter.ts - - kind: ethereum - name: HypercertTrader - network: goerli - source: - address: "0x689587461AA3103D3D7975c5e4B352Ab711C14C2" - abi: HypercertTrader - mapping: - kind: ethereum/events - apiVersion: 0.0.7 - language: wasm/assemblyscript - entities: - - Offer - abis: - - name: HypercertTrader - file: ./abis/HypercertTrader.json - eventHandlers: - - event: OfferCancelled(indexed address,indexed address,indexed uint256,uint256) - handler: handleOfferCancelled - - event: OfferCreated(indexed address,indexed address,indexed uint256,uint256) - handler: handleOfferCreated - - event: Trade(indexed address,indexed address,indexed - address,uint256,uint256,address,uint256,uint256) - handler: handleTrade - file: ./src/hypercert-trader.ts diff --git a/graph/tests/.latest.json b/graph/tests/.latest.json index 29ed621c..9f77af1a 100644 --- a/graph/tests/.latest.json +++ b/graph/tests/.latest.json @@ -1,4 +1,4 @@ { "version": "0.6.0", - "timestamp": 1698242510644 + "timestamp": 1698421837557 } diff --git a/graph/tests/hypercert-trader-utils.ts b/graph/tests/hypercert-trader-utils.ts deleted file mode 100644 index 74ee37c1..00000000 --- a/graph/tests/hypercert-trader-utils.ts +++ /dev/null @@ -1,261 +0,0 @@ -import { - AdminChanged, - BeaconUpgraded, - Initialized, - OfferCancelled, - OfferCreated, - OwnershipTransferred, - Paused, - Trade, - Unpaused, - Upgraded, -} from "../generated/HypercertTrader/HypercertTrader"; -import { ethereum, Address, BigInt } from "@graphprotocol/graph-ts"; -import { newMockEvent } from "matchstick-as"; - -export const DEFAULT_TRADER_ADDRESS = Address.fromString( - "0x0000000000000000000000000000000000001337", -); - -export function createAdminChangedEvent( - previousAdmin: Address, - newAdmin: Address, -): AdminChanged { - let adminChangedEvent = changetype(newMockEvent()); - - adminChangedEvent.parameters = new Array(); - - adminChangedEvent.parameters.push( - new ethereum.EventParam( - "previousAdmin", - ethereum.Value.fromAddress(previousAdmin), - ), - ); - adminChangedEvent.parameters.push( - new ethereum.EventParam("newAdmin", ethereum.Value.fromAddress(newAdmin)), - ); - - return adminChangedEvent; -} - -export function createBeaconUpgradedEvent(beacon: Address): BeaconUpgraded { - let beaconUpgradedEvent = changetype(newMockEvent()); - - beaconUpgradedEvent.parameters = new Array(); - - beaconUpgradedEvent.parameters.push( - new ethereum.EventParam("beacon", ethereum.Value.fromAddress(beacon)), - ); - - return beaconUpgradedEvent; -} - -export function createInitializedEvent(version: i32): Initialized { - let initializedEvent = changetype(newMockEvent()); - - initializedEvent.parameters = new Array(); - - initializedEvent.parameters.push( - new ethereum.EventParam( - "version", - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(version)), - ), - ); - - return initializedEvent; -} - -export function createOfferCancelledEvent( - creator: Address, - hypercertContract: Address, - fractionID: BigInt, - offerID: BigInt, -): OfferCancelled { - let offerCancelledEvent = changetype(newMockEvent()); - - offerCancelledEvent.parameters = new Array(); - - offerCancelledEvent.parameters.push( - new ethereum.EventParam("creator", ethereum.Value.fromAddress(creator)), - ); - offerCancelledEvent.parameters.push( - new ethereum.EventParam( - "hypercertContract", - ethereum.Value.fromAddress(hypercertContract), - ), - ); - offerCancelledEvent.parameters.push( - new ethereum.EventParam( - "fractionID", - ethereum.Value.fromUnsignedBigInt(fractionID), - ), - ); - offerCancelledEvent.parameters.push( - new ethereum.EventParam( - "offerID", - ethereum.Value.fromUnsignedBigInt(offerID), - ), - ); - - offerCancelledEvent.address = DEFAULT_TRADER_ADDRESS; - - return offerCancelledEvent; -} - -export function createOfferCreatedEvent( - offerer: Address, - hypercertContract: Address, - fractionID: BigInt, - offerID: BigInt, -): OfferCreated { - let offerCreatedEvent = changetype(newMockEvent()); - - offerCreatedEvent.parameters = new Array(); - - offerCreatedEvent.parameters.push( - new ethereum.EventParam("offerer", ethereum.Value.fromAddress(offerer)), - ); - offerCreatedEvent.parameters.push( - new ethereum.EventParam( - "hypercertContract", - ethereum.Value.fromAddress(hypercertContract), - ), - ); - offerCreatedEvent.parameters.push( - new ethereum.EventParam( - "fractionID", - ethereum.Value.fromUnsignedBigInt(fractionID), - ), - ); - offerCreatedEvent.parameters.push( - new ethereum.EventParam( - "offerID", - ethereum.Value.fromUnsignedBigInt(offerID), - ), - ); - - offerCreatedEvent.address = DEFAULT_TRADER_ADDRESS; - - return offerCreatedEvent; -} - -export function createOwnershipTransferredEvent( - previousOwner: Address, - newOwner: Address, -): OwnershipTransferred { - let ownershipTransferredEvent = changetype( - newMockEvent(), - ); - - ownershipTransferredEvent.parameters = new Array(); - - ownershipTransferredEvent.parameters.push( - new ethereum.EventParam( - "previousOwner", - ethereum.Value.fromAddress(previousOwner), - ), - ); - ownershipTransferredEvent.parameters.push( - new ethereum.EventParam("newOwner", ethereum.Value.fromAddress(newOwner)), - ); - - return ownershipTransferredEvent; -} - -export function createPausedEvent(account: Address): Paused { - let pausedEvent = changetype(newMockEvent()); - - pausedEvent.parameters = new Array(); - - pausedEvent.parameters.push( - new ethereum.EventParam("account", ethereum.Value.fromAddress(account)), - ); - - return pausedEvent; -} - -export function createTradeEvent( - seller: Address, - buyer: Address, - hypercertContract: Address, - fractionID: BigInt, - unitsBought: BigInt, - buyToken: Address, - tokenAmountPerUnit: BigInt, - offerID: BigInt, -): Trade { - let tradeEvent = changetype(newMockEvent()); - - tradeEvent.parameters = new Array(); - - tradeEvent.parameters.push( - new ethereum.EventParam("seller", ethereum.Value.fromAddress(seller)), - ); - tradeEvent.parameters.push( - new ethereum.EventParam("buyer", ethereum.Value.fromAddress(buyer)), - ); - tradeEvent.parameters.push( - new ethereum.EventParam( - "hypercertContract", - ethereum.Value.fromAddress(hypercertContract), - ), - ); - tradeEvent.parameters.push( - new ethereum.EventParam( - "fractionID", - ethereum.Value.fromUnsignedBigInt(fractionID), - ), - ); - tradeEvent.parameters.push( - new ethereum.EventParam( - "unitsBought", - ethereum.Value.fromUnsignedBigInt(unitsBought), - ), - ); - tradeEvent.parameters.push( - new ethereum.EventParam("buyToken", ethereum.Value.fromAddress(buyToken)), - ); - tradeEvent.parameters.push( - new ethereum.EventParam( - "tokenAmountPerUnit", - ethereum.Value.fromUnsignedBigInt(tokenAmountPerUnit), - ), - ); - tradeEvent.parameters.push( - new ethereum.EventParam( - "offerID", - ethereum.Value.fromUnsignedBigInt(offerID), - ), - ); - - tradeEvent.address = DEFAULT_TRADER_ADDRESS; - - return tradeEvent; -} - -export function createUnpausedEvent(account: Address): Unpaused { - let unpausedEvent = changetype(newMockEvent()); - - unpausedEvent.parameters = new Array(); - - unpausedEvent.parameters.push( - new ethereum.EventParam("account", ethereum.Value.fromAddress(account)), - ); - - return unpausedEvent; -} - -export function createUpgradedEvent(implementation: Address): Upgraded { - let upgradedEvent = changetype(newMockEvent()); - - upgradedEvent.parameters = new Array(); - - upgradedEvent.parameters.push( - new ethereum.EventParam( - "implementation", - ethereum.Value.fromAddress(implementation), - ), - ); - - return upgradedEvent; -} diff --git a/graph/tests/hypercert-trader.test.ts b/graph/tests/hypercert-trader.test.ts deleted file mode 100644 index 51230b74..00000000 --- a/graph/tests/hypercert-trader.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { handleOfferCreated } from "../src/hypercert-trader"; -import { ZERO_ADDRESS } from "../src/utils"; -import { - DEFAULT_TRADER_ADDRESS, - createOfferCreatedEvent, -} from "./hypercert-trader-utils"; -import { Address, BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts"; -import { - assert, - describe, - test, - clearStore, - beforeAll, - afterAll, - createMockedFunction, -} from "matchstick-as/assembly/index"; - -// Tests structure (matchstick-as >=0.5.0) -// https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0 - -describe("Describe entity assertions", () => { - beforeAll(() => { - let acceptedToken: Array = [ - ethereum.Value.fromAddress( - Address.fromString("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7"), - ), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ]; - - let tuple = changetype(acceptedToken); - let tupleValue = ethereum.Value.fromTupleArray([tuple]); - - const returnValues = [ - ethereum.Value.fromAddress( - Address.fromString("0x0000000000000000000000000000000000000003"), - ), - ethereum.Value.fromAddress( - Address.fromString("0x0000000000000000000000000000000000000004"), - ), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1)), - ethereum.Value.fromTupleArray([tuple]), - ]; - - let returnValueTuple = changetype(returnValues); - let returnValue = ethereum.Value.fromTuple(returnValueTuple); - - createMockedFunction( - DEFAULT_TRADER_ADDRESS, - "getOffer", - "getOffer(uint256):((address,address,uint256,uint256,uint256,uint256,uint8,uint8,(address,uint256)[]))", - ) - .withArgs([ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(1))]) - .returns([returnValue]); - }); - - afterAll(() => { - clearStore(); - }); - - test("Offer created and stored", () => { - assert.entityCount("Offer", 0); - - // Create an OfferCreated event - let offerCreatedEvent = createOfferCreatedEvent( - Address.fromString("0x0000000000000000000000000000000000000001"), - Address.fromString("0x0000000000000000000000000000000000000002"), - BigInt.fromI32(1), - BigInt.fromI32(1), - ); - - handleOfferCreated(offerCreatedEvent); - - assert.entityCount("Offer", 1); - }); -}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2e178258..988958cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,6 +33,9 @@ importers: contracts: devDependencies: + '@chainlink/contracts': + specifier: ^0.8.0 + version: 0.8.0(ethers@5.7.2) '@commitlint/cli': specifier: ^17.1.2 version: 17.8.1 @@ -51,6 +54,9 @@ importers: '@ethersproject/providers': specifier: ^5.7.2 version: 5.7.2 + '@looksrare/contracts-libs': + specifier: ^3.4.0 + version: 3.4.0 '@nomicfoundation/hardhat-chai-matchers': specifier: ^1.0.5 version: 1.0.6(@nomiclabs/hardhat-ethers@2.2.3)(chai@4.3.10)(ethers@5.7.2)(hardhat@2.13.1) @@ -59,13 +65,16 @@ importers: version: 1.0.9(hardhat@2.13.1) '@nomicfoundation/hardhat-toolbox': specifier: ^2.0.0 - version: 2.0.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-chai-matchers@1.0.6)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(@typechain/ethers-v5@11.1.2)(@typechain/hardhat@9.1.0)(@types/chai@4.3.9)(@types/mocha@9.1.0)(@types/node@18.18.6)(chai@4.3.10)(ethers@5.7.2)(hardhat-gas-reporter@1.0.9)(hardhat@2.13.1)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.2)(typescript@4.9.5) + version: 2.0.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-chai-matchers@1.0.6)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(@typechain/ethers-v5@11.1.2)(@typechain/hardhat@9.1.0)(@types/chai@4.3.9)(@types/mocha@9.1.0)(@types/node@18.18.7)(chai@4.3.10)(ethers@5.7.2)(hardhat-gas-reporter@1.0.9)(hardhat@2.13.1)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.2)(typescript@4.9.5) '@nomiclabs/hardhat-ethers': specifier: ^2.2.1 version: 2.2.3(ethers@5.7.2)(hardhat@2.13.1) '@nomiclabs/hardhat-etherscan': specifier: ^3.1.3 version: 3.1.7(hardhat@2.13.1) + '@openzeppelin/contracts': + specifier: <5.0.0 + version: 4.9.3 '@openzeppelin/hardhat-defender': specifier: ^1.8.2 version: 1.9.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.13.1) @@ -101,7 +110,7 @@ importers: version: 9.1.0 '@types/node': specifier: ^18.11.11 - version: 18.18.6 + version: 18.18.7 '@typescript-eslint/eslint-plugin': specifier: ^5.38.0 version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.52.0)(typescript@4.9.5) @@ -113,7 +122,7 @@ importers: version: 4.3.10 commitizen: specifier: ^4.2.5 - version: 4.3.0 + version: 4.3.0(typescript@4.9.5) copyfiles: specifier: ^2.4.1 version: 2.4.1 @@ -122,7 +131,7 @@ importers: version: 7.0.3 cz-conventional-changelog: specifier: ^3.3.0 - version: 3.3.0 + version: 3.3.0(typescript@4.9.5) dotenv: specifier: ^16.0.2 version: 16.3.1 @@ -189,9 +198,12 @@ importers: solidity-coverage: specifier: ^0.8.2 version: 0.8.5(hardhat@2.13.1) + solmate: + specifier: ^6.2.0 + version: 6.2.0 ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + version: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) typechain: specifier: ^8.3.1 version: 8.3.2(typescript@4.9.5) @@ -203,7 +215,7 @@ importers: devDependencies: '@cloudflare/workers-types': specifier: ^4.20230115.0 - version: 4.20231016.0 + version: 4.20231025.0 typescript: specifier: ^4.9.5 version: 4.9.5 @@ -220,23 +232,23 @@ importers: specifier: 0.8.11 version: 0.8.11 '@openzeppelin/defender-autotask-client': - specifier: ^1.48.0 - version: 1.49.0 + specifier: 1.50.0 + version: 1.50.0 '@openzeppelin/defender-autotask-utils': - specifier: ^1.48.0 - version: 1.49.0 + specifier: 1.50.0 + version: 1.50.0 '@openzeppelin/defender-base-client': - specifier: ^1.48.0 + specifier: 1.49.0 version: 1.49.0(debug@4.3.4) '@openzeppelin/defender-sentinel-client': - specifier: ^1.48.0 + specifier: 1.49.0 version: 1.49.0 '@openzeppelin/merkle-tree': specifier: ^1.0.2 version: 1.0.5 '@supabase/supabase-js': specifier: ^2.4.1 - version: 2.38.2 + version: 2.38.3 axios: specifier: ^1.2.6 version: 1.5.1(debug@4.3.4) @@ -252,7 +264,7 @@ importers: devDependencies: '@types/node': specifier: ^18.11.18 - version: 18.18.6 + version: 18.18.7 rimraf: specifier: ^5.0.5 version: 5.0.5 @@ -264,7 +276,7 @@ importers: version: 9.5.0(typescript@4.9.5)(webpack@5.89.0) ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + version: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) tsx: specifier: ^3.14.0 version: 3.14.0 @@ -337,13 +349,13 @@ importers: version: 1.1.0(@rainbow-me/rainbowkit@1.0.8)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(wagmi@1.3.9)(zod@3.22.4) '@emotion/react': specifier: ^11.10.5 - version: 11.11.1(@types/react@18.2.31)(react@18.2.0) + version: 11.11.1(@types/react@18.2.33)(react@18.2.0) '@emotion/styled': specifier: ^11.10.5 - version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) + version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) '@graphprotocol/client-cli': specifier: ^2.2.16 - version: 2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) + version: 2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) '@hypercerts-org/contracts': specifier: 0.8.11 version: 0.8.11 @@ -352,16 +364,16 @@ importers: version: link:../vendor/observabletreemap '@hypercerts-org/sdk': specifier: 0.8.16 - version: 0.8.16(@envelop/core@3.0.6)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3) + version: 0.8.16(@envelop/core@3.0.6)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3) '@mui/icons-material': specifier: ^5.11.9 - version: 5.14.14(@mui/material@5.14.14)(@types/react@18.2.31)(react@18.2.0) + version: 5.14.15(@mui/material@5.14.15)(@types/react@18.2.33)(react@18.2.0) '@mui/material': specifier: ^5.11.2 - version: 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) + version: 5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) '@mui/x-date-pickers': specifier: ^5.0.12 - version: 5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(@mui/system@5.14.14)(@types/react@18.2.31)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) + version: 5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.15)(@mui/system@5.14.15)(@types/react@18.2.33)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) '@next/eslint-plugin-next': specifier: ^13.4.12 version: 13.5.6 @@ -379,16 +391,16 @@ importers: version: 1.0.333(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) '@rainbow-me/rainbowkit': specifier: 1.0.8 - version: 1.0.8(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9) + version: 1.0.8(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9) '@sentry/nextjs': specifier: ^7.73.0 - version: 7.74.1(next@13.5.6)(react@18.2.0)(webpack@5.89.0) + version: 7.75.1(next@13.5.6)(react@18.2.0)(webpack@5.89.0) '@sentry/utils': specifier: ^7.73.0 - version: 7.74.1 + version: 7.75.1 '@supabase/supabase-js': specifier: ^2.1.2 - version: 2.38.2 + version: 2.38.3 '@tanstack/react-query': specifier: ^4.36.1 version: 4.36.1(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0) @@ -421,10 +433,10 @@ importers: version: 2.4.5(react@18.2.0) formik-mui: specifier: ^5.0.0-alpha.0 - version: 5.0.0-alpha.0(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3) + version: 5.0.0-alpha.0(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.15)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3) formik-mui-x-date-pickers: specifier: ^0.0.1 - version: 0.0.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(@mui/system@5.14.14)(@mui/x-date-pickers@5.0.20)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3) + version: 0.0.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.15)(@mui/system@5.14.15)(@mui/x-date-pickers@5.0.20)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3) graphql: specifier: ^16.6.0 version: 16.8.1 @@ -445,7 +457,7 @@ importers: version: 5.4.1 primereact: specifier: ^9.6.0 - version: 9.6.3(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) + version: 9.6.3(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) qs: specifier: ^6.11.0 version: 6.11.2 @@ -463,7 +475,7 @@ importers: version: 14.2.3(react@18.2.0) react-markdown: specifier: ^8.0.7 - version: 8.0.7(@types/react@18.2.31)(react@18.2.0) + version: 8.0.7(@types/react@18.2.33)(react@18.2.0) react-toastify: specifier: ^9.1.1 version: 9.1.3(react-dom@18.2.0)(react@18.2.0) @@ -478,7 +490,7 @@ importers: version: 1.5.3(typescript@5.1.6)(zod@3.22.4) wagmi: specifier: 1.3.9 - version: 1.3.9(@types/react@18.2.31)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + version: 1.3.9(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) yup: specifier: ^0.32.11 version: 0.32.11 @@ -497,7 +509,7 @@ importers: version: 14.5.1(@testing-library/dom@9.3.3) '@types/node': specifier: ^18.0.0 - version: 18.18.6 + version: 18.18.7 '@types/papaparse': specifier: ^5.3.7 version: 5.3.10 @@ -506,7 +518,7 @@ importers: version: 6.9.9 '@types/react': specifier: ^18.0.14 - version: 18.2.31 + version: 18.2.33 '@types/react-dom': specifier: ^18.0.5 version: 18.2.14 @@ -533,7 +545,7 @@ importers: version: 1.1.7 jest: specifier: ^29.5.0 - version: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) + version: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) jest-environment-jsdom: specifier: ^29.5.0 version: 29.7.0 @@ -545,7 +557,7 @@ importers: devDependencies: '@graphprotocol/graph-cli': specifier: 0.60.0 - version: 0.60.0(@types/node@18.18.6)(node-fetch@3.3.2)(typescript@4.9.5) + version: 0.60.0(@types/node@18.18.7)(node-fetch@3.3.2)(typescript@4.9.5) '@graphprotocol/graph-ts': specifier: 0.31.0 version: 0.31.0 @@ -566,37 +578,37 @@ importers: version: 5.7.0 '@graphprotocol/client-add-source-name': specifier: ^1.0.16 - version: 1.0.20(@graphql-mesh/types@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) + version: 1.0.20(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) '@graphprotocol/client-polling-live': specifier: ^2.0.0 - version: 2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@9.0.0)(graphql@16.8.1) + version: 2.0.0(@envelop/core@4.0.3)(@graphql-tools/merge@9.0.0)(graphql@16.8.1) '@graphql-mesh/cache-localforage': specifier: ^0.95.7 - version: 0.95.7(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2) + version: 0.95.8(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/cross-helpers': specifier: ^0.4.1 version: 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) '@graphql-mesh/graphql': specifier: ^0.95.7 - version: 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2) + version: 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2) '@graphql-mesh/http': specifier: ^0.96.13 - version: 0.96.13(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/runtime@0.96.12)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2) + version: 0.96.14(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/runtime@0.96.13)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/merger-bare': specifier: ^0.95.7 - version: 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + version: 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/runtime': specifier: ^0.96.12 - version: 0.96.12(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + version: 0.96.13(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/store': specifier: ^0.95.7 - version: 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + version: 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/types': specifier: ^0.95.7 - version: 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + version: 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/utils': specifier: ^0.95.7 - version: 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + version: 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.8.1) @@ -608,7 +620,7 @@ importers: version: 1.0.5 '@whatwg-node/fetch': specifier: ^0.9.13 - version: 0.9.13 + version: 0.9.14 ajv: specifier: ^8.11.2 version: 8.12.0 @@ -629,7 +641,7 @@ importers: version: 0.17.0(uint8arraylist@2.4.3) jest: specifier: ^29.3.1 - version: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) + version: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) loglevel: specifier: ^1.8.1 version: 1.8.1 @@ -657,7 +669,7 @@ importers: version: 8.2.0 '@graphprotocol/client-cli': specifier: ^3.0.0 - version: 3.0.0(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) + version: 3.0.0(@babel/core@7.23.2)(@envelop/core@4.0.3)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) '@jest/globals': specifier: ^29.7.0 version: 29.7.0 @@ -684,7 +696,7 @@ importers: version: 9.1.0 '@types/node': specifier: ^18.11.17 - version: 18.18.6 + version: 18.18.7 '@types/sinon': specifier: ^10.0.15 version: 10.0.20 @@ -753,7 +765,7 @@ importers: version: 10.0.0(mocha@10.2.0) ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + version: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) tslib: specifier: ^2.5.0 version: 2.6.2 @@ -797,7 +809,7 @@ packages: resolution: {integrity: sha512-rU4G75TEOTIPlkeDnPEVwx/VmMMFta42kY2SMmVobRkrtNLnxtU08Yhriu6tSBc9oO0wXdfNNeuLnNnEnL7w/A==} dependencies: '@achingbrain/ssdp': 4.0.6 - '@libp2p/logger': 3.0.3 + '@libp2p/logger': 3.0.4 default-gateway: 7.2.2 err-code: 3.0.1 it-first: 3.0.3 @@ -988,8 +1000,8 @@ packages: optional: true dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) - '@wry/context': 0.7.3 - '@wry/equality': 0.5.6 + '@wry/context': 0.7.4 + '@wry/equality': 0.5.7 '@wry/trie': 0.4.3 graphql: 16.8.1 graphql-tag: 2.12.6(graphql@16.8.1) @@ -2623,10 +2635,10 @@ packages: wagmi: '>=1.0.0 && <=2.0.0' dependencies: '@metamask/providers': 11.1.2 - '@rainbow-me/rainbowkit': 1.0.8(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9) - '@wagmi/connectors': 2.6.6(@wagmi/chains@1.6.0)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + '@rainbow-me/rainbowkit': 1.0.8(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9) + '@wagmi/connectors': 2.7.0(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) - wagmi: 1.3.9(@types/react@18.2.31)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + wagmi: 1.3.9(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) transitivePeerDependencies: - '@react-native-async-storage/async-storage' - '@wagmi/chains' @@ -2640,6 +2652,19 @@ packages: - zod dev: false + /@chainlink/contracts@0.8.0(ethers@5.7.2): + resolution: {integrity: sha512-nUv1Uxw5Mn92wgLs2bgPYmo8hpdQ3s9jB/lcbdU0LmNOVu0hbfmouVnqwRLa28Ll50q6GczUA+eO0ikNIKLZsA==} + dependencies: + '@eth-optimism/contracts': 0.5.40(ethers@5.7.2) + '@openzeppelin/contracts': 4.3.3 + '@openzeppelin/contracts-upgradeable-4.7.3': /@openzeppelin/contracts-upgradeable@4.7.3 + '@openzeppelin/contracts-v0.7': /@openzeppelin/contracts@3.4.2 + transitivePeerDependencies: + - bufferutil + - ethers + - utf-8-validate + dev: true + /@chainsafe/as-sha256@0.3.1: resolution: {integrity: sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==} @@ -2740,8 +2765,8 @@ packages: mime: 3.0.0 dev: true - /@cloudflare/workers-types@4.20231016.0: - resolution: {integrity: sha512-eGB0cRVyoJpeyGJx2re5sbd9R316a61sY73xwnqm4cwGpb+OxCK2gc651RxGiN7H4w6LY1RpysUgeGLmj5B3+g==} + /@cloudflare/workers-types@4.20231025.0: + resolution: {integrity: sha512-TkcZkntUTOcvJ4vgmwpNfLTclpMbmbClZCe62B25/VTukmyv91joRa4eKzSjzCZUXTbFHNmVdOpmGaaJU2U3+A==} dev: true /@coinbase/wallet-sdk@3.7.2: @@ -2813,12 +2838,12 @@ packages: ajv: 8.12.0 dev: true - /@commitlint/config-validator@18.0.0: - resolution: {integrity: sha512-PlXy5QZzQeMgQM7jb0odIhxsI6GWcbGgfy+Hkz5ap31KES/oJgtEvgD8pjg0Z9Ri296bT6zK3ts6brS0MAcMgg==} + /@commitlint/config-validator@18.1.0: + resolution: {integrity: sha512-kbHkIuItXn93o2NmTdwi5Mk1ujyuSIysRE/XHtrcps/27GuUKEIqBJp6TdJ4Sq+ze59RlzYSHMKuDKZbfg9+uQ==} engines: {node: '>=v18'} requiresBuild: true dependencies: - '@commitlint/types': 18.0.0 + '@commitlint/types': 18.1.0 ajv: 8.12.0 dev: true optional: true @@ -2840,8 +2865,8 @@ packages: engines: {node: '>=v14'} dev: true - /@commitlint/execute-rule@18.0.0: - resolution: {integrity: sha512-eNUSaHajb+g3sgZeIrfc6cXNnKIkYN2SXtDVXuiE+hOa055T0bLdZK29gSd945JCztxPVwdOkPLDeLg3NfDubg==} + /@commitlint/execute-rule@18.1.0: + resolution: {integrity: sha512-w3Vt4K+O7+nSr9/gFSEfZ1exKUOPSlJaRpnk7Y+XowEhvwT7AIk1HNANH+gETf0zGZ020+hfiMW/Ome+SNCUsg==} engines: {node: '>=v18'} requiresBuild: true dev: true @@ -2896,28 +2921,25 @@ packages: - '@swc/wasm' dev: true - /@commitlint/load@18.0.0: - resolution: {integrity: sha512-ocvMSkzNZCJ4yV673xjd4Y7sFVG/mg7S6yvL5ioM0OIG2XTbcCdzpmq+BeJcIwsRYU9g/b688yh7RDzGlbai6w==} + /@commitlint/load@18.2.0(typescript@4.9.5): + resolution: {integrity: sha512-xjX3d3CRlOALwImhOsmLYZh14/+gW/KxsY7+bPKrzmGuFailf9K7ckhB071oYZVJdACnpY4hDYiosFyOC+MpAA==} engines: {node: '>=v18'} requiresBuild: true dependencies: - '@commitlint/config-validator': 18.0.0 - '@commitlint/execute-rule': 18.0.0 - '@commitlint/resolve-extends': 18.0.0 - '@commitlint/types': 18.0.0 - '@types/node': 18.18.6 + '@commitlint/config-validator': 18.1.0 + '@commitlint/execute-rule': 18.1.0 + '@commitlint/resolve-extends': 18.1.0 + '@commitlint/types': 18.1.0 + '@types/node': 18.18.7 chalk: 4.1.2 - cosmiconfig: 8.3.6(typescript@5.2.2) - cosmiconfig-typescript-loader: 4.4.0(@types/node@18.18.6)(cosmiconfig@8.3.6)(ts-node@10.9.1)(typescript@5.2.2) + cosmiconfig: 8.3.6(typescript@4.9.5) + cosmiconfig-typescript-loader: 5.0.0(@types/node@18.18.7)(cosmiconfig@8.3.6)(typescript@4.9.5) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 resolve-from: 5.0.0 - ts-node: 10.9.1(@types/node@18.18.6)(typescript@5.2.2) - typescript: 5.2.2 transitivePeerDependencies: - - '@swc/core' - - '@swc/wasm' + - typescript dev: true optional: true @@ -2958,13 +2980,13 @@ packages: resolve-global: 1.0.0 dev: true - /@commitlint/resolve-extends@18.0.0: - resolution: {integrity: sha512-MD9+6GSiWvqgdJtfos+1gqz+zmy2vV7TbUVz2ETZzpfECgmUZSZSYzyivivBAQK6feS71KxmMLL8+YFF9+FFRQ==} + /@commitlint/resolve-extends@18.1.0: + resolution: {integrity: sha512-3mZpzOEJkELt7BbaZp6+bofJyxViyObebagFn0A7IHaLARhPkWTivXdjvZHS12nAORftv88Yhbh8eCPKfSvB7g==} engines: {node: '>=v18'} requiresBuild: true dependencies: - '@commitlint/config-validator': 18.0.0 - '@commitlint/types': 18.0.0 + '@commitlint/config-validator': 18.1.0 + '@commitlint/types': 18.1.0 import-fresh: 3.3.0 lodash.mergewith: 4.6.2 resolve-from: 5.0.0 @@ -3002,8 +3024,8 @@ packages: chalk: 4.1.2 dev: true - /@commitlint/types@18.0.0: - resolution: {integrity: sha512-FDzAdSm7kIir0NW0bZLENdrEgf/9Ihs1AAqE9DK9R+dRFby4ookkxPMaz7elZmG+e5rBl7hGrWJzJINqG9cDDg==} + /@commitlint/types@18.1.0: + resolution: {integrity: sha512-65vGxZmbs+2OVwEItxhp3Ul7X2m2LyLfifYI/NdPwRqblmuES2w2aIRhIjb7cwUIBHHSTT8WXj4ixVHQibmvLQ==} engines: {node: '>=v18'} requiresBuild: true dependencies: @@ -3017,8 +3039,8 @@ packages: dependencies: '@jridgewell/trace-mapping': 0.3.9 - /@cypress/code-coverage@3.12.5(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(cypress@12.17.4)(webpack@5.89.0): - resolution: {integrity: sha512-0hczq2kgzkh/fBLm74rHcDRX//W3bhJJw/aPWu57/pPaRp5c+LcatWuv8ZtIWNXit2kBClueOrVj0I20Arh80A==} + /@cypress/code-coverage@3.12.6(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(cypress@12.17.4)(webpack@5.89.0): + resolution: {integrity: sha512-QeOB54dkxee8LKdbK9NqMinlMtzy60K2DexSvx4XZdrU52gut9Ukc7sUvRe44gK1yJFYno977Kx9miNIeYWVtA==} peerDependencies: '@babel/core': ^7.0.1 '@babel/preset-env': ^7.0.0 @@ -3284,7 +3306,7 @@ packages: react-router: 5.3.4(react@18.2.0) react-router-config: 5.1.1(react-router@5.3.4)(react@18.2.0) react-router-dom: 5.3.4(react@18.2.0) - rtl-detect: 1.0.4 + rtl-detect: 1.1.2 semver: 7.5.4 serve-handler: 6.1.5 shelljs: 0.8.5 @@ -3393,7 +3415,7 @@ packages: '@docusaurus/react-loadable': 5.5.2(react@18.2.0) '@docusaurus/types': 2.4.3(react-dom@18.2.0)(react@18.2.0) '@types/history': 4.7.11 - '@types/react': 18.2.31 + '@types/react': 18.2.33 '@types/react-router-config': 5.0.9 '@types/react-router-dom': 5.3.3 react: 18.2.0 @@ -3740,7 +3762,7 @@ packages: peerDependencies: react: '*' dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 prop-types: 15.8.1 react: 18.2.0 @@ -3811,7 +3833,7 @@ packages: '@docusaurus/utils': 2.4.3(@docusaurus/types@2.4.3) '@docusaurus/utils-common': 2.4.3(@docusaurus/types@2.4.3) '@types/history': 4.7.11 - '@types/react': 18.2.31 + '@types/react': 18.2.33 '@types/react-router-config': 5.0.9 clsx: 1.2.1 parse-numeric-range: 1.3.0 @@ -3891,7 +3913,7 @@ packages: '@docusaurus/utils': 2.4.3(@docusaurus/types@2.4.3) '@docusaurus/utils-validation': 2.4.3(@docusaurus/types@2.4.3) algoliasearch: 4.20.0 - algoliasearch-helper: 3.14.2(algoliasearch@4.20.0) + algoliasearch-helper: 3.15.0(algoliasearch@4.20.0) clsx: 1.2.1 eta: 2.2.0 fs-extra: 10.1.0 @@ -3937,7 +3959,7 @@ packages: react-dom: ^16.8.4 || ^17.0.0 dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.31 + '@types/react': 18.2.33 commander: 5.1.0 joi: 17.11.0 react: 18.2.0 @@ -4068,7 +4090,7 @@ packages: resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} dev: false - /@emotion/react@11.11.1(@types/react@18.2.31)(react@18.2.0): + /@emotion/react@11.11.1(@types/react@18.2.33)(react@18.2.0): resolution: {integrity: sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==} peerDependencies: '@types/react': '*' @@ -4084,7 +4106,7 @@ packages: '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) '@emotion/utils': 1.2.1 '@emotion/weak-memoize': 0.3.1 - '@types/react': 18.2.31 + '@types/react': 18.2.33 hoist-non-react-statics: 3.3.2 react: 18.2.0 dev: false @@ -4103,7 +4125,7 @@ packages: resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} dev: false - /@emotion/styled@11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0): + /@emotion/styled@11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0): resolution: {integrity: sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==} peerDependencies: '@emotion/react': ^11.0.0-rc.0 @@ -4116,11 +4138,11 @@ packages: '@babel/runtime': 7.23.2 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.1 - '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) + '@emotion/react': 11.11.1(@types/react@18.2.33)(react@18.2.0) '@emotion/serialize': 1.1.2 '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) '@emotion/utils': 1.2.1 - '@types/react': 18.2.31 + '@types/react': 18.2.33 react: 18.2.0 dev: false @@ -4166,6 +4188,13 @@ packages: '@envelop/types': 3.0.2 tslib: 2.6.2 + /@envelop/core@4.0.3: + resolution: {integrity: sha512-O0Vz8E0TObT6ijAob8jYFVJavcGywKThM3UAsxUIBBVPYZTMiqI9lo2gmAnbMUnrDcAYkUTZEW9FDYPRdF5l6g==} + engines: {node: '>=16.0.0'} + dependencies: + '@envelop/types': 4.0.1 + tslib: 2.6.2 + /@envelop/core@5.0.0: resolution: {integrity: sha512-aJdnH/ptv+cvwfvciCBe7TSvccBwo9g0S5f6u35TBVzRVqIGkK03lFlIL+x1cnfZgN9EfR2b1PH2galrT1CdCQ==} engines: {node: '>=18.0.0'} @@ -4217,6 +4246,12 @@ packages: dependencies: tslib: 2.6.2 + /@envelop/types@4.0.1: + resolution: {integrity: sha512-ULo27/doEsP7uUhm2iTnElx13qTO6I5FKvmLoX41cpfuw8x6e0NUFknoqhEsLzAbgz8xVS5mjwcxGCXh4lDYzg==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.2 + /@envelop/types@5.0.0: resolution: {integrity: sha512-IPjmgSc4KpQRlO4qbEDnBEixvtb06WDmjKfi/7fkZaryh5HuOmTtixe1EupQI5XfXO8joc3d27uUZ0QdC++euA==} engines: {node: '>=18.0.0'} @@ -5065,8 +5100,8 @@ packages: eslint: 8.52.0 eslint-visitor-keys: 3.4.3 - /@eslint-community/regexpp@4.9.1: - resolution: {integrity: sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==} + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} /@eslint/eslintrc@1.4.1: @@ -5106,6 +5141,44 @@ packages: resolution: {integrity: sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@eth-optimism/contracts@0.5.40(ethers@5.7.2): + resolution: {integrity: sha512-MrzV0nvsymfO/fursTB7m/KunkPsCndltVgfdHaT1Aj5Vi6R/doKIGGkOofHX+8B6VMZpuZosKCMQ5lQuqjt8w==} + peerDependencies: + ethers: ^5.7.2 + dependencies: + '@eth-optimism/core-utils': 0.12.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@eth-optimism/core-utils@0.12.0: + resolution: {integrity: sha512-qW+7LZYCz7i8dRa7SRlUKIo1VBU8lvN0HeXCxJR+z+xtMzMQpPds20XJNCMclszxYQHkXY00fOT6GvFw9ZL6nw==} + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@ethersproject/rlp': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/web': 5.7.1 + bufio: 1.2.1 + chai: 4.3.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + /@ethereum-attestation-service/eas-contracts@0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(ts-node@10.9.1)(typescript@4.9.5): resolution: {integrity: sha512-ly1N/jLbXJjACDL7dnMSkzViBxxuVc+aMZ3EB1kpFxeMWrXkb7nN6w9gxGTH+m3gJztaKvyMsyr/13pA0OYq6Q==} dependencies: @@ -5785,7 +5858,7 @@ packages: tslib: 2.6.2 dev: false - /@graphprotocol/client-add-source-name@1.0.20(@graphql-mesh/types@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): + /@graphprotocol/client-add-source-name@1.0.20(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): resolution: {integrity: sha512-JJ++BVg4fhNCbLej105uHpabZesLsCSo9p43ZKSTT1VUdbuZtarzyIHC3uUmbvCfWQMVTCJEBZGx4l41oooOiw==} peerDependencies: '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 @@ -5794,7 +5867,7 @@ packages: '@graphql-tools/wrap': ^9.4.2 graphql: ^16.6.0 dependencies: - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) @@ -5803,7 +5876,7 @@ packages: tslib: 2.6.2 dev: false - /@graphprotocol/client-add-source-name@2.0.0(@graphql-mesh/types@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): + /@graphprotocol/client-add-source-name@2.0.0(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): resolution: {integrity: sha512-3vX8mVPIEJFwAoRhjTPd9IjQrBuE+Gv+JB7IEf8/9222qiU9EzHVFUekKxVtcxQXD40CfageS41CxOreWQ1enA==} engines: {node: '>=16.0.0'} peerDependencies: @@ -5813,7 +5886,7 @@ packages: '@graphql-tools/wrap': ^9.4.2 || ^10.0.0 graphql: ^16.6.0 dependencies: - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) @@ -5840,7 +5913,7 @@ packages: tslib: 2.6.2 dev: false - /@graphprotocol/client-auto-pagination@2.0.0(@graphql-mesh/types@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): + /@graphprotocol/client-auto-pagination@2.0.0(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): resolution: {integrity: sha512-TouHgs6rQLpZSgnMoPdes8/ZTtMMEoxWeUUCkfho/xfSi49prb5DcsI83pykln0OEAUnNPnaX0MhP+xA5LtFSg==} engines: {node: '>=16.0.0'} peerDependencies: @@ -5850,7 +5923,7 @@ packages: '@graphql-tools/wrap': ^9.4.2 || ^10.0.0 graphql: ^16.6.0 dependencies: - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) @@ -5875,7 +5948,7 @@ packages: - '@graphql-mesh/utils' dev: false - /@graphprotocol/client-auto-type-merging@2.0.0(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1): + /@graphprotocol/client-auto-type-merging@2.0.0(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1): resolution: {integrity: sha512-mxqXKHK2lO+k4r02Q44n3qhd5dufo+SSDduD8zGUDBsYcRQAtQD9PwmXRHyUoB9nw4A+NC+CtVh+76fueXCG1w==} engines: {node: '>=16.0.0'} peerDependencies: @@ -5883,8 +5956,8 @@ packages: '@graphql-tools/delegate': ^9.0.32 || ^10.0.0 graphql: ^16.6.0 dependencies: - '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) graphql: 16.8.1 tslib: 2.6.2 @@ -5917,7 +5990,7 @@ packages: tslib: 2.6.2 dev: true - /@graphprotocol/client-cli@2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): + /@graphprotocol/client-cli@2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): resolution: {integrity: sha512-PIi8rFibYZVup+0jb08399RmbGF1ZrqUe6RXzLtKZBT57OWIMWwsFvdJyUAdr8Y8f0rrMn6A+Oy4nP1lf3hc1g==} hasBin: true peerDependencies: @@ -5928,8 +6001,8 @@ packages: '@graphprotocol/client-auto-type-merging': 1.0.25(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-block-tracking': 1.0.14(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-polling-live': 1.1.1(@envelop/core@3.0.6)(@graphql-tools/merge@8.4.2)(graphql@16.8.1) - '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) - '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) + '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2) graphql: 16.8.1 tslib: 2.6.2 transitivePeerDependencies: @@ -5955,20 +6028,20 @@ packages: - utf-8-validate dev: false - /@graphprotocol/client-cli@3.0.0(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): + /@graphprotocol/client-cli@3.0.0(@babel/core@7.23.2)(@envelop/core@4.0.3)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): resolution: {integrity: sha512-hTISbOzKavlDifBNsR6JqQMfdYwY7++hflPy+c3WHRrZ4OMoxFmW7ZuvaP6LvgKdJV77O8w9dnT/uxeHs6a90g==} engines: {node: '>=16.0.0'} hasBin: true peerDependencies: graphql: ^16.6.0 dependencies: - '@graphprotocol/client-add-source-name': 2.0.0(@graphql-mesh/types@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) - '@graphprotocol/client-auto-pagination': 2.0.0(@graphql-mesh/types@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) - '@graphprotocol/client-auto-type-merging': 2.0.0(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) + '@graphprotocol/client-add-source-name': 2.0.0(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) + '@graphprotocol/client-auto-pagination': 2.0.0(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) + '@graphprotocol/client-auto-type-merging': 2.0.0(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-block-tracking': 2.0.0(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) - '@graphprotocol/client-polling-live': 2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@9.0.0)(graphql@16.8.1) - '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) - '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(tslib@2.6.2) + '@graphprotocol/client-polling-live': 2.0.0(@envelop/core@4.0.3)(@graphql-tools/merge@9.0.0)(graphql@16.8.1) + '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) + '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2) graphql: 16.8.1 tslib: 2.6.2 transitivePeerDependencies: @@ -6023,7 +6096,7 @@ packages: tslib: 2.6.2 dev: false - /@graphprotocol/client-polling-live@2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@9.0.0)(graphql@16.8.1): + /@graphprotocol/client-polling-live@2.0.0(@envelop/core@4.0.3)(@graphql-tools/merge@9.0.0)(graphql@16.8.1): resolution: {integrity: sha512-JQ0sKiFCX+ErR0fynBNUg/WDiVaaEndlS12fkgrFZrQA2vVpSyow9pW0nKMGVZJa4cN+VDskgwqK5BWXMvdeRA==} engines: {node: '>=16.0.0'} peerDependencies: @@ -6031,21 +6104,21 @@ packages: '@graphql-tools/merge': ^8.3.14 || ^9.0.0 graphql: ^16.6.0 dependencies: - '@envelop/core': 3.0.6 + '@envelop/core': 4.0.3 '@graphql-tools/merge': 9.0.0(graphql@16.8.1) '@repeaterjs/repeater': 3.0.4 graphql: 16.8.1 tslib: 2.6.2 - /@graphprotocol/graph-cli@0.60.0(@types/node@18.18.6)(node-fetch@3.3.2)(typescript@4.9.5): + /@graphprotocol/graph-cli@0.60.0(@types/node@18.18.7)(node-fetch@3.3.2)(typescript@4.9.5): resolution: {integrity: sha512-8tGaQJ0EzAPtkDXCAijFGoVdJXM+pKFlGxjiU31TdG5bS4cIUoSB6yWojVsFFod0yETAwf+giel/0/8sudYsDw==} engines: {node: '>=14'} hasBin: true dependencies: '@float-capital/float-subgraph-uncrashable': 0.0.0-internal-testing.5 - '@oclif/core': 2.8.6(@types/node@18.18.6)(typescript@4.9.5) - '@oclif/plugin-autocomplete': 2.3.10(@types/node@18.18.6)(typescript@4.9.5) - '@oclif/plugin-not-found': 2.4.3(@types/node@18.18.6)(typescript@4.9.5) + '@oclif/core': 2.8.6(@types/node@18.18.7)(typescript@4.9.5) + '@oclif/plugin-autocomplete': 2.3.10(@types/node@18.18.7)(typescript@4.9.5) + '@oclif/plugin-not-found': 2.4.3(@types/node@18.18.7)(typescript@4.9.5) '@whatwg-node/fetch': 0.8.8 assemblyscript: 0.19.23 binary-install-raw: 0.0.13(debug@4.3.4) @@ -6300,23 +6373,23 @@ packages: localforage: 1.10.0 tslib: 2.6.2 - /@graphql-mesh/cache-localforage@0.95.7(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-/e9sFn0kgSxGE6O/GWfdGnFMOIfk1Y+IZwRqPIofHmIPdyC5cZ/gnkN6oRQv7nnx+c9hzQQ5OnxiOGdOKwb1cg==} + /@graphql-mesh/cache-localforage@0.95.8(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-PgCTHh1dLwjmusWEWAMQkglL7gR8VyyT9pzTcYBVFhGYNXysepCrl85QtaqtEMnR/YijgpCWaKGIYK+bosQZsg==} engines: {node: '>=16.0.0'} peerDependencies: - '@graphql-mesh/types': ^0.95.7 - '@graphql-mesh/utils': ^0.95.7 + '@graphql-mesh/types': ^0.95.8 + '@graphql-mesh/utils': ^0.95.8 graphql: ^16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) graphql: 16.8.1 localforage: 1.10.0 tslib: 2.6.2 dev: false - /@graphql-mesh/cli@0.82.35(@babel/core@7.23.2)(@types/node@18.18.6)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): + /@graphql-mesh/cli@0.82.35(@babel/core@7.23.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): resolution: {integrity: sha512-5IuXpk+Zpg05u6qNPX19VzC5/HCiLdDRF6EPZ3ze57FIRgGA3YsB1CUGga6Ky3inalURYwx0kWqmdjbdKZYx1w==} hasBin: true peerDependencies: @@ -6350,7 +6423,7 @@ packages: open: 7.4.2 pascal-case: 3.1.2 rimraf: 5.0.5 - ts-node: 10.9.1(@types/node@18.18.6)(typescript@5.1.6) + ts-node: 10.9.1(@types/node@18.18.7)(typescript@5.1.6) tsconfig-paths: 4.2.0 tslib: 2.6.2 typescript: 5.1.6 @@ -6430,7 +6503,7 @@ packages: graphql: 16.8.1 path-browserify: 1.0.1 - /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(tslib@2.6.2): + /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-1G2/1jkl1VPWhsZsUBwFQI5d9OxxEc+CMxy5ef0qI2WEXqIocOxMhEY53cc+tCSbuXR99rxos+KD/8Z6ZasaOQ==} peerDependencies: '@graphql-mesh/cross-helpers': ^0.3.4 @@ -6447,7 +6520,7 @@ packages: '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) - '@graphql-tools/url-loader': 7.17.18(@types/node@18.18.6)(graphql@16.8.1) + '@graphql-tools/url-loader': 7.17.18(@types/node@18.18.7)(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) graphql: 16.8.1 @@ -6460,7 +6533,7 @@ packages: - utf-8-validate dev: false - /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(tslib@2.6.2): + /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-1G2/1jkl1VPWhsZsUBwFQI5d9OxxEc+CMxy5ef0qI2WEXqIocOxMhEY53cc+tCSbuXR99rxos+KD/8Z6ZasaOQ==} peerDependencies: '@graphql-mesh/cross-helpers': ^0.3.4 @@ -6472,12 +6545,12 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) - '@graphql-mesh/store': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) - '@graphql-tools/url-loader': 7.17.18(@types/node@18.18.6)(graphql@16.8.1) + '@graphql-tools/url-loader': 7.17.18(@types/node@18.18.7)(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) graphql: 16.8.1 @@ -6490,26 +6563,26 @@ packages: - utf-8-validate dev: true - /@graphql-mesh/graphql@0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2): - resolution: {integrity: sha512-Fjf1Ti2HYOEP+dFLVnVxafD/Z4Ev+sR6BUbx3E7Mw8r/XGY28KmCA/QftBOB6BRNKMLe5w7RsgjCrO+Qp0klNg==} + /@graphql-mesh/graphql@0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2): + resolution: {integrity: sha512-mEbz2XYSgRTdNidUBWB7FT3QzLliJwxJIoqipSbZNputJqSbUZZ6QD/oI1IrdPXqVl/ELE2CuLiogkOSO24C1Q==} engines: {node: '>=16.0.0'} peerDependencies: '@graphql-mesh/cross-helpers': ^0.4.1 - '@graphql-mesh/store': ^0.95.7 - '@graphql-mesh/types': ^0.95.7 - '@graphql-mesh/utils': ^0.95.7 + '@graphql-mesh/store': ^0.95.8 + '@graphql-mesh/types': ^0.95.8 + '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 graphql: ^16.6.0 tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) - '@graphql-mesh/store': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/string-interpolation': 0.5.2(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/string-interpolation': 0.5.3(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) - '@graphql-tools/federation': 1.1.10(@types/node@18.18.6)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) - '@graphql-tools/url-loader': 8.0.0(@types/node@18.18.6)(graphql@16.8.1) + '@graphql-tools/federation': 1.1.10(@types/node@18.18.7)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + '@graphql-tools/url-loader': 8.0.0(@types/node@18.18.7)(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) graphql: 16.8.1 lodash.get: 4.4.2 @@ -6544,22 +6617,22 @@ packages: graphql-yoga: 3.9.1(graphql@16.8.1) tslib: 2.6.2 - /@graphql-mesh/http@0.96.13(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/runtime@0.96.12)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-WNiOJkwuRKoVCv/+9bp8/PFdclyTN0COIwSXjzIf36QICPtUXhokPLkXKhR7Xdtk175aIIpUHYRRwlgQw3BC1w==} + /@graphql-mesh/http@0.96.14(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/runtime@0.96.13)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-38Mxw2K2RABBBO0IiXKZDu2o+jlM4vcUSEg+9h2Dz67oOJZHpKeId6z1PFb7uYMzAs29yoMcqXIEnews+HVhrQ==} engines: {node: '>=16.0.0'} peerDependencies: '@graphql-mesh/cross-helpers': ^0.4.1 - '@graphql-mesh/runtime': ^0.96.12 - '@graphql-mesh/types': ^0.95.7 - '@graphql-mesh/utils': ^0.95.7 + '@graphql-mesh/runtime': ^0.96.13 + '@graphql-mesh/types': ^0.95.8 + '@graphql-mesh/utils': ^0.95.8 graphql: ^16.6.0 tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) - '@graphql-mesh/runtime': 0.96.12(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@whatwg-node/server': 0.9.15 + '@graphql-mesh/runtime': 0.96.13(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@whatwg-node/server': 0.9.16 graphql: 16.8.1 graphql-yoga: 5.0.0(graphql@16.8.1) tslib: 2.6.2 @@ -6584,19 +6657,19 @@ packages: transitivePeerDependencies: - '@graphql-mesh/store' - /@graphql-mesh/merger-bare@0.95.7(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-QNLm5otrzcpClR8Puks4Md7Mh6AON+EWK+l3NBKvEkiOINFcnDRFv4FrSEXSfrAv/vHrSBbxAEXGUWHjjbQ8Kw==} + /@graphql-mesh/merger-bare@0.95.8(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-E5R8Sv5Dkp+eswYKEDHgu8puwSeolPX1j9IHwBVe1npRRCXc3CjMsQJ9+kcTln453vbSBcM1a3fQspIaKA1Tcg==} engines: {node: '>=16.0.0'} peerDependencies: - '@graphql-mesh/types': ^0.95.7 - '@graphql-mesh/utils': ^0.95.7 + '@graphql-mesh/types': ^0.95.8 + '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 graphql: ^16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/merger-stitching': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/merger-stitching': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/schema': 10.0.0(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) graphql: 16.8.1 @@ -6626,20 +6699,20 @@ packages: graphql: 16.8.1 tslib: 2.6.2 - /@graphql-mesh/merger-stitching@0.95.7(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-0fooZHNseNrrVIm+OPfy7NdN1f/Cq6yhpW7d9lXjB8kPWjRGaX6gBUxpfCsRqSrfBDP1VwusZ6Z9EmW+84AtCQ==} + /@graphql-mesh/merger-stitching@0.95.8(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-eAukU8AsjK8jIT3vFhalGoERh98xZgzKkTCQL7w2wPpFXveSDMn+9fVvCJ1EBKTsLa7SkNXqzAFkfYp21hW0ng==} engines: {node: '>=16.0.0'} peerDependencies: - '@graphql-mesh/store': ^0.95.7 - '@graphql-mesh/types': ^0.95.7 - '@graphql-mesh/utils': ^0.95.7 + '@graphql-mesh/store': ^0.95.8 + '@graphql-mesh/types': ^0.95.8 + '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 graphql: ^16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/store': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/schema': 10.0.0(graphql@16.8.1) '@graphql-tools/stitch': 9.0.3(graphql@16.8.1) @@ -6673,13 +6746,13 @@ packages: graphql: 16.8.1 tslib: 2.6.2 - /@graphql-mesh/runtime@0.96.12(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-b3a/XjbTtS8gF30wu35M4pA2KyUYkYcWlnYNGXWOObtdEtEXjj+GkX//yO2XzTGI/sGWKElAAKIv4asPsye4jA==} + /@graphql-mesh/runtime@0.96.13(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-eZIW/gdEVLvCLEEae8e3lny7d89CFfDyu0Z0xu4yVEdYeVpG9Ki2mDYFHztusIIkZikecvdsoM9MZX6LYcPOkg==} engines: {node: '>=16.0.0'} peerDependencies: '@graphql-mesh/cross-helpers': ^0.4.1 - '@graphql-mesh/types': ^0.95.7 - '@graphql-mesh/utils': ^0.95.7 + '@graphql-mesh/types': ^0.95.8 + '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 graphql: ^16.6.0 tslib: ^2.4.0 @@ -6688,7 +6761,7 @@ packages: '@envelop/extended-validation': 4.0.0(@envelop/core@5.0.0)(graphql@16.8.1) '@envelop/graphql-jit': 8.0.1(@envelop/core@5.0.0)(graphql@16.8.1) '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) - '@graphql-mesh/string-interpolation': 0.5.2(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/string-interpolation': 0.5.3(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/batch-delegate': 9.0.0(graphql@16.8.1) @@ -6696,19 +6769,19 @@ packages: '@graphql-tools/executor': 1.2.0(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 10.0.1(graphql@16.8.1) - '@whatwg-node/fetch': 0.9.13 + '@whatwg-node/fetch': 0.9.14 graphql: 16.8.1 graphql-jit: 0.8.2(graphql@16.8.1) tslib: 2.6.2 dev: false - /@graphql-mesh/runtime@0.96.12(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-b3a/XjbTtS8gF30wu35M4pA2KyUYkYcWlnYNGXWOObtdEtEXjj+GkX//yO2XzTGI/sGWKElAAKIv4asPsye4jA==} + /@graphql-mesh/runtime@0.96.13(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-eZIW/gdEVLvCLEEae8e3lny7d89CFfDyu0Z0xu4yVEdYeVpG9Ki2mDYFHztusIIkZikecvdsoM9MZX6LYcPOkg==} engines: {node: '>=16.0.0'} peerDependencies: '@graphql-mesh/cross-helpers': ^0.4.1 - '@graphql-mesh/types': ^0.95.7 - '@graphql-mesh/utils': ^0.95.7 + '@graphql-mesh/types': ^0.95.8 + '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 graphql: ^16.6.0 tslib: ^2.4.0 @@ -6717,15 +6790,15 @@ packages: '@envelop/extended-validation': 4.0.0(@envelop/core@5.0.0)(graphql@16.8.1) '@envelop/graphql-jit': 8.0.1(@envelop/core@5.0.0)(graphql@16.8.1) '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) - '@graphql-mesh/string-interpolation': 0.5.2(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/string-interpolation': 0.5.3(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/batch-delegate': 9.0.0(graphql@16.8.1) '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/executor': 1.2.0(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 10.0.1(graphql@16.8.1) - '@whatwg-node/fetch': 0.9.13 + '@whatwg-node/fetch': 0.9.14 graphql: 16.8.1 graphql-jit: 0.8.2(graphql@16.8.1) tslib: 2.6.2 @@ -6749,21 +6822,21 @@ packages: graphql: 16.8.1 tslib: 2.6.2 - /@graphql-mesh/store@0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-4T5MnkdV70gPzM3Hj+Er2Qg4FTzePzbzGdHdWRSbW++4K+05Hbe1gKPix2f3s3BGkAO4Et5XkkdILL5QynhQFw==} + /@graphql-mesh/store@0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-29lpMcvqS1DM9alUOCyj6he2V7ZzG/DZxkerRefT8Mo5FexwJZI3LeI0YHNSY9Cq0x8KzRoH1TWcTTN/1PDRRw==} engines: {node: '>=16.0.0'} peerDependencies: '@graphql-mesh/cross-helpers': ^0.4.1 - '@graphql-mesh/types': ^0.95.7 - '@graphql-mesh/utils': ^0.95.7 + '@graphql-mesh/types': ^0.95.8 + '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 graphql: ^16.6.0 tslib: ^2.4.0 dependencies: '@graphql-inspector/core': 5.0.1(graphql@16.8.1) '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) graphql: 16.8.1 tslib: 2.6.2 @@ -6780,8 +6853,8 @@ packages: lodash.get: 4.4.2 tslib: 2.6.2 - /@graphql-mesh/string-interpolation@0.5.2(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-TkSAJ9pj1zesQyDlHrEUevVGOc1s/z9IQC0AONcpMHAunb8uYGO4Yryl8JIRIvDl5DlexHt3z8kLDNCInRGWNQ==} + /@graphql-mesh/string-interpolation@0.5.3(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-/R4kj3M1uqUie/7RZ58zgRrT8RBrDsCCR6ii00s62DbLsl+jZYOZFyTqHGsFbP7L7aHnl0fo1dwhEJIs+rjCLg==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^16.6.0 @@ -6809,7 +6882,7 @@ packages: tslib: 2.6.2 dev: false - /@graphql-mesh/transform-type-merging@0.93.1(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2): + /@graphql-mesh/transform-type-merging@0.93.1(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-CUrqCMaEqO1LDusv59UPqmQju3f+LpEGxFu7CydMiIvbfKDDDrf8+dF3OVU7d/ZOMRxB6hR80JsQF0SVeXPCOQ==} peerDependencies: '@graphql-mesh/types': ^0.93.1 @@ -6817,8 +6890,8 @@ packages: graphql: ^16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/stitching-directives': 2.3.34(graphql@16.8.1) graphql: 16.8.1 @@ -6841,16 +6914,16 @@ packages: graphql: 16.8.1 tslib: 2.6.2 - /@graphql-mesh/types@0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-afM2uuGR//lBoDrQvyfDmCcPwObpouRauahKVrXGyxkWe9LuIBG+scBZcynSbKotO1SgFcbJtToafMAIk5CefQ==} + /@graphql-mesh/types@0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-H2xh5KGc3+Ly3VdAPnRdKTibZpW9zEFgUzsozL9MQhCs6WLX+/kOADb0uIDqYFKX5c/2axmcy87BFNOausXYig==} engines: {node: '>=16.0.0'} peerDependencies: - '@graphql-mesh/store': ^0.95.7 + '@graphql-mesh/store': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 graphql: ^16.6.0 tslib: ^2.4.0 dependencies: - '@graphql-mesh/store': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/batch-delegate': 9.0.0(graphql@16.8.1) '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -6872,7 +6945,7 @@ packages: '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - dset: 3.1.2 + dset: 3.1.3 graphql: 16.8.1 js-yaml: 4.1.0 lodash.get: 4.4.2 @@ -6880,23 +6953,23 @@ packages: tiny-lru: 8.0.2 tslib: 2.6.2 - /@graphql-mesh/utils@0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-6YQTMTrLt6m/cAdesrBgbGVSrLd+68xTo1dRIhxUFHSgucSAqA47Q8E71Lc9cLHh80HQT+/pauKHHG40csy1Ng==} + /@graphql-mesh/utils@0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-gH2/kXvxMHVWMX8DppIIZpFfSUaoKDJ6eQHFoAAsdabGE+vLtVk0OEYqMGVGtD/8ZDFa/P6CmwXc6hBzoLY6Kg==} engines: {node: '>=16.0.0'} peerDependencies: '@graphql-mesh/cross-helpers': ^0.4.1 - '@graphql-mesh/types': ^0.95.7 + '@graphql-mesh/types': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 graphql: ^16.6.0 tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) - '@graphql-mesh/string-interpolation': 0.5.2(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/string-interpolation': 0.5.3(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - '@whatwg-node/fetch': 0.9.13 - dset: 3.1.2 + '@whatwg-node/fetch': 0.9.14 + dset: 3.1.3 graphql: 16.8.1 js-yaml: 4.1.0 lodash.get: 4.4.2 @@ -7030,7 +7103,7 @@ packages: - utf-8-validate dev: false - /@graphql-tools/executor-http@0.1.10(@types/node@18.18.6)(graphql@16.8.1): + /@graphql-tools/executor-http@0.1.10(@types/node@18.18.7)(graphql@16.8.1): resolution: {integrity: sha512-hnAfbKv0/lb9s31LhWzawQ5hghBfHS+gYWtqxME6Rl0Aufq9GltiiLBcl7OVVOnkLF0KhwgbYP1mB5VKmgTGpg==} peerDependencies: graphql: ^16.6.0 @@ -7038,16 +7111,16 @@ packages: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@repeaterjs/repeater': 3.0.4 '@whatwg-node/fetch': 0.8.8 - dset: 3.1.2 + dset: 3.1.3 extract-files: 11.0.0 graphql: 16.8.1 - meros: 1.3.0(@types/node@18.18.6) + meros: 1.3.0(@types/node@18.18.7) tslib: 2.6.2 value-or-promise: 1.0.12 transitivePeerDependencies: - '@types/node' - /@graphql-tools/executor-http@1.0.3(@types/node@18.18.6)(graphql@16.8.1): + /@graphql-tools/executor-http@1.0.3(@types/node@18.18.7)(graphql@16.8.1): resolution: {integrity: sha512-5WZIMBevRaxMabZ8U2Ty0dTUPy/PpeYSlMNEmC/YJjKKykgSfc/AwSejx2sE4FFKZ0I2kxRKRenyoWMHRAV49Q==} engines: {node: '>=16.0.0'} peerDependencies: @@ -7055,10 +7128,10 @@ packages: dependencies: '@graphql-tools/utils': 10.0.7(graphql@16.8.1) '@repeaterjs/repeater': 3.0.4 - '@whatwg-node/fetch': 0.9.13 + '@whatwg-node/fetch': 0.9.14 extract-files: 11.0.0 graphql: 16.8.1 - meros: 1.3.0(@types/node@18.18.6) + meros: 1.3.0(@types/node@18.18.7) tslib: 2.6.2 value-or-promise: 1.0.12 transitivePeerDependencies: @@ -7134,14 +7207,14 @@ packages: tslib: 2.6.2 value-or-promise: 1.0.12 - /@graphql-tools/federation@1.1.10(@types/node@18.18.6)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0): + /@graphql-tools/federation@1.1.10(@types/node@18.18.7)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-H51qTYwbtfIYBO1uHXlImRWzo9tknSoIGBgJckDh+hdxJx43sZaMjJiLHc2DjRc/A8d2Bf0bi0HbH++HqOos/w==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^16.6.0 dependencies: '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) - '@graphql-tools/executor-http': 1.0.3(@types/node@18.18.6)(graphql@16.8.1) + '@graphql-tools/executor-http': 1.0.3(@types/node@18.18.7)(graphql@16.8.1) '@graphql-tools/merge': 9.0.0(graphql@16.8.1) '@graphql-tools/schema': 10.0.0(graphql@16.8.1) '@graphql-tools/stitch': 9.0.3(graphql@16.8.1) @@ -7316,7 +7389,7 @@ packages: graphql: 16.8.1 tslib: 2.6.2 - /@graphql-tools/url-loader@7.17.18(@types/node@18.18.6)(graphql@16.8.1): + /@graphql-tools/url-loader@7.17.18(@types/node@18.18.7)(graphql@16.8.1): resolution: {integrity: sha512-ear0CiyTj04jCVAxi7TvgbnGDIN2HgqzXzwsfcqiVg9cvjT40NcMlZ2P1lZDgqMkZ9oyLTV8Bw6j+SyG6A+xPw==} peerDependencies: graphql: ^16.6.0 @@ -7324,7 +7397,7 @@ packages: '@ardatan/sync-fetch': 0.0.1 '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/executor-graphql-ws': 0.0.14(graphql@16.8.1) - '@graphql-tools/executor-http': 0.1.10(@types/node@18.18.6)(graphql@16.8.1) + '@graphql-tools/executor-http': 0.1.10(@types/node@18.18.7)(graphql@16.8.1) '@graphql-tools/executor-legacy-ws': 0.0.11(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) @@ -7341,7 +7414,7 @@ packages: - encoding - utf-8-validate - /@graphql-tools/url-loader@8.0.0(@types/node@18.18.6)(graphql@16.8.1): + /@graphql-tools/url-loader@8.0.0(@types/node@18.18.7)(graphql@16.8.1): resolution: {integrity: sha512-rPc9oDzMnycvz+X+wrN3PLrhMBQkG4+sd8EzaFN6dypcssiefgWKToXtRKI8HHK68n2xEq1PyrOpkjHFJB+GwA==} engines: {node: '>=16.0.0'} peerDependencies: @@ -7350,12 +7423,12 @@ packages: '@ardatan/sync-fetch': 0.0.1 '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/executor-graphql-ws': 1.1.0(graphql@16.8.1) - '@graphql-tools/executor-http': 1.0.3(@types/node@18.18.6)(graphql@16.8.1) + '@graphql-tools/executor-http': 1.0.3(@types/node@18.18.7)(graphql@16.8.1) '@graphql-tools/executor-legacy-ws': 1.0.4(graphql@16.8.1) '@graphql-tools/utils': 10.0.7(graphql@16.8.1) '@graphql-tools/wrap': 10.0.1(graphql@16.8.1) '@types/ws': 8.5.8 - '@whatwg-node/fetch': 0.9.13 + '@whatwg-node/fetch': 0.9.14 graphql: 16.8.1 isomorphic-ws: 5.0.0(ws@8.14.2) tslib: 2.6.2 @@ -7375,7 +7448,7 @@ packages: graphql: ^16.6.0 dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) - dset: 3.1.2 + dset: 3.1.3 graphql: 16.8.1 tslib: 2.6.2 @@ -7517,33 +7590,33 @@ packages: resolution: {integrity: sha512-n6fwMsaoR50VITM2upR4OOi4EZJmZvU6vvXrHWCSakP9e1OeDuAOk+kHiK+egqDRYj6uKtg9VTUFKZBYvu3jRg==} dev: false - /@hypercerts-org/sdk@0.8.16(@envelop/core@3.0.6)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.6)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3): + /@hypercerts-org/sdk@0.8.16(@envelop/core@3.0.6)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3): resolution: {integrity: sha512-WkxYb5RYhv3QI7+N5y4xg5IL4azLqCq4ia1/bgFB55vWJLjnmoMj3VYbiybMxyfgnPfh5O8n2DU86u8ClLgyhg==} dependencies: '@ethereum-attestation-service/eas-sdk': 0.28.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(typescript@5.1.6) '@ethersproject/abstract-signer': 5.7.0 - '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.95.7)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) + '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) '@graphprotocol/client-polling-live': 2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@8.4.2)(graphql@16.8.1) - '@graphql-mesh/cache-localforage': 0.95.7(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/cache-localforage': 0.95.8(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) - '@graphql-mesh/graphql': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(@types/node@18.18.6)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2) - '@graphql-mesh/http': 0.96.13(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/runtime@0.96.12)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/merger-bare': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/runtime': 0.96.12(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/store': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-mesh/utils@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.7(@graphql-mesh/store@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.7(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.7)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/graphql': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2) + '@graphql-mesh/http': 0.96.14(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/runtime@0.96.13)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/merger-bare': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/runtime': 0.96.13(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) '@hypercerts-org/contracts': 0.8.11 '@openzeppelin/merkle-tree': 1.0.5 - '@whatwg-node/fetch': 0.9.13 + '@whatwg-node/fetch': 0.9.14 ajv: 8.12.0 axios: 1.5.1(debug@4.3.4) dotenv: 16.3.1 ethers: 5.7.2 graphql: 16.8.1 ipfs-core: 0.17.0(uint8arraylist@2.4.3) - jest: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) + jest: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) loglevel: 1.8.1 mime: 3.0.0 nft.storage: 7.1.1(node-fetch@3.3.2) @@ -7592,8 +7665,8 @@ packages: engines: {node: '>=16.0.0', npm: '>=7.0.0'} dependencies: '@ipld/dag-cbor': 9.0.6 - cborg: 4.0.4 - multiformats: 12.1.2 + cborg: 4.0.5 + multiformats: 12.1.3 varint: 6.0.0 dev: false @@ -7622,8 +7695,8 @@ packages: resolution: {integrity: sha512-3kNab5xMppgWw6DVYx2BzmFq8t7I56AGWfp5kaU1fIPkwHVpBRglJJTYsGtbVluCi/s/q97HZM3bC+aDW4sxbQ==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} dependencies: - cborg: 4.0.4 - multiformats: 12.1.2 + cborg: 4.0.5 + multiformats: 12.1.3 dev: false /@ipld/dag-json@8.0.11: @@ -7683,7 +7756,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -7703,14 +7776,14 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) + jest-config: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -7743,7 +7816,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 jest-mock: 29.7.0 /@jest/expect-utils@29.7.0: @@ -7767,7 +7840,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 18.18.6 + '@types/node': 18.18.7 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -7798,7 +7871,7 @@ packages: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.20 - '@types/node': 18.18.6 + '@types/node': 18.18.7 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -7879,7 +7952,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.5 '@types/istanbul-reports': 3.0.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 '@types/yargs': 15.0.17 chalk: 4.1.2 @@ -7889,7 +7962,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.5 '@types/istanbul-reports': 3.0.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 '@types/yargs': 16.0.7 chalk: 4.1.2 @@ -7900,7 +7973,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.5 '@types/istanbul-reports': 3.0.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 '@types/yargs': 17.0.29 chalk: 4.1.2 @@ -8354,14 +8427,14 @@ packages: - supports-color dev: false - /@libp2p/interface@0.1.3: - resolution: {integrity: sha512-C1O7Xqd2TGVWrIOEDx6kGJSk4YOysWGmYG5Oh3chnsCY0wjUSsLDpl9+wKrdiM/lJbAlHlV65ZOvSkIQ9cWPBQ==} + /@libp2p/interface@0.1.4: + resolution: {integrity: sha512-Pk8mzit/w7PbTh28n77RDLTU1CQBBzLygiNC07MvcEjaIwqXdNPN3Vuzr/5qiF6aDsbM9fA1W5dWoCif9xBdxg==} dependencies: '@multiformats/multiaddr': 12.1.7 abortable-iterator: 5.0.1 it-pushable: 3.2.1 it-stream-types: 2.0.1 - multiformats: 12.1.2 + multiformats: 12.1.3 p-defer: 4.0.0 race-signal: 1.0.1 uint8arraylist: 2.4.3 @@ -8440,14 +8513,14 @@ packages: - supports-color dev: false - /@libp2p/logger@3.0.3: - resolution: {integrity: sha512-85ioPX10QN4ZOZeurAZe5sQeRUCkIBT2DikKRbE/AIWKauIKHvvIrN4CSdCdzLw29XNA+xxNO2FVkf51HGgCeQ==} + /@libp2p/logger@3.0.4: + resolution: {integrity: sha512-MF42c7SOJIx5YmHhIsFaSYfaC266YYmMbAJHjjH8Zl5unFsqW82M+Xr7sGVj9/WXrWAd37ts8xJaQrkIXc3OZQ==} dependencies: - '@libp2p/interface': 0.1.3 + '@libp2p/interface': 0.1.4 '@multiformats/multiaddr': 12.1.7 debug: 4.3.4(supports-color@8.1.1) interface-datastore: 8.2.5 - multiformats: 12.1.2 + multiformats: 12.1.3 transitivePeerDependencies: - supports-color dev: false @@ -8824,6 +8897,11 @@ packages: '@lit-labs/ssr-dom-shim': 1.1.2 dev: false + /@looksrare/contracts-libs@3.4.0: + resolution: {integrity: sha512-tRFHcz9D4J0PLQg4ETWlvlRqrHpEoZhKsCTbyqATDXmekXvxbgk8+sRtaZK9Zo4gHpt6x+TcOgdUdARCg2elWg==} + engines: {node: '>=8.3.0'} + dev: true + /@mdx-js/mdx@1.6.22: resolution: {integrity: sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==} dependencies: @@ -8872,8 +8950,8 @@ packages: tweetnacl: 1.0.3 tweetnacl-util: 0.15.1 - /@metamask/object-multiplex@1.2.0: - resolution: {integrity: sha512-hksV602d3NWE2Q30Mf2Np1WfVKaGqfJRy9vpHAmelbaD0OkDt06/0KQkRR6UVYdMbTbkuEu8xN5JDUU80inGwQ==} + /@metamask/object-multiplex@1.3.0: + resolution: {integrity: sha512-czcQeVYdSNtabd+NcYQnrM69MciiJyd1qvKH8WM2Id3C0ZiUUX5Xa/MK+/VUk633DBhVOwdNzAKIQ33lGyA+eQ==} engines: {node: '>=12.0.0'} dependencies: end-of-stream: 1.4.4 @@ -8885,10 +8963,10 @@ packages: resolution: {integrity: sha512-xjE4cKrGpKZjripkMKMStc0H4LXrWJPijfbaj1kKeDLVhRH2Yu3ZecV3iIhf1EIJePeA+Kx6Pcm7d0IVJ+ea7g==} engines: {node: '>=16.0.0'} dependencies: - '@metamask/object-multiplex': 1.2.0 + '@metamask/object-multiplex': 1.3.0 '@metamask/safe-event-emitter': 3.0.0 detect-browser: 5.3.0 - eth-rpc-errors: 4.0.2 + eth-rpc-errors: 4.0.3 extension-port-stream: 2.1.1 fast-deep-equal: 3.1.3 is-stream: 2.0.1 @@ -9175,8 +9253,8 @@ packages: - supports-color dev: true - /@mui/base@5.0.0-beta.20(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-CS2pUuqxST7ch9VNDCklRYDbJ3rru20Tx7na92QvVVKfu3RL4z/QLuVIc8jYGsdCnauMaeUSlFNLAJNb0yXe6w==} + /@mui/base@5.0.0-beta.21(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-eTKWx3WV/nwmRUK4z4K1MzlMyWCsi3WJ3RtV4DiXZeRh4qd4JCyp1Zzzi8Wv9xM4dEBmqQntFoei716PzwmFfA==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -9188,22 +9266,22 @@ packages: dependencies: '@babel/runtime': 7.23.2 '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0)(react@18.2.0) - '@mui/types': 7.2.6(@types/react@18.2.31) - '@mui/utils': 5.14.14(@types/react@18.2.31)(react@18.2.0) + '@mui/types': 7.2.7(@types/react@18.2.33) + '@mui/utils': 5.14.15(@types/react@18.2.33)(react@18.2.0) '@popperjs/core': 2.11.8 - '@types/react': 18.2.31 + '@types/react': 18.2.33 clsx: 2.0.0 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /@mui/core-downloads-tracker@5.14.14: - resolution: {integrity: sha512-Rw/xKiTOUgXD8hdKqj60aC6QcGprMipG7ne2giK6Mz7b4PlhL/xog9xLeclY3BxsRLkZQ05egFnIEY1CSibTbw==} + /@mui/core-downloads-tracker@5.14.15: + resolution: {integrity: sha512-ZCDzBWtCKjAYAlKKM3PA/jG/3uVIDT9ZitOtVixIVmTCQyc5jSV1qhJX8+qIGz4RQZ9KLzPWO2tXd0O5hvzouQ==} dev: false - /@mui/icons-material@5.14.14(@mui/material@5.14.14)(@types/react@18.2.31)(react@18.2.0): - resolution: {integrity: sha512-vwuaMsKvI7AWTeYqR8wYbpXijuU8PzMAJWRAq2DDIuOZPxjKyHlr8WQ25+azZYkIXtJ7AqnVb1ZmHdEyB4/kug==} + /@mui/icons-material@5.14.15(@mui/material@5.14.15)(@types/react@18.2.33)(react@18.2.0): + resolution: {integrity: sha512-Dqu21vN/mVNzebJ+ofnKG+CeJYIhHuDs5+0fMEpdpzRt6UojelzdrEkNv+XkO0e1JMclzeXIRx404FirK/CFRw==} engines: {node: '>=12.0.0'} peerDependencies: '@mui/material': ^5.0.0 @@ -9214,13 +9292,13 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.2 - '@mui/material': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) - '@types/react': 18.2.31 + '@mui/material': 5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.33 react: 18.2.0 dev: false - /@mui/material@5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-cAmCwAHFQXxb44kWbVFkhKATN8tACgMsFwrXo8ro6WzYW73U/qsR5AcCiJIhCyYYg+gcftfkmNcpRaV3JjhHCg==} + /@mui/material@5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Gq65rHjvLzkxmhG8bvag851Oqsmru7qkUb/cCI2xu7dQzmY345f9xJRJi72sRGjhaqHXWeRKw/yIwp/7oQoeXg==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -9237,14 +9315,14 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.2 - '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) - '@mui/base': 5.0.0-beta.20(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) - '@mui/core-downloads-tracker': 5.14.14 - '@mui/system': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react@18.2.0) - '@mui/types': 7.2.6(@types/react@18.2.31) - '@mui/utils': 5.14.14(@types/react@18.2.31)(react@18.2.0) - '@types/react': 18.2.31 + '@emotion/react': 11.11.1(@types/react@18.2.33)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) + '@mui/base': 5.0.0-beta.21(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@mui/core-downloads-tracker': 5.14.15 + '@mui/system': 5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react@18.2.0) + '@mui/types': 7.2.7(@types/react@18.2.33) + '@mui/utils': 5.14.15(@types/react@18.2.33)(react@18.2.0) + '@types/react': 18.2.33 '@types/react-transition-group': 4.4.8 clsx: 2.0.0 csstype: 3.1.2 @@ -9255,8 +9333,8 @@ packages: react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: false - /@mui/private-theming@5.14.14(@types/react@18.2.31)(react@18.2.0): - resolution: {integrity: sha512-n77au3CQj9uu16hak2Y+rvbGSBaJKxziG/gEbOLVGrAuqZ+ycVSkorCfN6Y/4XgYOpG/xvmuiY3JwhAEOzY3iA==} + /@mui/private-theming@5.14.15(@types/react@18.2.33)(react@18.2.0): + resolution: {integrity: sha512-V2Xh+Tu6A07NoSpup0P9m29GwvNMYl5DegsGWqlOTJyAV7cuuVjmVPqxgvL8xBng4R85xqIQJRMjtYYktoPNuQ==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -9266,14 +9344,14 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.2 - '@mui/utils': 5.14.14(@types/react@18.2.31)(react@18.2.0) - '@types/react': 18.2.31 + '@mui/utils': 5.14.15(@types/react@18.2.33)(react@18.2.0) + '@types/react': 18.2.33 prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/styled-engine@5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): - resolution: {integrity: sha512-sF3DS2PVG+cFWvkVHQQaGFpL1h6gSwOW3L91pdxPLQDHDZ5mZ/X0SlXU5XA+WjypoysG4urdAQC7CH/BRvUiqg==} + /@mui/styled-engine@5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): + resolution: {integrity: sha512-mbOjRf867BysNpexe5Z/P8s3bWzDPNowmKhi7gtNDP/LPEeqAfiDSuC4WPTXmtvse1dCl30Nl755OLUYuoi7Mw==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.4.1 @@ -9287,15 +9365,15 @@ packages: dependencies: '@babel/runtime': 7.23.2 '@emotion/cache': 11.11.0 - '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) + '@emotion/react': 11.11.1(@types/react@18.2.33)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) csstype: 3.1.2 prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/system@5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react@18.2.0): - resolution: {integrity: sha512-y4InFmCgGGWXnz+iK4jRTWVikY0HgYnABjz4wgiUgEa2W1H8M4ow+27BegExUWPkj4TWthQ2qG9FOGSMtI+PKA==} + /@mui/system@5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react@18.2.0): + resolution: {integrity: sha512-zr0Gdk1RgKiEk+tCMB900LaOpEC8NaGvxtkmMdL/CXgkqQZSVZOt2PQsxJWaw7kE4YVkIe4VukFVc43qcq9u3w==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -9311,32 +9389,32 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.2 - '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) - '@mui/private-theming': 5.14.14(@types/react@18.2.31)(react@18.2.0) - '@mui/styled-engine': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) - '@mui/types': 7.2.6(@types/react@18.2.31) - '@mui/utils': 5.14.14(@types/react@18.2.31)(react@18.2.0) - '@types/react': 18.2.31 + '@emotion/react': 11.11.1(@types/react@18.2.33)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) + '@mui/private-theming': 5.14.15(@types/react@18.2.33)(react@18.2.0) + '@mui/styled-engine': 5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) + '@mui/types': 7.2.7(@types/react@18.2.33) + '@mui/utils': 5.14.15(@types/react@18.2.33)(react@18.2.0) + '@types/react': 18.2.33 clsx: 2.0.0 csstype: 3.1.2 prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/types@7.2.6(@types/react@18.2.31): - resolution: {integrity: sha512-7sjLQrUmBwufm/M7jw/quNiPK/oor2+pGUQP2CULRcFCArYTq78oJ3D5esTaL0UMkXKJvDqXn6Ike69yAOBQng==} + /@mui/types@7.2.7(@types/react@18.2.33): + resolution: {integrity: sha512-sofpWmcBqOlTzRbr1cLQuUDKaUYVZTw8ENQrtL39TECRNENEzwgnNPh6WMfqMZlMvf1Aj9DLg74XPjnLr0izUQ==} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 peerDependenciesMeta: '@types/react': optional: true dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 dev: false - /@mui/utils@5.14.14(@types/react@18.2.31)(react@18.2.0): - resolution: {integrity: sha512-3AKp8uksje5sRfVrtgG9Q/2TBsHWVBUtA0NaXliZqGcXo8J+A+Agp0qUW2rJ+ivgPWTCCubz9FZVT2IQZ3bGsw==} + /@mui/utils@5.14.15(@types/react@18.2.33)(react@18.2.0): + resolution: {integrity: sha512-QBfHovAvTa0J1jXuYDaXGk+Yyp7+Fm8GSqx6nK2JbezGqzCFfirNdop/+bL9Flh/OQ/64PeXcW4HGDdOge+n3A==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -9347,13 +9425,13 @@ packages: dependencies: '@babel/runtime': 7.23.2 '@types/prop-types': 15.7.9 - '@types/react': 18.2.31 + '@types/react': 18.2.33 prop-types: 15.8.1 react: 18.2.0 react-is: 18.2.0 dev: false - /@mui/x-date-pickers@5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(@mui/system@5.14.14)(@types/react@18.2.31)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0): + /@mui/x-date-pickers@5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.15)(@mui/system@5.14.15)(@types/react@18.2.33)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-ERukSeHIoNLbI1C2XRhF9wRhqfsr+Q4B1SAw2ZlU7CWgcG8UBOxgqRKDEOVAIoSWL+DWT6GRuQjOKvj6UXZceA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -9387,11 +9465,11 @@ packages: '@date-io/dayjs': 2.17.0(dayjs@1.11.10) '@date-io/luxon': 2.17.0 '@date-io/moment': 2.17.0 - '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) - '@mui/material': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) - '@mui/system': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react@18.2.0) - '@mui/utils': 5.14.14(@types/react@18.2.31)(react@18.2.0) + '@emotion/react': 11.11.1(@types/react@18.2.33)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) + '@mui/material': 5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@mui/system': 5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react@18.2.0) + '@mui/utils': 5.14.15(@types/react@18.2.33)(react@18.2.0) '@types/react-transition-group': 4.4.8 clsx: 1.2.1 dayjs: 1.11.10 @@ -9450,9 +9528,9 @@ packages: dependencies: '@chainsafe/is-ip': 2.0.2 '@chainsafe/netmask': 2.0.0 - '@libp2p/interface': 0.1.3 + '@libp2p/interface': 0.1.4 dns-over-http-resolver: 2.1.2 - multiformats: 12.1.2 + multiformats: 12.1.3 uint8-varint: 2.0.1 uint8arrays: 4.0.6 transitivePeerDependencies: @@ -9470,7 +9548,7 @@ packages: resolution: {integrity: sha512-Yf0UpAaONjed+8PTt5NM/GG4Z4Ai4m1qfT7bqevjnkwRQ12K+0jxtRomirz+VJx4PokpA2St1ZSD1iMkZTqPRQ==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} dependencies: - multiformats: 12.1.2 + multiformats: 12.1.3 murmurhash3js-revisited: 3.0.0 dev: false @@ -9804,7 +9882,7 @@ packages: hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) dev: true - /@nomicfoundation/hardhat-toolbox@2.0.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-chai-matchers@1.0.6)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(@typechain/ethers-v5@11.1.2)(@typechain/hardhat@9.1.0)(@types/chai@4.3.9)(@types/mocha@9.1.0)(@types/node@18.18.6)(chai@4.3.10)(ethers@5.7.2)(hardhat-gas-reporter@1.0.9)(hardhat@2.13.1)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.2)(typescript@4.9.5): + /@nomicfoundation/hardhat-toolbox@2.0.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-chai-matchers@1.0.6)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(@typechain/ethers-v5@11.1.2)(@typechain/hardhat@9.1.0)(@types/chai@4.3.9)(@types/mocha@9.1.0)(@types/node@18.18.7)(chai@4.3.10)(ethers@5.7.2)(hardhat-gas-reporter@1.0.9)(hardhat@2.13.1)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.2)(typescript@4.9.5): resolution: {integrity: sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg==} peerDependencies: '@ethersproject/abi': ^5.4.7 @@ -9837,13 +9915,13 @@ packages: '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2) '@types/chai': 4.3.9 '@types/mocha': 9.1.0 - '@types/node': 18.18.6 + '@types/node': 18.18.7 chai: 4.3.10 ethers: 5.7.2 hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) hardhat-gas-reporter: 1.0.9(hardhat@2.13.1) solidity-coverage: 0.8.5(hardhat@2.13.1) - ts-node: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) typechain: 8.3.2(typescript@4.9.5) typescript: 4.9.5 dev: true @@ -9995,7 +10073,7 @@ packages: d3-require: 1.3.0 dev: false - /@oclif/core@2.15.0(@types/node@18.18.6)(typescript@4.9.5): + /@oclif/core@2.15.0(@types/node@18.18.7)(typescript@4.9.5): resolution: {integrity: sha512-fNEMG5DzJHhYmI3MgpByTvltBOMyFcnRIUMxbiz2ai8rhaYgaTHMG3Q38HcosfIvtw9nCjxpcQtC8MN8QtVCcA==} engines: {node: '>=14.0.0'} dependencies: @@ -10022,7 +10100,7 @@ packages: strip-ansi: 6.0.1 supports-color: 8.1.1 supports-hyperlinks: 2.3.0 - ts-node: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) tslib: 2.6.2 widest-line: 3.1.0 wordwrap: 1.0.0 @@ -10034,7 +10112,7 @@ packages: - typescript dev: true - /@oclif/core@2.8.6(@types/node@18.18.6)(typescript@4.9.5): + /@oclif/core@2.8.6(@types/node@18.18.7)(typescript@4.9.5): resolution: {integrity: sha512-1QlPaHMhOORySCXkQyzjsIsy2GYTilOw3LkjeHkCgsPJQjAT4IclVytJusWktPbYNys9O+O4V23J44yomQvnBQ==} engines: {node: '>=14.0.0'} dependencies: @@ -10057,12 +10135,12 @@ packages: natural-orderby: 2.0.3 object-treeify: 1.1.33 password-prompt: 1.1.3 - semver: 7.5.4 + semver: 7.4.0 string-width: 4.2.3 strip-ansi: 6.0.1 supports-color: 8.1.1 supports-hyperlinks: 2.3.0 - ts-node: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) tslib: 2.6.2 widest-line: 3.1.0 wordwrap: 1.0.0 @@ -10074,11 +10152,11 @@ packages: - typescript dev: true - /@oclif/plugin-autocomplete@2.3.10(@types/node@18.18.6)(typescript@4.9.5): + /@oclif/plugin-autocomplete@2.3.10(@types/node@18.18.7)(typescript@4.9.5): resolution: {integrity: sha512-Ow1AR8WtjzlyCtiWWPgzMyT8SbcDJFr47009riLioHa+MHX2BCDtVn2DVnN/E6b9JlPV5ptQpjefoRSNWBesmg==} engines: {node: '>=12.0.0'} dependencies: - '@oclif/core': 2.15.0(@types/node@18.18.6)(typescript@4.9.5) + '@oclif/core': 2.15.0(@types/node@18.18.7)(typescript@4.9.5) chalk: 4.1.2 debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: @@ -10089,11 +10167,11 @@ packages: - typescript dev: true - /@oclif/plugin-not-found@2.4.3(@types/node@18.18.6)(typescript@4.9.5): + /@oclif/plugin-not-found@2.4.3(@types/node@18.18.7)(typescript@4.9.5): resolution: {integrity: sha512-nIyaR4y692frwh7wIHZ3fb+2L6XEecQwRDIb4zbEam0TvaVmBQWZoColQyWA84ljFBPZ8XWiQyTz+ixSwdRkqg==} engines: {node: '>=12.0.0'} dependencies: - '@oclif/core': 2.15.0(@types/node@18.18.6)(typescript@4.9.5) + '@oclif/core': 2.15.0(@types/node@18.18.7)(typescript@4.9.5) chalk: 4.1.2 fast-levenshtein: 3.0.0 transitivePeerDependencies: @@ -10107,10 +10185,26 @@ packages: resolution: {integrity: sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==} dev: true - /@openzeppelin/defender-admin-client@1.49.0: - resolution: {integrity: sha512-ka+GTbsnGO6j1R2AGj027uu29es/EBVs3VjJStb+7u/1lNhx1xSRS11JBD0a0GNhrwqsKU4czIemlIKMlUzhhQ==} + /@openzeppelin/contracts-upgradeable@4.7.3: + resolution: {integrity: sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A==} + dev: true + + /@openzeppelin/contracts@3.4.2: + resolution: {integrity: sha512-z0zMCjyhhp4y7XKAcDAi3Vgms4T2PstwBdahiO0+9NaGICQKjynK3wduSRplTgk4LXmoO1yfDGO5RbjKYxtuxA==} + dev: true + + /@openzeppelin/contracts@4.3.3: + resolution: {integrity: sha512-tDBopO1c98Yk7Cv/PZlHqrvtVjlgK5R4J6jxLwoO7qxK4xqOiZG+zSkIvGFpPZ0ikc3QOED3plgdqjgNTnBc7g==} + dev: true + + /@openzeppelin/contracts@4.9.3: + resolution: {integrity: sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==} + dev: true + + /@openzeppelin/defender-admin-client@1.50.0: + resolution: {integrity: sha512-JxeA111ifCIzXho2gFymhepufB0ElI1UMvFIMEfJLvRL7g7V69wSiN8v+OqZyqZTahiY32Rb+TwdhVjKF5Zu+A==} dependencies: - '@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4) + '@openzeppelin/defender-base-client': 1.50.0 axios: 1.5.1(debug@4.3.4) ethers: 5.7.2 lodash: 4.17.21 @@ -10122,11 +10216,11 @@ packages: - utf-8-validate dev: true - /@openzeppelin/defender-autotask-client@1.49.0: - resolution: {integrity: sha512-FhqFB/E0jaDNEgx0WklodpRS2RPfE181+kwtGL23a8uzGiyQRs7+Ia/a8ARGaLEqD9gWwAte6ODiqZAaim7/jg==} + /@openzeppelin/defender-autotask-client@1.50.0: + resolution: {integrity: sha512-QWob3F6xuOu8r8oPy0Y2XLfAL1PTuKE2F4nC4wGeu3JJT8/pJz3xnHX5DgUYwiGIMqnkitUNUoBcmi4CPI31yw==} hasBin: true dependencies: - '@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4) + '@openzeppelin/defender-base-client': 1.50.0 axios: 1.5.1(debug@4.3.4) dotenv: 10.0.0 glob: 7.2.3 @@ -10138,8 +10232,8 @@ packages: - encoding dev: false - /@openzeppelin/defender-autotask-utils@1.49.0: - resolution: {integrity: sha512-rJls6HOuddBsPJwbSmIN/nugdIsgdrwzgpVJC/hxv+amu0HsSkrH26LbcoDig7Eb2dp68Avtmo0EOyAUP1bNGA==} + /@openzeppelin/defender-autotask-utils@1.50.0: + resolution: {integrity: sha512-wuhm5idjsIiC7hdLj+z5ewDmyKx5q0tRXKHp05K9X8uo1CyLdHV2kKZjBrWzGE9qxVhJ79f9PzHZrLcyPHNDOg==} dev: false /@openzeppelin/defender-base-client@1.49.0(debug@4.3.4): @@ -10154,6 +10248,18 @@ packages: - debug - encoding + /@openzeppelin/defender-base-client@1.50.0: + resolution: {integrity: sha512-V5uJ4t3kr9ex1RrqGH2DwsHuyW7/hl3VK0sSkq3VVbAewtcsW3cdg/UkXd5ITu6mtz76RoYkvUBHtkYUm0nb+w==} + dependencies: + amazon-cognito-identity-js: 6.3.6 + async-retry: 1.3.3 + axios: 1.5.1(debug@4.3.4) + lodash: 4.17.21 + node-fetch: 2.7.0 + transitivePeerDependencies: + - debug + - encoding + /@openzeppelin/defender-sentinel-client@1.49.0: resolution: {integrity: sha512-fr39U1GRWvJP1fWgwqjTYCz7uhfVfXJReWcivwxMeaoyMl+jYFxj8NkMhqkkbmI6O4TUyNMsmAQ34qFf0IS0/A==} dependencies: @@ -10171,7 +10277,7 @@ packages: resolution: {integrity: sha512-dl2pQyBvwEZVq1sgw/i+mLQiu4ZD7iKn2/ghD9RbAGHIM8hZQ4ou8cXl1S6wCA92prpeO1rPGQ+NcJajbY4MCw==} deprecated: '@openzeppelin/hardhat-defender is deprecated. This functionality is now included as part of @openzeppelin/hardhat-upgrades' dependencies: - '@openzeppelin/defender-admin-client': 1.49.0 + '@openzeppelin/defender-admin-client': 1.50.0 '@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4) '@openzeppelin/hardhat-upgrades': 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.13.1) ethereumjs-util: 7.1.5 @@ -10481,7 +10587,7 @@ packages: /@protobufjs/utf8@1.1.0: resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - /@rainbow-me/rainbowkit@1.0.8(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9): + /@rainbow-me/rainbowkit@1.0.8(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9): resolution: {integrity: sha512-m1B9/X3p8MLmj4fDfs2NpJlFRmKz7vOR0jmcdBw2SMFzXqP1FQFQc4pjvtLEeyfEUGSNNceGrecFZRVS0Qk//A==} engines: {node: '>=12.4'} peerDependencies: @@ -10497,9 +10603,9 @@ packages: qrcode: 1.5.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.4(@types/react@18.2.31)(react@18.2.0) + react-remove-scroll: 2.5.4(@types/react@18.2.33)(react@18.2.0) viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) - wagmi: 1.3.9(@types/react@18.2.31)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + wagmi: 1.3.9(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) transitivePeerDependencies: - '@types/react' dev: false @@ -11107,26 +11213,24 @@ packages: '@scure/base': 1.1.3 dev: true - /@sentry-internal/tracing@7.74.1: - resolution: {integrity: sha512-nNaiZreQxCitG2PzYPaC7XtyA9OMsETGYMKAtiK4p62/uTmeYbsBva9BoNx1XeiHRwbrVQYRMKQ9nV5e2jS4/A==} + /@sentry-internal/tracing@7.75.1: + resolution: {integrity: sha512-nynV+7iVcF8k3CqhvI2K7iA8h4ovJhgYHKnXR8RDDevQOqNG2AEX9+hjCj9fZM4MhKHYFqf1od2oO9lTr38kwg==} engines: {node: '>=8'} dependencies: - '@sentry/core': 7.74.1 - '@sentry/types': 7.74.1 - '@sentry/utils': 7.74.1 - tslib: 2.6.2 + '@sentry/core': 7.75.1 + '@sentry/types': 7.75.1 + '@sentry/utils': 7.75.1 dev: false - /@sentry/browser@7.74.1: - resolution: {integrity: sha512-OYWNne/KO60lOvkIpIlJUyiJt/9j8DGI57thSDFEYSmmbNqMitczUTBOaEStouvHKyfchqLZm1CZfWKt+z0VOA==} + /@sentry/browser@7.75.1: + resolution: {integrity: sha512-0+jPfPA5P9HVYYRQraDokGCY2NiMknSfz11dggClK4VmjvG+hOXiEyf73SFVwLFnv/hwrkWySjoIrVCX65xXQA==} engines: {node: '>=8'} dependencies: - '@sentry-internal/tracing': 7.74.1 - '@sentry/core': 7.74.1 - '@sentry/replay': 7.74.1 - '@sentry/types': 7.74.1 - '@sentry/utils': 7.74.1 - tslib: 2.6.2 + '@sentry-internal/tracing': 7.75.1 + '@sentry/core': 7.75.1 + '@sentry/replay': 7.75.1 + '@sentry/types': 7.75.1 + '@sentry/utils': 7.75.1 dev: false /@sentry/cli@1.75.2: @@ -11172,13 +11276,12 @@ packages: '@sentry/utils': 5.30.0 tslib: 1.14.1 - /@sentry/core@7.74.1: - resolution: {integrity: sha512-LvEhOSfdIvwkr+PdlrT/aA/iOLhkXrSkvjqAQyogE4ddCWeYfS0NoirxNt1EaxMBAWKhYZRqzkA7WA4LDLbzlA==} + /@sentry/core@7.75.1: + resolution: {integrity: sha512-Kw4KyKBxbxbh8OKO0S11Tm0gWP+6AaXXYrsq3hp8H338l/wOmIzyckmCbUrc/XJeoRqaFLJbdcCrcUEDZUvsVQ==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.74.1 - '@sentry/utils': 7.74.1 - tslib: 2.6.2 + '@sentry/types': 7.75.1 + '@sentry/utils': 7.75.1 dev: false /@sentry/hub@5.30.0: @@ -11189,15 +11292,14 @@ packages: '@sentry/utils': 5.30.0 tslib: 1.14.1 - /@sentry/integrations@7.74.1: - resolution: {integrity: sha512-Q7chPehHpHB4WOQ1J/X6NiN2ptiqJMmxtL+6wHumzIAyrjup3c9XekR83qEs8zpqYJAlb/4MUlwd9fPbkhGXnQ==} + /@sentry/integrations@7.75.1: + resolution: {integrity: sha512-qSCyTNX3DiL1aYRmdq10LRhPLfh1KJYKhbmGszC1PII4mt9FbLVmC8fSXiDbhgiuSUKKrDE+J2lC//w688lvHw==} engines: {node: '>=8'} dependencies: - '@sentry/core': 7.74.1 - '@sentry/types': 7.74.1 - '@sentry/utils': 7.74.1 + '@sentry/core': 7.75.1 + '@sentry/types': 7.75.1 + '@sentry/utils': 7.75.1 localforage: 1.10.0 - tslib: 2.6.2 dev: false /@sentry/minimal@5.30.0: @@ -11208,8 +11310,8 @@ packages: '@sentry/types': 5.30.0 tslib: 1.14.1 - /@sentry/nextjs@7.74.1(next@13.5.6)(react@18.2.0)(webpack@5.89.0): - resolution: {integrity: sha512-1RySEs3WBEqlpQCAFQ/XwV+oW4wEAtpYglvAyDBwPen/s6KnkkZ0za0l3Ug0O6S9HvMiNll1rPhvnkH5nM37Tg==} + /@sentry/nextjs@7.75.1(next@13.5.6)(react@18.2.0)(webpack@5.89.0): + resolution: {integrity: sha512-5DEW6Ksjuox8idf3O0NclF/rHSS0Z1VCIoFHW6d28FHFKU+/RkFwJTB13KfpQMBj1fiA9qSNJdy/2QlGUWVRmA==} engines: {node: '>=8'} peerDependencies: next: ^10.0.8 || ^11.0 || ^12.0 || ^13.0 @@ -11220,13 +11322,13 @@ packages: optional: true dependencies: '@rollup/plugin-commonjs': 24.0.0(rollup@2.78.0) - '@sentry/core': 7.74.1 - '@sentry/integrations': 7.74.1 - '@sentry/node': 7.74.1 - '@sentry/react': 7.74.1(react@18.2.0) - '@sentry/types': 7.74.1 - '@sentry/utils': 7.74.1 - '@sentry/vercel-edge': 7.74.1 + '@sentry/core': 7.75.1 + '@sentry/integrations': 7.75.1 + '@sentry/node': 7.75.1 + '@sentry/react': 7.75.1(react@18.2.0) + '@sentry/types': 7.75.1 + '@sentry/utils': 7.75.1 + '@sentry/vercel-edge': 7.75.1 '@sentry/webpack-plugin': 1.20.0 chalk: 3.0.0 next: 13.5.6(@babel/core@7.23.2)(react-dom@18.2.0)(react@18.2.0) @@ -11234,7 +11336,6 @@ packages: resolve: 1.22.8 rollup: 2.78.0 stacktrace-parser: 0.1.10 - tslib: 2.6.2 webpack: 5.89.0(webpack-cli@5.1.4) transitivePeerDependencies: - encoding @@ -11257,43 +11358,40 @@ packages: transitivePeerDependencies: - supports-color - /@sentry/node@7.74.1: - resolution: {integrity: sha512-aMUQ2LFZF64FBr+cgjAqjT4OkpYBIC9lyWI8QqjEHqNho5+LGu18/iVrJPD4fgs4UhGdCuAiQjpC36MbmnIDZA==} + /@sentry/node@7.75.1: + resolution: {integrity: sha512-E174NbP3j7OIqQQYPtpMGz1FfL/KE5PeGnhoACyMIk0D5MGB7Ia7Y9+nYfHB7+EOJPV2Ob6BYlhemX/MxPrYWg==} engines: {node: '>=8'} dependencies: - '@sentry-internal/tracing': 7.74.1 - '@sentry/core': 7.74.1 - '@sentry/types': 7.74.1 - '@sentry/utils': 7.74.1 - cookie: 0.5.0 + '@sentry-internal/tracing': 7.75.1 + '@sentry/core': 7.75.1 + '@sentry/types': 7.75.1 + '@sentry/utils': 7.75.1 https-proxy-agent: 5.0.1 - lru_map: 0.3.3 - tslib: 2.6.2 transitivePeerDependencies: - supports-color dev: false - /@sentry/react@7.74.1(react@18.2.0): - resolution: {integrity: sha512-16oTsNi2hl/S5AL/e5bo9DQZDwXPkX0nC8ajrpU0z2pH4cwjQZUZt/9Xq1+MKqDIEZkqDcMwpTmBptOvy1Pvkw==} + /@sentry/react@7.75.1(react@18.2.0): + resolution: {integrity: sha512-5zFcIor8vwQa13VRwk7yDE8U7uspj0eKpsjOcYcfSvDkiL7LW0sA6rXxvO3jwd1AKaB3EAfr1F4oIdEz8aRIkA==} engines: {node: '>=8'} peerDependencies: react: 15.x || 16.x || 17.x || 18.x dependencies: - '@sentry/browser': 7.74.1 - '@sentry/types': 7.74.1 - '@sentry/utils': 7.74.1 + '@sentry/browser': 7.75.1 + '@sentry/types': 7.75.1 + '@sentry/utils': 7.75.1 hoist-non-react-statics: 3.3.2 react: 18.2.0 - tslib: 2.6.2 dev: false - /@sentry/replay@7.74.1: - resolution: {integrity: sha512-qmbOl+jYdyhoHFbPp9WemKx8UojID5hVmuVLxNIP0ANqAwmE9OQEK9YFg2cf7L/TpKb1tqz0qLgi5MYIdcdpgQ==} + /@sentry/replay@7.75.1: + resolution: {integrity: sha512-MKQTDWNYs9QXCJ+irGX5gu8Kxdk/Ds5puhILy8+DnCoXgXuPFRMGob1Sxt8qXmbQmcGeogsx221MNTselsRS6g==} engines: {node: '>=12'} dependencies: - '@sentry/core': 7.74.1 - '@sentry/types': 7.74.1 - '@sentry/utils': 7.74.1 + '@sentry-internal/tracing': 7.75.1 + '@sentry/core': 7.75.1 + '@sentry/types': 7.75.1 + '@sentry/utils': 7.75.1 dev: false /@sentry/tracing@5.30.0: @@ -11310,8 +11408,8 @@ packages: resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} engines: {node: '>=6'} - /@sentry/types@7.74.1: - resolution: {integrity: sha512-2jIuPc+YKvXqZETwr2E8VYnsH1zsSUR/wkIvg1uTVeVNyoowJv+YsOtCdeGyL2AwiotUBSPKu7O1Lz0kq5rMOQ==} + /@sentry/types@7.75.1: + resolution: {integrity: sha512-km+ygqgMDaFfTrbQwdhrptFqx0Oq15jZABqIoIpbaOCkCAMm+tyCqrFS8dTfaq5wpCktqWOy2qU/DOpppO99Cg==} engines: {node: '>=8'} dev: false @@ -11322,22 +11420,20 @@ packages: '@sentry/types': 5.30.0 tslib: 1.14.1 - /@sentry/utils@7.74.1: - resolution: {integrity: sha512-qUsqufuHYcy5gFhLZslLxA5kcEOkkODITXW3c7D+x+8iP/AJqa8v8CeUCVNS7RetHCuIeWAbbTClC4c411EwQg==} + /@sentry/utils@7.75.1: + resolution: {integrity: sha512-QzW2eRjY20epD//9/tQ0FTNwdAL6XZi+LyJNUQIeK3NMnc5NgHrgpxId87gmFq8cNx47utH1Blub8RuMbKqiwQ==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.74.1 - tslib: 2.6.2 + '@sentry/types': 7.75.1 dev: false - /@sentry/vercel-edge@7.74.1: - resolution: {integrity: sha512-E2lTfEtDFSh57EkjVe4EcgcdjOM8UvfZVsmANBqG4bnwRKrNX9GouClzKU2Ckd5vQnOiCH9r8x2aJ/dTqyBswQ==} + /@sentry/vercel-edge@7.75.1: + resolution: {integrity: sha512-TCiObqegXdWkObf0YUDTvAPgGS5rOpRtZKQmjJ03ZahwrSMZTWESvlKo1V/5JhgfZSRWJTvDnJAtomteopT5/A==} engines: {node: '>=8'} dependencies: - '@sentry/core': 7.74.1 - '@sentry/types': 7.74.1 - '@sentry/utils': 7.74.1 - tslib: 2.6.2 + '@sentry/core': 7.75.1 + '@sentry/types': 7.75.1 + '@sentry/utils': 7.75.1 dev: false /@sentry/webpack-plugin@1.20.0: @@ -11606,8 +11702,8 @@ packages: '@supabase/node-fetch': 2.6.14 dev: false - /@supabase/realtime-js@2.8.1: - resolution: {integrity: sha512-bka5U4OeoKMdorGMPjdF30cl8n8nbhn+I9H4iySKzbN45W6AGxi7xoODnxdq/QwaDGtVyTMVbU+GVWre0QCdtw==} + /@supabase/realtime-js@2.8.4: + resolution: {integrity: sha512-5C9slLTGikHnYmAnIBOaPogAgbcNY68vnIyE6GpqIKjHElVb6LIi4clwNcjHSj4z6szuvvzj8T/+ePEgGEGekw==} dependencies: '@supabase/node-fetch': 2.6.14 '@types/phoenix': 1.6.3 @@ -11623,14 +11719,14 @@ packages: '@supabase/node-fetch': 2.6.14 dev: false - /@supabase/supabase-js@2.38.2: - resolution: {integrity: sha512-yOCi94oO5WVUBhQ890BvtT7J3p8spP47PMhn22YldIcDLEQWE6N6X2JzfWCLHktXw+oCYUJfQBuqYhyLHAKb0w==} + /@supabase/supabase-js@2.38.3: + resolution: {integrity: sha512-qIQxXZJN42iM41VChBo3kmGNyRhM0LOk27fkTX8A4tHnWxt0zmxMGFKVCX7Qnrz8zttiJkcym/BZreM/F9k0FQ==} dependencies: '@supabase/functions-js': 2.1.5 '@supabase/gotrue-js': 2.57.0 '@supabase/node-fetch': 2.6.14 '@supabase/postgrest-js': 1.8.5 - '@supabase/realtime-js': 2.8.1 + '@supabase/realtime-js': 2.8.4 '@supabase/storage-js': 2.5.4 transitivePeerDependencies: - supports-color @@ -11800,7 +11896,7 @@ packages: engines: {node: '>=14'} hasBin: true dependencies: - '@cypress/code-coverage': 3.12.5(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(cypress@12.17.4)(webpack@5.89.0) + '@cypress/code-coverage': 3.12.6(@babel/core@7.23.2)(@babel/preset-env@7.23.2)(babel-loader@9.1.3)(cypress@12.17.4)(webpack@5.89.0) '@cypress/webpack-dev-server': 3.6.1(debug@4.3.4)(webpack@5.89.0) '@drptbl/gremlins.js': 2.2.1 '@foundry-rs/easy-foundryup': 0.1.3 @@ -12027,7 +12123,7 @@ packages: '@babel/parser': 7.18.9 '@babel/traverse': 7.17.3 '@babel/types': 7.17.0 - '@vue/compiler-sfc': 3.3.6 + '@vue/compiler-sfc': 3.3.7 javascript-natural-sort: 0.7.1 lodash: 4.17.21 prettier: 2.8.8 @@ -12214,29 +12310,29 @@ packages: /@types/better-sqlite3@7.6.6: resolution: {integrity: sha512-nuFAptzt0hZYBvyLzKQCbuCCK+RN9PHH4ezar5EJLIg2qpVhwQ/uLvLO/K8A9O7N8DafawgFupiyXQSs0U48Ng==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: true /@types/bn.js@4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/bn.js@5.1.3: resolution: {integrity: sha512-wT1B4iIO82ecXkdN6waCK8Ou7E71WU+mP1osDA5Q8c6Ur+ozU2vIKUIhSpUr6uE5L2YHocKS1Z2jG2fBC1YVeg==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/body-parser@1.19.4: resolution: {integrity: sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==} dependencies: '@types/connect': 3.4.37 - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/bonjour@3.5.12: resolution: {integrity: sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/chai-as-promised@7.1.7: resolution: {integrity: sha512-APucaP5rlmTRYKtRA6FE5QPP87x76ejw5t5guRJ4y5OgMnwtsvigw7HHhKZlx2MGXLeZd6R/GNZR/IqDHcbtQw==} @@ -12257,25 +12353,25 @@ packages: /@types/cli-progress@3.11.4: resolution: {integrity: sha512-yufTxeeNCZuEIxx2uebK8lpSAsJM4lvzakm/VxzYhDtqhXCzwH9jpn7nPCxzrROuEbLATqhFq4MIPoG0tlrsvw==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: true /@types/concat-stream@1.6.1: resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: true /@types/connect-history-api-fallback@1.5.2: resolution: {integrity: sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==} dependencies: '@types/express-serve-static-core': 4.17.39 - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/connect@3.4.37: resolution: {integrity: sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/cookie@0.4.1: resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} @@ -12289,7 +12385,7 @@ packages: /@types/dns-packet@5.6.2: resolution: {integrity: sha512-vgUZ0ilYvpnTDx7tBmmAUn1HsyzK3huAtulHaDbBBCW5UdaDrEei5XJjWHnD4s8r9/MSL1hJ8s+nvJdcvNKgMA==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: false /@types/eslint-scope@3.7.6: @@ -12310,7 +12406,7 @@ packages: /@types/express-serve-static-core@4.17.39: resolution: {integrity: sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 '@types/qs': 6.9.9 '@types/range-parser': 1.2.6 '@types/send': 0.17.3 @@ -12326,20 +12422,20 @@ packages: /@types/form-data@0.0.33: resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: true /@types/glob@7.2.0: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: true /@types/graceful-fs@4.1.8: resolution: {integrity: sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/hast@2.3.7: resolution: {integrity: sha512-EVLigw5zInURhzfXUM65eixfadfsHKomGKUakToXo84t8gGIJuTcD2xooM2See7GyQ7DRtYjhCHnSUQez8JaLw==} @@ -12353,7 +12449,7 @@ packages: /@types/hoist-non-react-statics@3.3.4: resolution: {integrity: sha512-ZchYkbieA+7tnxwX/SCBySx9WwvWR8TaP5tb2jRAzwvLb/rWchGw3v0w3pqUbUvj0GCwW2Xz/AVPSk6kUGctXQ==} dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 hoist-non-react-statics: 3.3.2 dev: false @@ -12370,7 +12466,7 @@ packages: /@types/http-proxy@1.17.13: resolution: {integrity: sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/istanbul-lib-coverage@2.0.5: resolution: {integrity: sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==} @@ -12403,7 +12499,7 @@ packages: /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 '@types/tough-cookie': 4.0.4 parse5: 7.1.2 dev: true @@ -12413,13 +12509,12 @@ packages: /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - requiresBuild: true dev: true /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/level-errors@3.0.1: resolution: {integrity: sha512-eFJZWaOUhgjSqgEsPKJZrqXS9aEDUQh/5F9saFhhkR5uEVKlYb4GSG8XyoVC7APklcQKPGDVenTointTZBGIQg==} @@ -12430,7 +12525,7 @@ packages: dependencies: '@types/abstract-leveldown': 7.2.4 '@types/level-errors': 3.0.1 - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: true /@types/lodash@4.14.200: @@ -12467,7 +12562,7 @@ packages: /@types/mkdirp@0.5.2: resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: true /@types/mocha@9.1.0: @@ -12481,13 +12576,13 @@ packages: resolution: {integrity: sha512-2SZ079yRhuhDn5BssqkQGp07vErjm3PD8S/JAlduWXacZ8SVHF0q6R2m0PwjjgTDU1vE3kibNPlmnr1iKbP/Sw==} dependencies: '@types/dns-packet': 5.6.2 - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: false /@types/node-fetch@2.6.7: resolution: {integrity: sha512-lX17GZVpJ/fuCjguZ5b3TjEbSENxmEk1B2z02yoXSK9WMEWRivhdSY73wWMn6bpcCDAOh6qAdktpKHIlkDk2lg==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 form-data: 4.0.0 dev: true @@ -12510,8 +12605,10 @@ packages: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} dev: false - /@types/node@18.18.6: - resolution: {integrity: sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==} + /@types/node@18.18.7: + resolution: {integrity: sha512-bw+lEsxis6eqJYW8Ql6+yTqkE6RuFtsQPSe5JxXbqYRFQEER5aJA9a5UH9igqDWm3X4iLHIKOHlnAXLM4mi7uQ==} + dependencies: + undici-types: 5.26.5 /@types/node@20.5.1: resolution: {integrity: sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==} @@ -12527,7 +12624,7 @@ packages: /@types/papaparse@5.3.10: resolution: {integrity: sha512-mS1Fta/xJ9EDYmAvpeWzcV9Gr0cOl1ClpW7di9+wSUNDIDO55tBtyXg97O7K+Syrd9rDEmuejM2iqmJIJ1SO5g==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: true /@types/parse-json@4.0.1: @@ -12540,7 +12637,7 @@ packages: /@types/pbkdf2@3.1.1: resolution: {integrity: sha512-4HCoGwR3221nOc7G0Z/6KgTNGgaaFGkbGrtUJsB+zlKX2LBVjFHHIUkieMBgHHXgBH5Gq6dZHJKdBYdtlhBQvw==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/phoenix@1.6.3: resolution: {integrity: sha512-D8TtchWVnU2ZdPVDY6tBJuz8MUDmCNVduilZTrf0Gn/u5I/uZEXOsaL4Gs4F0j43cysHsU/4h7eqAKc+SF2boQ==} @@ -12561,37 +12658,37 @@ packages: /@types/react-dom@18.2.14: resolution: {integrity: sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==} dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 dev: true /@types/react-router-config@5.0.9: resolution: {integrity: sha512-a7zOj9yVUtM3Ns5stoseQAAsmppNxZpXDv6tZiFV5qlRmV4W96u53on1vApBX1eRSc8mrFOiB54Hc0Pk1J8GFg==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.31 + '@types/react': 18.2.33 '@types/react-router': 5.1.20 /@types/react-router-dom@5.3.3: resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.31 + '@types/react': 18.2.33 '@types/react-router': 5.1.20 /@types/react-router@5.1.20: resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.31 + '@types/react': 18.2.33 /@types/react-transition-group@4.4.8: resolution: {integrity: sha512-QmQ22q+Pb+HQSn04NL3HtrqHwYMf4h3QKArOy5F8U5nEVMaihBs3SR10WiOM1iwPz5jIo8x/u11al+iEGZZrvg==} dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 dev: false - /@types/react@18.2.31: - resolution: {integrity: sha512-c2UnPv548q+5DFh03y8lEDeMfDwBn9G3dRwfkrxQMo/dOtRHUUO57k6pHvBIfH/VF4Nh+98mZ5aaSe+2echD5g==} + /@types/react@18.2.33: + resolution: {integrity: sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==} dependencies: '@types/prop-types': 15.7.9 '@types/scheduler': 0.16.5 @@ -12600,7 +12697,7 @@ packages: /@types/readable-stream@2.3.15: resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 safe-buffer: 5.1.2 /@types/resolve@1.20.2: @@ -12610,7 +12707,7 @@ packages: /@types/responselike@1.0.2: resolution: {integrity: sha512-/4YQT5Kp6HxUDb4yhRkm0bJ7TbjvTddqX7PZ5hz6qV3pxSo72f/6YPRo+Mu2DU307tm9IioO69l7uAwn5XNcFA==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/retry@0.12.0: resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} @@ -12622,7 +12719,7 @@ packages: /@types/sax@1.2.6: resolution: {integrity: sha512-A1mpYCYu1aHFayy8XKN57ebXeAbh9oQIZ1wXcno6b1ESUAfMBDMx7mf/QGlYwcMRaFryh9YBuH03i/3FlPGDkQ==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: false /@types/scheduler@0.16.5: @@ -12631,7 +12728,7 @@ packages: /@types/secp256k1@4.0.5: resolution: {integrity: sha512-aIonTBMErtE3T9MxDvTZRzcrT/mCqpEZBw3CCY/i+oG9n57N/+7obBkhFgavUAIrX21bU0LHg1XRgtaLdelBhA==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/seedrandom@3.0.1: resolution: {integrity: sha512-giB9gzDeiCeloIXDgzFBCgjj1k4WxcDrZtGl6h1IqmUPlxF+Nx8Ve+96QCyDZ/HseB/uvDsKbpib9hU5cU53pw==} @@ -12645,7 +12742,7 @@ packages: resolution: {integrity: sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==} dependencies: '@types/mime': 1.3.4 - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/serve-index@1.9.3: resolution: {integrity: sha512-4KG+yMEuvDPRrYq5fyVm/I2uqAJSAwZK9VSa+Zf+zUq9/oxSSvy3kkIqyL+jjStv6UCVi8/Aho0NHtB1Fwosrg==} @@ -12657,12 +12754,12 @@ packages: dependencies: '@types/http-errors': 2.0.3 '@types/mime': 3.0.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/set-cookie-parser@2.4.5: resolution: {integrity: sha512-ZPmztaAQ4rbnW/WTUnT1dwSENQo4bjGqxCSeyK+gZxmd+zJl/QAeF6dpEXcS5UEJX22HwiggFSaY8nE1nRmkbg==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: true /@types/sinon@10.0.20: @@ -12686,7 +12783,7 @@ packages: /@types/sockjs@0.3.35: resolution: {integrity: sha512-tIF57KB+ZvOBpAQwSaACfEu7htponHXaFzP7RfKYgsOS0NoYnn+9+jzp7bbq4fWerizI3dTB4NfAZoyeQKWJLw==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/source-list-map@0.1.4: resolution: {integrity: sha512-Kdfm7Sk5VX8dFW7Vbp18+fmAatBewzBILa1raHYxrGEFXT0jNl9x3LWfuW7bTbjEKFNey9Dfkj/UzT6z/NvRlg==} @@ -12737,7 +12834,7 @@ packages: /@types/webpack-sources@3.2.2: resolution: {integrity: sha512-acCzhuVe+UJy8abiSFQWXELhhNMZjQjQKpLNEi1pKGgKXZj0ul614ATcx4kkhunPost6Xw+aCq8y8cn1/WwAiA==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 '@types/source-list-map': 0.1.4 source-map: 0.7.4 dev: true @@ -12745,7 +12842,7 @@ packages: /@types/webpack@4.41.35: resolution: {integrity: sha512-XRC6HLGHtNfN8/xWeu1YUQV1GSE+28q8lSqvcJ+0xt/zW9Wmn4j9pCSvaXPyRlCKrl5OuqECQNEJUy2vo8oWqg==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 '@types/tapable': 1.0.10 '@types/uglify-js': 3.17.3 '@types/webpack-sources': 3.2.2 @@ -12756,18 +12853,18 @@ packages: /@types/websocket@1.0.8: resolution: {integrity: sha512-wvkOpWApbuxVfHhSQ1XrjVN4363vsfLJwEo4AboIZk0g1vJA5nmLp8GXUHuIdf4/Fe7+/V0Efe2HvWiLqHtlqw==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: false /@types/ws@7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/ws@8.5.8: resolution: {integrity: sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg==} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /@types/yargs-parser@21.0.2: resolution: {integrity: sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==} @@ -12791,7 +12888,7 @@ packages: resolution: {integrity: sha512-Km7XAtUIduROw7QPgvcft0lIupeG8a8rdKL8RiSyKvlE7dYY31fEn41HVuQsRFDuROA8tA4K2UVL+WdfFmErBA==} requiresBuild: true dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 dev: true optional: true @@ -12806,7 +12903,7 @@ packages: typescript: optional: true dependencies: - '@eslint-community/regexpp': 4.9.1 + '@eslint-community/regexpp': 4.10.0 '@typescript-eslint/parser': 5.62.0(eslint@8.19.0)(typescript@5.1.6) '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/type-utils': 5.62.0(eslint@8.19.0)(typescript@5.1.6) @@ -12834,7 +12931,7 @@ packages: typescript: optional: true dependencies: - '@eslint-community/regexpp': 4.9.1 + '@eslint-community/regexpp': 4.10.0 '@typescript-eslint/parser': 5.62.0(eslint@8.52.0)(typescript@4.9.5) '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/type-utils': 5.62.0(eslint@8.52.0)(typescript@4.9.5) @@ -13120,56 +13217,56 @@ packages: pretty-format: 27.5.1 dev: true - /@vue/compiler-core@3.3.6: - resolution: {integrity: sha512-2JNjemwaNwf+MkkatATVZi7oAH1Hx0B04DdPH3ZoZ8vKC1xZVP7nl4HIsk8XYd3r+/52sqqoz9TWzYc3yE9dqA==} + /@vue/compiler-core@3.3.7: + resolution: {integrity: sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ==} dependencies: '@babel/parser': 7.23.0 - '@vue/shared': 3.3.6 + '@vue/shared': 3.3.7 estree-walker: 2.0.2 source-map-js: 1.0.2 dev: true - /@vue/compiler-dom@3.3.6: - resolution: {integrity: sha512-1MxXcJYMHiTPexjLAJUkNs/Tw2eDf2tY3a0rL+LfuWyiKN2s6jvSwywH3PWD8bKICjfebX3GWx2Os8jkRDq3Ng==} + /@vue/compiler-dom@3.3.7: + resolution: {integrity: sha512-0LwkyJjnUPssXv/d1vNJ0PKfBlDoQs7n81CbO6Q0zdL7H1EzqYRrTVXDqdBVqro0aJjo/FOa1qBAPVI4PGSHBw==} dependencies: - '@vue/compiler-core': 3.3.6 - '@vue/shared': 3.3.6 + '@vue/compiler-core': 3.3.7 + '@vue/shared': 3.3.7 dev: true - /@vue/compiler-sfc@3.3.6: - resolution: {integrity: sha512-/Kms6du2h1VrXFreuZmlvQej8B1zenBqIohP0690IUBkJjsFvJxY0crcvVRJ0UhMgSR9dewB+khdR1DfbpArJA==} + /@vue/compiler-sfc@3.3.7: + resolution: {integrity: sha512-7pfldWy/J75U/ZyYIXRVqvLRw3vmfxDo2YLMwVtWVNew8Sm8d6wodM+OYFq4ll/UxfqVr0XKiVwti32PCrruAw==} dependencies: '@babel/parser': 7.23.0 - '@vue/compiler-core': 3.3.6 - '@vue/compiler-dom': 3.3.6 - '@vue/compiler-ssr': 3.3.6 - '@vue/reactivity-transform': 3.3.6 - '@vue/shared': 3.3.6 + '@vue/compiler-core': 3.3.7 + '@vue/compiler-dom': 3.3.7 + '@vue/compiler-ssr': 3.3.7 + '@vue/reactivity-transform': 3.3.7 + '@vue/shared': 3.3.7 estree-walker: 2.0.2 magic-string: 0.30.5 postcss: 8.4.31 source-map-js: 1.0.2 dev: true - /@vue/compiler-ssr@3.3.6: - resolution: {integrity: sha512-QTIHAfDCHhjXlYGkUg5KH7YwYtdUM1vcFl/FxFDlD6d0nXAmnjizka3HITp8DGudzHndv2PjKVS44vqqy0vP4w==} + /@vue/compiler-ssr@3.3.7: + resolution: {integrity: sha512-TxOfNVVeH3zgBc82kcUv+emNHo+vKnlRrkv8YvQU5+Y5LJGJwSNzcmLUoxD/dNzv0bhQ/F0s+InlgV0NrApJZg==} dependencies: - '@vue/compiler-dom': 3.3.6 - '@vue/shared': 3.3.6 + '@vue/compiler-dom': 3.3.7 + '@vue/shared': 3.3.7 dev: true - /@vue/reactivity-transform@3.3.6: - resolution: {integrity: sha512-RlJl4dHfeO7EuzU1iJOsrlqWyJfHTkJbvYz/IOJWqu8dlCNWtxWX377WI0VsbAgBizjwD+3ZjdnvSyyFW1YVng==} + /@vue/reactivity-transform@3.3.7: + resolution: {integrity: sha512-APhRmLVbgE1VPGtoLQoWBJEaQk4V8JUsqrQihImVqKT+8U6Qi3t5ATcg4Y9wGAPb3kIhetpufyZ1RhwbZCIdDA==} dependencies: '@babel/parser': 7.23.0 - '@vue/compiler-core': 3.3.6 - '@vue/shared': 3.3.6 + '@vue/compiler-core': 3.3.7 + '@vue/shared': 3.3.7 estree-walker: 2.0.2 magic-string: 0.30.5 dev: true - /@vue/shared@3.3.6: - resolution: {integrity: sha512-Xno5pEqg8SVhomD0kTSmfh30ZEmV/+jZtyh39q6QflrjdJCXah5lrnOLi9KB6a5k5aAHXMXjoMnxlzUkCNfWLQ==} + /@vue/shared@3.3.7: + resolution: {integrity: sha512-N/tbkINRUDExgcPTBvxNkvHGu504k8lzlNQRITVnm6YjOjwa4r0nnbd4Jb01sNpur5hAllyRJzSK5PvB9PPwRg==} dev: true /@wagmi/chains@1.0.0(typescript@5.1.6): @@ -13230,7 +13327,42 @@ packages: - zod dev: false - /@wagmi/core@1.3.8(@types/react@18.2.31)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): + /@wagmi/connectors@2.7.0(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): + resolution: {integrity: sha512-1KOL0HTJl5kzSC/YdKwFwiokr6poUQn1V/tcT0TpG3iH2x0lSM7FTkvCjVVY/6lKzTXrLlo9y2aE7AsOPnkvqg==} + peerDependencies: + '@wagmi/chains': '>=1.7.0' + typescript: '>=5.0.4' + viem: '>=0.3.35' + peerDependenciesMeta: + '@wagmi/chains': + optional: true + typescript: + optional: true + dependencies: + '@coinbase/wallet-sdk': 3.7.2 + '@ledgerhq/connect-kit-loader': 1.1.2 + '@safe-global/safe-apps-provider': 0.17.1(typescript@5.1.6)(zod@3.22.4) + '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.1.6)(zod@3.22.4) + '@walletconnect/ethereum-provider': 2.9.2(@walletconnect/modal@2.6.1) + '@walletconnect/legacy-provider': 2.0.0 + '@walletconnect/modal': 2.6.1(react@18.2.0) + '@walletconnect/utils': 2.9.2 + abitype: 0.8.7(typescript@5.1.6)(zod@3.22.4) + eventemitter3: 4.0.7 + typescript: 5.1.6 + viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - bufferutil + - encoding + - lokijs + - react + - supports-color + - utf-8-validate + - zod + dev: false + + /@wagmi/core@1.3.8(@types/react@18.2.33)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): resolution: {integrity: sha512-OYSxikoMizqVnpSkFTwGE7PwFaz2k0PXteSiI0W2Mtk4j4sZzRFdP+9AWeDB6AYm0yU3WvgN1IATx0EEBKUe3w==} peerDependencies: typescript: '>=5.0.4' @@ -13245,7 +13377,7 @@ packages: eventemitter3: 4.0.7 typescript: 5.1.6 viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) - zustand: 4.4.4(@types/react@18.2.31)(react@18.2.0) + zustand: 4.4.4(@types/react@18.2.33)(react@18.2.0) transitivePeerDependencies: - '@react-native-async-storage/async-storage' - '@types/react' @@ -13285,6 +13417,32 @@ packages: - utf-8-validate dev: false + /@walletconnect/core@2.9.2: + resolution: {integrity: sha512-VARMPAx8sIgodeyngDHbealP3B621PQqjqKsByFUTOep8ZI1/R/20zU+cmq6j9RCrL+kLKZcrZqeVzs8Z7OlqQ==} + dependencies: + '@walletconnect/heartbeat': 1.2.1 + '@walletconnect/jsonrpc-provider': 1.0.13 + '@walletconnect/jsonrpc-types': 1.0.3 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/jsonrpc-ws-connection': 1.0.13 + '@walletconnect/keyvaluestorage': 1.0.2 + '@walletconnect/logger': 2.0.1 + '@walletconnect/relay-api': 1.0.9 + '@walletconnect/relay-auth': 1.0.4 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.9.2 + '@walletconnect/utils': 2.9.2 + events: 3.3.0 + lodash.isequal: 4.5.0 + uint8arrays: 3.1.1 + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - bufferutil + - lokijs + - utf-8-validate + dev: false + /@walletconnect/crypto@1.0.3: resolution: {integrity: sha512-+2jdORD7XQs76I2Odgr3wwrtyuLUXD/kprNVsjWRhhhdO9Mt6WqVzOPu0/t7OHSmgal8k7SoBQzUc5hu/8zL/g==} dependencies: @@ -13336,6 +13494,32 @@ packages: - utf-8-validate dev: false + /@walletconnect/ethereum-provider@2.9.2(@walletconnect/modal@2.6.1): + resolution: {integrity: sha512-eO1dkhZffV1g7vpG19XUJTw09M/bwGUwwhy1mJ3AOPbOSbMPvwiCuRz2Kbtm1g9B0Jv15Dl+TvJ9vTgYF8zoZg==} + peerDependencies: + '@walletconnect/modal': '>=2' + peerDependenciesMeta: + '@walletconnect/modal': + optional: true + dependencies: + '@walletconnect/jsonrpc-http-connection': 1.0.7 + '@walletconnect/jsonrpc-provider': 1.0.13 + '@walletconnect/jsonrpc-types': 1.0.3 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/modal': 2.6.1(react@18.2.0) + '@walletconnect/sign-client': 2.9.2 + '@walletconnect/types': 2.9.2 + '@walletconnect/universal-provider': 2.9.2 + '@walletconnect/utils': 2.9.2 + events: 3.3.0 + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - bufferutil + - encoding + - lokijs + - utf-8-validate + dev: false + /@walletconnect/events@1.0.1: resolution: {integrity: sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==} dependencies: @@ -13398,6 +13582,19 @@ packages: - utf-8-validate dev: false + /@walletconnect/jsonrpc-ws-connection@1.0.13: + resolution: {integrity: sha512-mfOM7uFH4lGtQxG+XklYuFBj6dwVvseTt5/ahOkkmpcAEgz2umuzu7fTR+h5EmjQBdrmYyEBOWADbeaFNxdySg==} + dependencies: + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/safe-json': 1.0.2 + events: 3.3.0 + tslib: 1.14.1 + ws: 7.5.9 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + /@walletconnect/keyvaluestorage@1.0.2: resolution: {integrity: sha512-U/nNG+VLWoPFdwwKx0oliT4ziKQCEoQ27L5Hhw8YOFGA2Po9A9pULUYNWhDgHkrb0gYDNt//X7wABcEWWBd3FQ==} peerDependencies: @@ -13486,6 +13683,14 @@ packages: - react dev: false + /@walletconnect/modal-core@2.6.1(react@18.2.0): + resolution: {integrity: sha512-f2hYlJ5pwzGvjyaZ6BoGR5uiMgXzWXt6w6ktt1N8lmY6PiYp8whZgqx2hTxVWwVlsGnaIfh6UHp1hGnANx0eTQ==} + dependencies: + valtio: 1.11.0(react@18.2.0) + transitivePeerDependencies: + - react + dev: false + /@walletconnect/modal-ui@2.5.9(react@18.2.0): resolution: {integrity: sha512-nfBaAT9Ls7RZTBBgAq+Nt/3AoUcinIJ9bcq5UHXTV3lOPu/qCKmUC/0HY3GvUK8ykabUAsjr0OAGmcqkB91qug==} dependencies: @@ -13497,6 +13702,17 @@ packages: - react dev: false + /@walletconnect/modal-ui@2.6.1(react@18.2.0): + resolution: {integrity: sha512-RFUOwDAMijSK8B7W3+KoLKaa1l+KEUG0LCrtHqaB0H0cLnhEGdLR+kdTdygw+W8+yYZbkM5tXBm7MlFbcuyitA==} + dependencies: + '@walletconnect/modal-core': 2.6.1(react@18.2.0) + lit: 2.7.6 + motion: 10.16.2 + qrcode: 1.5.3 + transitivePeerDependencies: + - react + dev: false + /@walletconnect/modal@2.5.9(react@18.2.0): resolution: {integrity: sha512-Zs2RvPwbBNRdBhb50FuJCxi3FJltt1KSpI7odjU/x9GTpTOcSOkmR66PBCy2JvNA0+ztnS1Xs0LVEr3lu7/Jzw==} dependencies: @@ -13506,6 +13722,15 @@ packages: - react dev: false + /@walletconnect/modal@2.6.1(react@18.2.0): + resolution: {integrity: sha512-G84tSzdPKAFk1zimgV7JzIUFT5olZUVtI3GcOk77OeLYjlMfnDT23RVRHm5EyCrjkptnvpD0wQScXePOFd2Xcw==} + dependencies: + '@walletconnect/modal-core': 2.6.1(react@18.2.0) + '@walletconnect/modal-ui': 2.6.1(react@18.2.0) + transitivePeerDependencies: + - react + dev: false + /@walletconnect/randombytes@1.0.3: resolution: {integrity: sha512-35lpzxcHFbTN3ABefC9W+uBpNZl1GC4Wpx0ed30gibfO/y9oLdy1NznbV96HARQKSBV9J9M/rrtIvf6a23jfYw==} dependencies: @@ -13558,6 +13783,25 @@ packages: - utf-8-validate dev: false + /@walletconnect/sign-client@2.9.2: + resolution: {integrity: sha512-anRwnXKlR08lYllFMEarS01hp1gr6Q9XUgvacr749hoaC/AwGVlxYFdM8+MyYr3ozlA+2i599kjbK/mAebqdXg==} + dependencies: + '@walletconnect/core': 2.9.2 + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.1 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.0.1 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.9.2 + '@walletconnect/utils': 2.9.2 + events: 3.3.0 + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - bufferutil + - lokijs + - utf-8-validate + dev: false + /@walletconnect/time@1.0.2: resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==} dependencies: @@ -13578,6 +13822,20 @@ packages: - lokijs dev: false + /@walletconnect/types@2.9.2: + resolution: {integrity: sha512-7Rdn30amnJEEal4hk83cdwHUuxI1SWQ+K7fFFHBMqkuHLGi3tpMY6kpyfDxnUScYEZXqgRps4Jo5qQgnRqVM7A==} + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.1 + '@walletconnect/jsonrpc-types': 1.0.3 + '@walletconnect/keyvaluestorage': 1.0.2 + '@walletconnect/logger': 2.0.1 + events: 3.3.0 + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - lokijs + dev: false + /@walletconnect/universal-provider@2.9.0: resolution: {integrity: sha512-k3nkSBkF69sJJVoe17IVoPtnhp/sgaa2t+x7BvA/BKeMxE0DGdtRJdEXotTc8DBmI7o2tkq6l8+HyFBGjQ/CjQ==} dependencies: @@ -13598,6 +13856,26 @@ packages: - utf-8-validate dev: false + /@walletconnect/universal-provider@2.9.2: + resolution: {integrity: sha512-JmaolkO8D31UdRaQCHwlr8uIFUI5BYhBzqYFt54Mc6gbIa1tijGOmdyr6YhhFO70LPmS6gHIjljwOuEllmlrxw==} + dependencies: + '@walletconnect/jsonrpc-http-connection': 1.0.7 + '@walletconnect/jsonrpc-provider': 1.0.13 + '@walletconnect/jsonrpc-types': 1.0.3 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.0.1 + '@walletconnect/sign-client': 2.9.2 + '@walletconnect/types': 2.9.2 + '@walletconnect/utils': 2.9.2 + events: 3.3.0 + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - bufferutil + - encoding + - lokijs + - utf-8-validate + dev: false + /@walletconnect/utils@2.9.0: resolution: {integrity: sha512-7Tu3m6dZL84KofrNBcblsgpSqU2vdo9ImLD7zWimLXERVGNQ8smXG+gmhQYblebIBhsPzjy9N38YMC3nPlfQNw==} dependencies: @@ -13620,6 +13898,28 @@ packages: - lokijs dev: false + /@walletconnect/utils@2.9.2: + resolution: {integrity: sha512-D44hwXET/8JhhIjqljY6qxSu7xXnlPrf63UN/Qfl98vDjWlYVcDl2+JIQRxD9GPastw0S8XZXdRq59XDXLuZBg==} + dependencies: + '@stablelib/chacha20poly1305': 1.0.1 + '@stablelib/hkdf': 1.0.1 + '@stablelib/random': 1.0.2 + '@stablelib/sha256': 1.0.1 + '@stablelib/x25519': 1.0.3 + '@walletconnect/relay-api': 1.0.9 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.9.2 + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + detect-browser: 5.3.0 + query-string: 7.1.3 + uint8arrays: 3.1.1 + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - lokijs + dev: false + /@walletconnect/window-getters@1.0.1: resolution: {integrity: sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==} dependencies: @@ -13836,11 +14136,11 @@ packages: urlpattern-polyfill: 8.0.2 web-streams-polyfill: 3.2.1 - /@whatwg-node/fetch@0.9.13: - resolution: {integrity: sha512-PPtMwhjtS96XROnSpowCQM85gCUG2m7AXZFw0PZlGbhzx2GK7f2iOXilfgIJ0uSlCuuGbOIzfouISkA7C4FJOw==} + /@whatwg-node/fetch@0.9.14: + resolution: {integrity: sha512-wurZC82zzZwXRDSW0OS9l141DynaJQh7Yt0FD1xZ8niX7/Et/7RoiLiltbVU1fSF1RR9z6ndEaTUQBAmddTm1w==} engines: {node: '>=16.0.0'} dependencies: - '@whatwg-node/node-fetch': 0.4.19 + '@whatwg-node/node-fetch': 0.5.0 urlpattern-polyfill: 9.0.0 /@whatwg-node/node-fetch@0.3.6: @@ -13852,8 +14152,8 @@ packages: fast-url-parser: 1.1.3 tslib: 2.6.2 - /@whatwg-node/node-fetch@0.4.19: - resolution: {integrity: sha512-AW7/m2AuweAoSXmESrYQr/KBafueScNbn2iNO0u6xFr2JZdPmYsSm5yvAXYk6yDLv+eDmSSKrf7JnFZ0CsJIdA==} + /@whatwg-node/node-fetch@0.5.0: + resolution: {integrity: sha512-q76lDAafvHNGWedNAVHrz/EyYTS8qwRLcwne8SJQdRN5P3HydxU6XROFvJfTML6KZXQX2FDdGY4/SnaNyd7M0Q==} engines: {node: '>=16.0.0'} dependencies: '@whatwg-node/events': 0.1.1 @@ -13868,23 +14168,23 @@ packages: '@whatwg-node/fetch': 0.8.8 tslib: 2.6.2 - /@whatwg-node/server@0.9.15: - resolution: {integrity: sha512-MDmw3HYfZt8hzP8Vac/LPwD8LyZFByVuO1vHPBDsOMYNf4XWv6eHbRCk4UFfLT8OMFgd+qMy/zNYc74o+3tXZg==} + /@whatwg-node/server@0.9.16: + resolution: {integrity: sha512-gktQkRyONEw2EGpx7UZaC6zNlUm21CGlqAHQXU3QC6W0zlLM5ZQNDCeD66q/nsPHDV08X2NTHlABsuAEk5rh/w==} engines: {node: '>=16.0.0'} dependencies: - '@whatwg-node/fetch': 0.9.13 + '@whatwg-node/fetch': 0.9.14 tslib: 2.6.2 dev: false - /@wry/context@0.7.3: - resolution: {integrity: sha512-Nl8WTesHp89RF803Se9X3IiHjdmLBrIvPMaJkl+rKVJAYyPsz1TEUbu89943HpvujtSJgDUx9W4vZw3K1Mr3sA==} + /@wry/context@0.7.4: + resolution: {integrity: sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==} engines: {node: '>=8'} dependencies: tslib: 2.6.2 dev: false - /@wry/equality@0.5.6: - resolution: {integrity: sha512-D46sfMTngaYlrH+OspKf8mIJETntFnf6Hsjb0V41jAXJ7Bx2kB8Rv8RCUujuVWYttFtHkUNp7g+FwxNQAr6mXA==} + /@wry/equality@0.5.7: + resolution: {integrity: sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==} engines: {node: '>=8'} dependencies: tslib: 2.6.2 @@ -14009,7 +14309,7 @@ packages: engines: {node: '>=6'} dependencies: buffer: 5.7.1 - immediate: 3.2.3 + immediate: 3.3.0 level-concat-iterator: 2.0.1 level-supports: 1.0.1 xtend: 4.0.2 @@ -14166,8 +14466,8 @@ packages: require-from-string: 2.0.2 uri-js: 4.4.1 - /algoliasearch-helper@3.14.2(algoliasearch@4.20.0): - resolution: {integrity: sha512-FjDSrjvQvJT/SKMW74nPgFpsoPUwZCzGbCqbp8HhBFfSk/OvNFxzCaCmuO0p7AWeLy1gD+muFwQEkBwcl5H4pg==} + /algoliasearch-helper@3.15.0(algoliasearch@4.20.0): + resolution: {integrity: sha512-DGUnK3TGtDQsaUE4ayF/LjSN0DGsuYThB8WBgnnDY0Wq04K6lNVruO3LfqJOgSfDiezp+Iyt8Tj4YKHi+/ivSA==} peerDependencies: algoliasearch: '>= 3.1 < 6' dependencies: @@ -14685,7 +14985,7 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.22.1 - caniuse-lite: 1.0.30001553 + caniuse-lite: 1.0.30001554 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -15377,8 +15677,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001553 - electron-to-chromium: 1.4.564 + caniuse-lite: 1.0.30001554 + electron-to-chromium: 1.4.567 node-releases: 2.0.13 update-browserslist-db: 1.0.13(browserslist@4.22.1) @@ -15472,6 +15772,11 @@ packages: dependencies: node-gyp-build: 4.6.1 + /bufio@1.2.1: + resolution: {integrity: sha512-9oR3zNdupcg/Ge2sSHQF3GX+kmvL/fTPvD0nd5AGLq8SjUYnTz+SlFjK/GXidndbZtIj+pVKXiWeR9w6e9wKCA==} + engines: {node: '>=14.0.0'} + dev: true + /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -15637,13 +15942,13 @@ packages: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} dependencies: browserslist: 4.22.1 - caniuse-lite: 1.0.30001553 + caniuse-lite: 1.0.30001554 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 dev: false - /caniuse-lite@1.0.30001553: - resolution: {integrity: sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==} + /caniuse-lite@1.0.30001554: + resolution: {integrity: sha512-A2E3U//MBwbJVzebddm1YfNp7Nud5Ip+IPn4BozBmn4KqVX7AvluoIDFWjsv5OkGnKUXQVmMSoMKLa3ScCblcQ==} /capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} @@ -15699,8 +16004,8 @@ packages: resolution: {integrity: sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==} hasBin: true - /cborg@4.0.4: - resolution: {integrity: sha512-nu+JXYskYqWN/tFWQVjL2ZYlUwK+dapqkTpruAtJkwmDv7XaTgg8PStUbO+sXfhqSWaeQ9LPSPCTrO2WZ2Bxfg==} + /cborg@4.0.5: + resolution: {integrity: sha512-q8TAjprr8pn9Fp53rOIGp/UFDdFY6os2Nq62YogPSIzczJD9M6g2b6igxMkpCiZZKJ0kn/KzDLDvG+EqBIEeCg==} hasBin: true dev: false @@ -16284,13 +16589,13 @@ packages: resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} engines: {node: ^12.20.0 || >=14} - /commitizen@4.3.0: + /commitizen@4.3.0(typescript@4.9.5): resolution: {integrity: sha512-H0iNtClNEhT0fotHvGV3E9tDejDeS04sN1veIebsKYGMuGscFaswRoYJKmT3eW85eIJAs0F28bG2+a/9wCOfPw==} engines: {node: '>= 12'} hasBin: true dependencies: cachedir: 2.3.0 - cz-conventional-changelog: 3.3.0 + cz-conventional-changelog: 3.3.0(typescript@4.9.5) dedent: 0.7.0 detect-indent: 6.1.0 find-node-modules: 2.1.3 @@ -16304,8 +16609,7 @@ packages: strip-bom: 4.0.0 strip-json-comments: 3.1.1 transitivePeerDependencies: - - '@swc/core' - - '@swc/wasm' + - typescript dev: true /common-path-prefix@3.0.0: @@ -16466,7 +16770,7 @@ packages: resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} engines: {node: '>=12.13'} dependencies: - is-what: 4.1.15 + is-what: 4.1.16 dev: false /copy-text-to-clipboard@3.2.0: @@ -16546,7 +16850,7 @@ packages: layout-base: 2.0.1 dev: false - /cosmiconfig-typescript-loader@4.4.0(@types/node@18.18.6)(cosmiconfig@8.3.6)(ts-node@10.9.1)(typescript@5.2.2): + /cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6)(ts-node@10.9.1)(typescript@4.9.5): resolution: {integrity: sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==} engines: {node: '>=v14.21.3'} peerDependencies: @@ -16555,27 +16859,27 @@ packages: ts-node: '>=10' typescript: '>=4' dependencies: - '@types/node': 18.18.6 - cosmiconfig: 8.3.6(typescript@5.2.2) - ts-node: 10.9.1(@types/node@18.18.6)(typescript@5.2.2) - typescript: 5.2.2 + '@types/node': 20.5.1 + cosmiconfig: 8.3.6(typescript@4.9.5) + ts-node: 10.9.1(@types/node@20.5.1)(typescript@4.9.5) + typescript: 4.9.5 dev: true - optional: true - /cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6)(ts-node@10.9.1)(typescript@4.9.5): - resolution: {integrity: sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==} - engines: {node: '>=v14.21.3'} + /cosmiconfig-typescript-loader@5.0.0(@types/node@18.18.7)(cosmiconfig@8.3.6)(typescript@4.9.5): + resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} + engines: {node: '>=v16'} + requiresBuild: true peerDependencies: '@types/node': '*' - cosmiconfig: '>=7' - ts-node: '>=10' + cosmiconfig: '>=8.2' typescript: '>=4' dependencies: - '@types/node': 20.5.1 + '@types/node': 18.18.7 cosmiconfig: 8.3.6(typescript@4.9.5) - ts-node: 10.9.1(@types/node@20.5.1)(typescript@4.9.5) + jiti: 1.20.0 typescript: 4.9.5 dev: true + optional: true /cosmiconfig@5.2.1: resolution: {integrity: sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==} @@ -16649,23 +16953,6 @@ packages: path-type: 4.0.0 typescript: 5.1.6 - /cosmiconfig@8.3.6(typescript@5.2.2): - resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - import-fresh: 3.3.0 - js-yaml: 4.1.0 - parse-json: 5.2.0 - path-type: 4.0.0 - typescript: 5.2.2 - dev: true - optional: true - /crc-32@1.2.2: resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} engines: {node: '>=0.8'} @@ -16690,7 +16977,7 @@ packages: safe-buffer: 5.2.1 sha.js: 2.4.11 - /create-jest@29.7.0(@types/node@18.18.6)(ts-node@10.9.1): + /create-jest@29.7.0(@types/node@18.18.7)(ts-node@10.9.1): resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -16699,7 +16986,7 @@ packages: chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) + jest-config: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -17046,21 +17333,20 @@ packages: lodash: 4.17.21 dev: false - /cz-conventional-changelog@3.3.0: + /cz-conventional-changelog@3.3.0(typescript@4.9.5): resolution: {integrity: sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==} engines: {node: '>= 10'} dependencies: chalk: 2.4.2 - commitizen: 4.3.0 + commitizen: 4.3.0(typescript@4.9.5) conventional-commit-types: 3.0.0 lodash.map: 4.6.0 longest: 2.0.1 word-wrap: 1.2.5 optionalDependencies: - '@commitlint/load': 18.0.0 + '@commitlint/load': 18.2.0(typescript@4.9.5) transitivePeerDependencies: - - '@swc/core' - - '@swc/wasm' + - typescript dev: true /d3-array@3.2.4: @@ -18072,8 +18358,8 @@ packages: pify: 4.0.1 dev: true - /dset@3.1.2: - resolution: {integrity: sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==} + /dset@3.1.3: + resolution: {integrity: sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==} engines: {node: '>=4'} /duplexer3@0.1.5: @@ -18127,8 +18413,8 @@ packages: dependencies: encoding: 0.1.13 - /electron-to-chromium@1.4.564: - resolution: {integrity: sha512-bGAx9+teIzL5I4esQwCMtiXtb78Ysc8xOKTPOvmafbJZ4SQ40kDO1ym3yRcGSkfaBtV81fGgHOgPoe6DsmpmkA==} + /electron-to-chromium@1.4.567: + resolution: {integrity: sha512-8KR114CAYQ4/r5EIEsOmOMqQ9j0MRbJZR3aXD/KFA8RuKzyoUB4XrUCg+l8RUGqTVQgKNIgTpjaG8YHRPAbX2w==} /elkjs@0.8.2: resolution: {integrity: sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==} @@ -18885,7 +19171,7 @@ packages: hasBin: true dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) - '@eslint-community/regexpp': 4.9.1 + '@eslint-community/regexpp': 4.10.0 '@eslint/eslintrc': 2.1.2 '@eslint/js': 8.52.0 '@humanwhocodes/config-array': 0.11.13 @@ -19059,6 +19345,12 @@ packages: fast-safe-stringify: 2.1.1 dev: false + /eth-rpc-errors@4.0.3: + resolution: {integrity: sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg==} + dependencies: + fast-safe-stringify: 2.1.1 + dev: false + /ethereum-bloom-filters@1.0.10: resolution: {integrity: sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==} dependencies: @@ -19231,7 +19523,7 @@ packages: resolution: {integrity: sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==} engines: {node: '>= 0.8'} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 require-like: 0.1.2 dev: false @@ -20025,7 +20317,7 @@ packages: dependencies: fetch-blob: 3.2.0 - /formik-mui-x-date-pickers@0.0.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(@mui/system@5.14.14)(@mui/x-date-pickers@5.0.20)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3): + /formik-mui-x-date-pickers@0.0.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.15)(@mui/system@5.14.15)(@mui/x-date-pickers@5.0.20)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3): resolution: {integrity: sha512-IxZsY6er+g0eNsucIDHcNs6DLaPDdG14IYx/lS2HSuKnTgV4vGEWpXyGMpkY/vGyh+W3N5U4TrBVu+7eRb5rLA==} peerDependencies: '@emotion/react': '>=11.5.0' @@ -20037,17 +20329,17 @@ packages: react: '>=17.0.2' tiny-warning: '>=1.0.3' dependencies: - '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) - '@mui/material': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) - '@mui/system': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react@18.2.0) - '@mui/x-date-pickers': 5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(@mui/system@5.14.14)(@types/react@18.2.31)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) + '@emotion/react': 11.11.1(@types/react@18.2.33)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) + '@mui/material': 5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@mui/system': 5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react@18.2.0) + '@mui/x-date-pickers': 5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.15)(@mui/system@5.14.15)(@types/react@18.2.33)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) formik: 2.4.5(react@18.2.0) react: 18.2.0 tiny-warning: 1.0.3 dev: false - /formik-mui@5.0.0-alpha.0(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.14)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3): + /formik-mui@5.0.0-alpha.0(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.15)(formik@2.4.5)(react@18.2.0)(tiny-warning@1.0.3): resolution: {integrity: sha512-tcY8B4I3N2UK9ghgVpeBWsXGMDe1y4LVKwI8GiUbLKGB86fI/CN9UMr4FuNo6kzNXvO42LFNmCxdEVzovNCyYQ==} peerDependencies: '@emotion/react': '>=11.5.0' @@ -20057,9 +20349,9 @@ packages: react: '>=17.0.2' tiny-warning: '>=1.0.3' dependencies: - '@emotion/react': 11.11.1(@types/react@18.2.31)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.31)(react@18.2.0) - '@mui/material': 5.14.14(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0) + '@emotion/react': 11.11.1(@types/react@18.2.33)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) + '@mui/material': 5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) formik: 2.4.5(react@18.2.0) react: 18.2.0 tiny-warning: 1.0.3 @@ -20784,7 +21076,7 @@ packages: '@graphql-yoga/subscription': 3.1.0 '@whatwg-node/fetch': 0.8.8 '@whatwg-node/server': 0.7.7 - dset: 3.1.2 + dset: 3.1.3 graphql: 16.8.1 lru-cache: 7.18.3 tslib: 2.6.2 @@ -20801,9 +21093,9 @@ packages: '@graphql-tools/utils': 10.0.7(graphql@16.8.1) '@graphql-yoga/logger': 2.0.0 '@graphql-yoga/subscription': 5.0.0 - '@whatwg-node/fetch': 0.9.13 - '@whatwg-node/server': 0.9.15 - dset: 3.1.2 + '@whatwg-node/fetch': 0.9.14 + '@whatwg-node/server': 0.9.16 + dset: 3.1.3 graphql: 16.8.1 lru-cache: 10.0.1 tslib: 2.6.2 @@ -20975,7 +21267,7 @@ packages: solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 - ts-node: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) tsort: 0.0.1 typescript: 4.9.5 undici: 5.26.5 @@ -22011,7 +22303,7 @@ packages: '@libp2p/interface-peer-info': 1.0.10 '@libp2p/interface-pubsub': 3.0.7 '@multiformats/multiaddr': 11.6.1 - '@types/node': 18.18.6 + '@types/node': 18.18.7 interface-datastore: 7.0.4 ipfs-unixfs: 8.0.0 multiformats: 10.0.3 @@ -22959,8 +23251,8 @@ packages: get-intrinsic: 1.2.2 dev: true - /is-what@4.1.15: - resolution: {integrity: sha512-uKua1wfy3Yt+YqsD6mTUEa2zSi3G1oPlqTflgaPJ7z63vUGN5pxFpnQfeSLMFnJDEsdvOtkp1rUWkYjB4YfhgA==} + /is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} dev: false @@ -23552,7 +23844,7 @@ packages: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -23572,7 +23864,7 @@ packages: - babel-plugin-macros - supports-color - /jest-cli@29.7.0(@types/node@18.18.6)(ts-node@10.9.1): + /jest-cli@29.7.0(@types/node@18.18.7)(ts-node@10.9.1): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -23586,10 +23878,10 @@ packages: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) + create-jest: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) + jest-config: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -23599,7 +23891,7 @@ packages: - supports-color - ts-node - /jest-config@29.7.0(@types/node@18.18.6)(ts-node@10.9.1): + /jest-config@29.7.0(@types/node@18.18.7)(ts-node@10.9.1): resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -23614,7 +23906,7 @@ packages: '@babel/core': 7.23.2 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 babel-jest: 29.7.0(@babel/core@7.23.2) chalk: 4.1.2 ci-info: 3.9.0 @@ -23634,7 +23926,7 @@ packages: pretty-format: 29.7.0 slash: 3.0.0 strip-json-comments: 3.1.1 - ts-node: 10.9.1(@types/node@18.18.6)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -23677,7 +23969,7 @@ packages: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 18.18.6 + '@types/node': 18.18.7 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -23694,7 +23986,7 @@ packages: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -23707,7 +23999,7 @@ packages: jest: optional: true dependencies: - jest: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) + jest: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) jest-diff: 29.7.0 jest-get-type: 29.6.3 dev: true @@ -23722,7 +24014,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.8 - '@types/node': 18.18.6 + '@types/node': 18.18.7 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -23769,7 +24061,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 jest-util: 29.7.0 /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -23823,7 +24115,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -23853,7 +24145,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -23903,7 +24195,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 18.18.6 + '@types/node': 18.18.7 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -23914,7 +24206,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -23937,7 +24229,7 @@ packages: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.18.6 + '@types/node': 18.18.7 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -23948,7 +24240,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -23956,12 +24248,12 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - /jest@29.7.0(@types/node@18.18.6)(ts-node@10.9.1): + /jest@29.7.0(@types/node@18.18.7)(ts-node@10.9.1): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -23974,7 +24266,7 @@ packages: '@jest/core': 29.7.0(ts-node@10.9.1) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) + jest-cli: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -23984,7 +24276,6 @@ packages: /jiti@1.20.0: resolution: {integrity: sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==} hasBin: true - dev: false /joi@17.11.0: resolution: {integrity: sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==} @@ -24166,7 +24457,7 @@ packages: engines: {node: '>=10.0.0'} dependencies: '@metamask/safe-event-emitter': 2.0.0 - eth-rpc-errors: 4.0.2 + eth-rpc-errors: 4.0.3 dev: false /json-rpc-middleware-stream@4.2.3: @@ -24765,6 +25056,14 @@ packages: lit-html: 2.8.0 dev: false + /lit@2.7.6: + resolution: {integrity: sha512-1amFHA7t4VaaDe+vdQejSVBklwtH9svGoG6/dZi9JhxtJBBlqY5D1RV7iLUYY0trCqQc4NfhYYZilZiVHt7Hxg==} + dependencies: + '@lit/reactive-element': 1.6.3 + lit-element: 3.3.3 + lit-html: 2.8.0 + dev: false + /load-json-file@1.1.0: resolution: {integrity: sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==} engines: {node: '>=0.10.0'} @@ -25496,7 +25795,7 @@ packages: web-worker: 1.2.0 dev: false - /meros@1.3.0(@types/node@18.18.6): + /meros@1.3.0(@types/node@18.18.7): resolution: {integrity: sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==} engines: {node: '>=13'} peerDependencies: @@ -25505,7 +25804,7 @@ packages: '@types/node': optional: true dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} @@ -26370,8 +26669,8 @@ packages: engines: {node: '>=16.0.0', npm: '>=7.0.0'} dev: false - /multiformats@12.1.2: - resolution: {integrity: sha512-6mRIsrZXyw5xNPO31IGBMmxgDXBSgCGDsBAtazkZ02ip4hMwZNrQvfxXZtytRoBSWuzSq5f9VmMnXj76fIz5FQ==} + /multiformats@12.1.3: + resolution: {integrity: sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} dev: false @@ -26531,7 +26830,7 @@ packages: '@next/env': 13.5.6 '@swc/helpers': 0.5.2 busboy: 1.6.0 - caniuse-lite: 1.0.30001553 + caniuse-lite: 1.0.30001554 postcss: 8.4.31 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -27012,7 +27311,7 @@ packages: /optimism@0.17.5: resolution: {integrity: sha512-TEcp8ZwK1RczmvMnvktxHSF2tKgMWjJ71xEFGX5ApLh67VsMSTy1ZUlipJw8W+KaqgOmQ+4pqwkeivY89j+4Vw==} dependencies: - '@wry/context': 0.7.3 + '@wry/context': 0.7.4 '@wry/trie': 0.4.3 tslib: 2.6.2 dev: false @@ -28219,7 +28518,7 @@ packages: engines: {node: '>=4'} dev: false - /primereact@9.6.3(@types/react@18.2.31)(react-dom@18.2.0)(react@18.2.0): + /primereact@9.6.3(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-E1Apj4zHeEqFuNR43PFmcpYO51V17PDaVuZmYggEUxZHUo7XWoqkOGg7896SRRMDMBQcO3+HXdJQXi6DOWRV1g==} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -28229,7 +28528,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 '@types/react-transition-group': 4.4.8 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -28351,7 +28650,7 @@ packages: '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 '@types/long': 4.0.2 - '@types/node': 18.18.6 + '@types/node': 18.18.7 long: 4.0.0 /protobufjs@7.2.5: @@ -28369,7 +28668,7 @@ packages: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 18.18.6 + '@types/node': 18.18.7 long: 5.2.3 dev: false @@ -28692,8 +28991,8 @@ packages: - vue-template-compiler dev: false - /react-devtools-core@4.28.4: - resolution: {integrity: sha512-IUZKLv3CimeM07G3vX4H4loxVpByrzq3HvfTX7v9migalwvLs9ZY5D3S3pKR33U+GguYfBBdMMZyToFhsSE/iQ==} + /react-devtools-core@4.28.5: + resolution: {integrity: sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==} dependencies: shell-quote: 1.8.1 ws: 7.5.9 @@ -28789,7 +29088,7 @@ packages: webpack: 5.89.0(webpack-cli@5.1.4) dev: false - /react-markdown@8.0.7(@types/react@18.2.31)(react@18.2.0): + /react-markdown@8.0.7(@types/react@18.2.33)(react@18.2.0): resolution: {integrity: sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==} peerDependencies: '@types/react': '>=16' @@ -28797,7 +29096,7 @@ packages: dependencies: '@types/hast': 2.3.7 '@types/prop-types': 15.7.9 - '@types/react': 18.2.31 + '@types/react': 18.2.33 '@types/unist': 2.0.9 comma-separated-tokens: 2.0.3 hast-util-whitespace: 2.0.1 @@ -28871,7 +29170,7 @@ packages: pretty-format: 26.6.2 promise: 8.3.0 react: 18.2.0 - react-devtools-core: 4.28.4 + react-devtools-core: 4.28.5 react-refresh: 0.4.3 react-shallow-renderer: 16.15.0(react@18.2.0) regenerator-runtime: 0.13.11 @@ -28893,7 +29192,7 @@ packages: resolution: {integrity: sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA==} engines: {node: '>=0.10.0'} - /react-remove-scroll-bar@2.3.4(@types/react@18.2.31)(react@18.2.0): + /react-remove-scroll-bar@2.3.4(@types/react@18.2.33)(react@18.2.0): resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==} engines: {node: '>=10'} peerDependencies: @@ -28903,13 +29202,13 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 react: 18.2.0 - react-style-singleton: 2.2.1(@types/react@18.2.31)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.2.33)(react@18.2.0) tslib: 2.6.2 dev: false - /react-remove-scroll@2.5.4(@types/react@18.2.31)(react@18.2.0): + /react-remove-scroll@2.5.4(@types/react@18.2.33)(react@18.2.0): resolution: {integrity: sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==} engines: {node: '>=10'} peerDependencies: @@ -28919,13 +29218,13 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 react: 18.2.0 - react-remove-scroll-bar: 2.3.4(@types/react@18.2.31)(react@18.2.0) - react-style-singleton: 2.2.1(@types/react@18.2.31)(react@18.2.0) + react-remove-scroll-bar: 2.3.4(@types/react@18.2.33)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.2.33)(react@18.2.0) tslib: 2.6.2 - use-callback-ref: 1.3.0(@types/react@18.2.31)(react@18.2.0) - use-sidecar: 1.1.2(@types/react@18.2.31)(react@18.2.0) + use-callback-ref: 1.3.0(@types/react@18.2.33)(react@18.2.0) + use-sidecar: 1.1.2(@types/react@18.2.33)(react@18.2.0) dev: false /react-router-config@5.1.1(react-router@5.3.4)(react@18.2.0): @@ -28980,7 +29279,7 @@ packages: react: 18.2.0 react-is: 18.2.0 - /react-style-singleton@2.2.1(@types/react@18.2.31)(react@18.2.0): + /react-style-singleton@2.2.1(@types/react@18.2.33)(react@18.2.0): resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} peerDependencies: @@ -28990,7 +29289,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 get-nonce: 1.0.1 invariant: 2.2.4 react: 18.2.0 @@ -29860,8 +30159,8 @@ packages: '@babel/runtime': 7.23.2 dev: false - /rtl-detect@1.0.4: - resolution: {integrity: sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==} + /rtl-detect@1.1.2: + resolution: {integrity: sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==} dev: false /rtlcss@3.5.0: @@ -30601,6 +30900,10 @@ packages: - supports-color dev: true + /solmate@6.2.0: + resolution: {integrity: sha512-AM38ioQ2P8zRsA42zenb9or6OybRjOLXIu3lhIT8rhddUuduCt76pUEuLxOIg9GByGojGz+EbpFdCB6B+QZVVA==} + dev: true + /sonic-boom@2.8.0: resolution: {integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==} dependencies: @@ -31803,7 +32106,7 @@ packages: bs-logger: 0.2.6 esbuild: 0.17.19 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.18.6)(ts-node@10.9.1) + jest: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -31842,7 +32145,7 @@ packages: tsconfig-paths: 3.14.2 dev: true - /ts-node@10.9.1(@types/node@18.18.6)(typescript@4.9.5): + /ts-node@10.9.1(@types/node@18.18.7)(typescript@4.9.5): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -31861,7 +32164,7 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 18.18.6 + '@types/node': 18.18.7 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 @@ -31872,7 +32175,7 @@ packages: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - /ts-node@10.9.1(@types/node@18.18.6)(typescript@5.1.6): + /ts-node@10.9.1(@types/node@18.18.7)(typescript@5.1.6): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -31891,7 +32194,7 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 18.18.6 + '@types/node': 18.18.7 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 @@ -31902,38 +32205,6 @@ packages: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - /ts-node@10.9.1(@types/node@18.18.6)(typescript@5.2.2): - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 18.18.6 - acorn: 8.10.0 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.2.2 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - optional: true - /ts-node@10.9.1(@types/node@20.5.1)(typescript@4.9.5): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true @@ -32314,14 +32585,6 @@ packages: engines: {node: '>=14.17'} hasBin: true - /typescript@5.2.2: - resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} - engines: {node: '>=14.17'} - hasBin: true - requiresBuild: true - dev: true - optional: true - /typical@4.0.0: resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} engines: {node: '>=8'} @@ -32385,7 +32648,7 @@ packages: /uint8arrays@4.0.6: resolution: {integrity: sha512-4ZesjQhqOU2Ip6GPReIwN60wRxIupavL8T0Iy36BBHr2qyMrNxsPJvr7vpS4eFt8F8kSguWUPad6ZM9izs/vyw==} dependencies: - multiformats: 12.1.2 + multiformats: 12.1.3 dev: false /unbox-primitive@1.0.2: @@ -32412,6 +32675,9 @@ packages: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} dev: true + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + /undici@5.26.5: resolution: {integrity: sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw==} engines: {node: '>=14.0'} @@ -32713,7 +32979,7 @@ packages: /urlpattern-polyfill@9.0.0: resolution: {integrity: sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==} - /use-callback-ref@1.3.0(@types/react@18.2.31)(react@18.2.0): + /use-callback-ref@1.3.0(@types/react@18.2.33)(react@18.2.0): resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} engines: {node: '>=10'} peerDependencies: @@ -32723,7 +32989,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 react: 18.2.0 tslib: 2.6.2 dev: false @@ -32761,7 +33027,7 @@ packages: use-isomorphic-layout-effect: 1.1.2(react@18.2.0) dev: false - /use-sidecar@1.1.2(@types/react@18.2.31)(react@18.2.0): + /use-sidecar@1.1.2(@types/react@18.2.33)(react@18.2.0): resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} engines: {node: '>=10'} peerDependencies: @@ -32771,7 +33037,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 detect-node-es: 1.1.0 react: 18.2.0 tslib: 2.6.2 @@ -32918,6 +33184,20 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false + /valtio@1.11.0(react@18.2.0): + resolution: {integrity: sha512-65Yd0yU5qs86b5lN1eu/nzcTgQ9/6YnD6iO+DDaDbQLn1Zv2w12Gwk43WkPlUBxk5wL/6cD5YMFf7kj6HZ1Kpg==} + engines: {node: '>=12.20.0'} + peerDependencies: + react: '>=16.8' + peerDependenciesMeta: + react: + optional: true + dependencies: + proxy-compare: 2.5.1 + react: 18.2.0 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + /value-equal@1.0.1: resolution: {integrity: sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==} dev: false @@ -33033,7 +33313,7 @@ packages: - zod dev: false - /vite-node@0.28.5(@types/node@18.18.6): + /vite-node@0.28.5(@types/node@18.18.7): resolution: {integrity: sha512-LmXb9saMGlrMZbXTvOveJKwMTBTNUH66c8rJnQ0ZPNX+myPEol64+szRzXtV5ORb0Hb/91yq+/D3oERoyAt6LA==} engines: {node: '>=v14.16.0'} hasBin: true @@ -33045,7 +33325,7 @@ packages: picocolors: 1.0.0 source-map: 0.6.1 source-map-support: 0.5.21 - vite: 4.5.0(@types/node@18.18.6) + vite: 4.5.0(@types/node@18.18.7) transitivePeerDependencies: - '@types/node' - less @@ -33057,7 +33337,7 @@ packages: - terser dev: true - /vite@4.5.0(@types/node@18.18.6): + /vite@4.5.0(@types/node@18.18.7): resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -33085,7 +33365,7 @@ packages: terser: optional: true dependencies: - '@types/node': 18.18.6 + '@types/node': 18.18.7 esbuild: 0.18.20 postcss: 8.4.31 rollup: 3.29.4 @@ -33117,7 +33397,7 @@ packages: dependencies: '@types/chai': 4.3.9 '@types/chai-subset': 1.3.4 - '@types/node': 18.18.6 + '@types/node': 18.18.7 '@vitest/expect': 0.28.5 '@vitest/runner': 0.28.5 '@vitest/spy': 0.28.5 @@ -33136,8 +33416,8 @@ packages: tinybench: 2.5.1 tinypool: 0.3.1 tinyspy: 1.1.1 - vite: 4.5.0(@types/node@18.18.6) - vite-node: 0.28.5(@types/node@18.18.6) + vite: 4.5.0(@types/node@18.18.7) + vite-node: 0.28.5(@types/node@18.18.7) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -33186,7 +33466,7 @@ packages: hasBin: true dev: true - /wagmi@1.3.9(@types/react@18.2.31)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): + /wagmi@1.3.9(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): resolution: {integrity: sha512-BQbl+vWLNpLraXd/MWsl1P3I41l7DHrujx6qshIa1HDV7Mdh0GNrDuluRYBtuK2bBx9WM/Fjw45Ef2aKADan9A==} peerDependencies: react: '>=17.0.0' @@ -33199,7 +33479,7 @@ packages: '@tanstack/query-sync-storage-persister': 4.36.1 '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0) '@tanstack/react-query-persist-client': 4.36.1(@tanstack/react-query@4.36.1) - '@wagmi/core': 1.3.8(@types/react@18.2.31)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + '@wagmi/core': 1.3.8(@types/react@18.2.33)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) abitype: 0.8.7(typescript@5.1.6)(zod@3.22.4) react: 18.2.0 typescript: 5.1.6 @@ -34161,7 +34441,7 @@ packages: /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} - /zustand@4.4.4(@types/react@18.2.31)(react@18.2.0): + /zustand@4.4.4(@types/react@18.2.33)(react@18.2.0): resolution: {integrity: sha512-5UTUIAiHMNf5+mFp7/AnzJXS7+XxktULFN0+D1sCiZWyX7ZG+AQpqs2qpYrynRij4QvoDdCD+U+bmg/cG3Ucxw==} engines: {node: '>=12.7.0'} peerDependencies: @@ -34176,7 +34456,7 @@ packages: react: optional: true dependencies: - '@types/react': 18.2.31 + '@types/react': 18.2.33 react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) dev: false From b39808272a6ca8d021ecc8f6f61e45f8fd219d53 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Fri, 27 Oct 2023 23:13:52 +0200 Subject: [PATCH 15/49] chore(lint): cleanup config and affiliate flows (#1140) --- contracts/.eslintrc.yml | 10 - contracts/.gitignore | 1 + contracts/.lintstagedrc | 5 +- contracts/.prettierignore | 2 + contracts/.prettierrc.yml | 23 -- contracts/.solcover.js | 7 - contracts/.solhint.json | 5 +- contracts/.vscode/settings.json | 2 - contracts/foundry.toml | 8 +- contracts/package.json | 9 +- .../BatchOrderTypehashRegistry.sol | 16 +- .../CreatorFeeManagerWithRebates.sol | 25 +- .../CreatorFeeManagerWithRoyalties.sol | 21 +- contracts/src/marketplace/CurrencyManager.sol | 4 +- .../src/marketplace/ExecutionManager.sol | 51 ++-- .../src/marketplace/InheritedStrategy.sol | 25 +- .../src/marketplace/LooksRareProtocol.sol | 108 ++++---- contracts/src/marketplace/NonceManager.sol | 8 +- .../src/marketplace/ProtocolFeeRecipient.sol | 8 +- contracts/src/marketplace/StrategyManager.sol | 16 +- contracts/src/marketplace/TransferManager.sol | 43 ++- .../src/marketplace/TransferSelectorNFT.sol | 18 +- .../executionStrategies/BaseStrategy.sol | 8 +- .../BaseStrategyChainlinkPriceLatency.sol | 2 +- .../StrategyChainlinkUSDDynamicAsk.sol | 45 ++-- .../StrategyCollectionOffer.sol | 34 +-- .../StrategyDutchAuction.sol | 30 +-- .../StrategyItemIdsRange.sol | 37 ++- .../marketplace/helpers/OrderValidatorV2A.sol | 254 ++++++++---------- .../marketplace/helpers/ProtocolHelpers.sol | 26 +- .../interfaces/ICreatorFeeManager.sol | 11 +- .../interfaces/IImmutableCreate2Factory.sol | 8 +- .../interfaces/ILooksRareProtocol.sol | 24 +- .../interfaces/IRoyaltyFeeRegistry.sol | 8 +- .../src/marketplace/interfaces/IStrategy.sol | 10 +- .../interfaces/ITransferManager.sol | 4 +- .../libraries/CurrencyValidator.sol | 6 +- .../MerkleProofCalldataWithNodes.sol | 23 +- .../OpenZeppelin/MerkleProofMemory.sol | 2 +- .../marketplace/libraries/OrderStructs.sol | 77 +++--- contracts/src/protocol/AllowlistMinter.sol | 20 +- contracts/src/protocol/HypercertMinter.sol | 59 ++-- contracts/src/protocol/SemiFungible1155.sol | 160 ++++++----- .../src/protocol/interfaces/IAllowlist.sol | 9 +- .../BatchMakerCollectionOrders.t.sol | 27 +- .../marketplace/BatchMakerOrders.t.sol | 202 +++++--------- .../BatchOrderTypehashRegistry.t.sol | 57 ++-- .../marketplace/BundleTransactions.t.sol | 72 ++--- .../CreatorFeeManagerWithRebates.t.sol | 81 ++---- .../CreatorFeeManagerWithRoyalties.t.sol | 138 +++------- .../foundry/marketplace/CurrencyManager.t.sol | 10 +- .../DelegationRecipientsTaker.t.sol | 29 +- .../marketplace/DomainSeparatorUpdates.t.sol | 36 +-- .../marketplace/ExecutionManager.t.sol | 112 ++++---- .../foundry/marketplace/GasGriefing.t.sol | 36 +-- .../foundry/marketplace/InitialStates.t.sol | 4 +- .../marketplace/LooksRareProtocol.t.sol | 104 +++---- .../marketplace/NonceInvalidation.t.sol | 91 +++---- .../marketplace/OrderValidatorV2A.t.sol | 168 +++++------- .../foundry/marketplace/ProtocolBase.t.sol | 63 ++--- .../marketplace/ProtocolFeeRecipient.t.sol | 17 +- .../test/foundry/marketplace/Sandbox.t.sol | 36 +-- .../marketplace/SignaturesEIP2098.t.sol | 14 +- .../SignaturesERC1271WalletForERC1155.t.sol | 150 ++++------- .../SignaturesERC1271WalletForERC721.t.sol | 105 +++----- .../marketplace/SignaturesRevertions.t.sol | 85 +++--- .../marketplace/StandardTransactions.t.sol | 141 ++++------ .../foundry/marketplace/StrategyManager.t.sol | 62 ++--- .../foundry/marketplace/TransferManager.t.sol | 32 +-- ...ifyOrderTimestampValidityEquivalence.t.sol | 8 +- .../Chainlink/USDDynamicAskOrders.t.sol | 93 ++++--- .../CollectionOffers.t.sol | 85 +++--- .../DutchAuctionOrders.t.sol | 143 ++++------ .../ItemIdsRangeOrders.t.sol | 82 +++--- .../MultiFillCollectionOrders.t.sol | 33 +-- .../foundry/marketplace/utils/BytesLib.sol | 4 +- .../marketplace/utils/EIP712MerkleTree.sol | 47 ++-- .../marketplace/utils/ERC1271Wallet.sol | 14 +- .../utils/MaliciousERC1271Wallet.sol | 22 +- ...MaliciousIsValidSignatureERC1271Wallet.sol | 2 +- ...aliciousOnERC1155ReceivedERC1271Wallet.sol | 14 +- ...C1155ReceivedTheThirdTimeERC1271Wallet.sol | 2 +- .../marketplace/utils/MerkleWithPosition.sol | 25 +- .../marketplace/utils/MockOrderGenerator.sol | 65 +++-- .../marketplace/utils/ProtocolHelpers.sol | 18 +- .../StrategyTestMultiFillCollectionOrder.sol | 32 +-- .../foundry/marketplace/utils/TestHelpers.sol | 4 +- .../marketplace/utils/TestParameters.sol | 13 +- .../foundry/protocol/AllowlistMinter.t.sol | 27 +- .../test/foundry/protocol/Bitshifting.t.sol | 17 +- .../HypercertMinter.batchminting.t.sol | 48 ++-- .../protocol/HypercertMinter.pausable.t.sol | 18 +- .../foundry/protocol/HypercertMinter.t.sol | 38 +-- .../protocol/HypercertMinter.transfers.t.sol | 14 +- .../foundry/protocol/PerformanceTesting.t.sol | 49 ++-- .../SemiFungible1155.allowances.t.sol | 8 +- .../protocol/SemiFungible1155.burning.t.sol | 8 +- .../protocol/SemiFungible1155.minting.t.sol | 24 +- .../foundry/protocol/SemiFungible1155.t.sol | 14 +- .../protocol/SemiFungible1155.transfers.t.sol | 18 +- .../protocol/SemiFungible1155.units.sol | 14 +- .../foundry/protocol/SemiFungibleHelper.sol | 8 +- .../api/contracts/HypercertMinter.md | 8 +- pnpm-lock.yaml | 3 - 104 files changed, 1738 insertions(+), 2428 deletions(-) delete mode 100644 contracts/.solcover.js diff --git a/contracts/.eslintrc.yml b/contracts/.eslintrc.yml index a6c77c81..bc63dc32 100644 --- a/contracts/.eslintrc.yml +++ b/contracts/.eslintrc.yml @@ -8,13 +8,3 @@ parserOptions: project: "./contracts/tsconfig.json" plugins: - "@typescript-eslint" -rules: - "@typescript-eslint/no-floating-promises": - - error - - ignoreIIFE: true - ignoreVoid: true - "@typescript-eslint/no-inferrable-types": "off" - "@typescript-eslint/no-unused-vars": - - error - - argsIgnorePattern: "_" - varsIgnorePattern: "_" diff --git a/contracts/.gitignore b/contracts/.gitignore index 41c2623f..45e7e641 100644 --- a/contracts/.gitignore +++ b/contracts/.gitignore @@ -35,6 +35,7 @@ yarn-error.log* .DS_Store /.idea test*.svg +lcov.info # broadcasts !/broadcast diff --git a/contracts/.lintstagedrc b/contracts/.lintstagedrc index 45a7492d..0e2564c9 100644 --- a/contracts/.lintstagedrc +++ b/contracts/.lintstagedrc @@ -1,5 +1,4 @@ { - "*.{js,json,md,sol,ts,yml}": [ - "prettier --config ./.prettierrc.yml --write" - ] + "*.{js,json,md,ts,yml}": ["prettier --config ./.prettierrc.yml --write"], + "*.{sol}": ["forge fmt"] } diff --git a/contracts/.prettierignore b/contracts/.prettierignore index 406d1f27..1a71d38f 100644 --- a/contracts/.prettierignore +++ b/contracts/.prettierignore @@ -22,8 +22,10 @@ # files *.env *.log +*.sol .pnp.* coverage.json npm-debug.log* yarn-debug.log* yarn-error.log* +.DS_Store diff --git a/contracts/.prettierrc.yml b/contracts/.prettierrc.yml index 0f125e7c..b8ea7e0f 100644 --- a/contracts/.prettierrc.yml +++ b/contracts/.prettierrc.yml @@ -6,26 +6,3 @@ singleQuote: false tabWidth: 2 trailingComma: "all" useTabs: false - -plugins: - - prettier-plugin-solidity - -overrides: - - files: "**/*.t.sol" - rules: - max-state-count": "off" - state-visibility": "off" - max-line-length": "off" - options: - tabWidth: 4 - - files: "*.sol" - rules: - compiler-version: "0.8.16" - options: - tabWidth: 4 - - files: "*.ts" - options: - importOrder: ["", "^[./]"] - importOrderParserPlugins: ["importAssertions", "typescript"] - importOrderSeparation: true - importOrderSortSpecifiers: true diff --git a/contracts/.solcover.js b/contracts/.solcover.js deleted file mode 100644 index a6b8e642..00000000 --- a/contracts/.solcover.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - istanbulReporter: ["html", "lcov"], - providerOptions: { - mnemonic: process.env.MNEMONIC, - }, - skipFiles: ["test", "mocks", "lib"], -}; diff --git a/contracts/.solhint.json b/contracts/.solhint.json index c7aea11c..5a2b49ec 100644 --- a/contracts/.solhint.json +++ b/contracts/.solhint.json @@ -1,13 +1,14 @@ { - "plugins": ["prettier"], "extends": "solhint:recommended", "rules": { + "avoid-low-level-calls": "off", "code-complexity": ["error", 12], "compiler-version": ["error", ">=0.8.16"], "func-visibility": ["error", { "ignoreConstructors": true }], - "max-line-length": ["warn", 200], "no-console": "off", + "no-empty-blocks": "off", "not-rely-on-time": "off", + "private-vars-leading-underscore": "warn", "reason-string": ["warn", { "maxLength": 64 }], "one-contract-per-file": "off" } diff --git a/contracts/.vscode/settings.json b/contracts/.vscode/settings.json index 5a74fb60..ea8a1e8a 100644 --- a/contracts/.vscode/settings.json +++ b/contracts/.vscode/settings.json @@ -1,10 +1,8 @@ { "editor.formatOnSave": true, - "solidity.formatter": "prettier", "solidity.packageDefaultDependenciesContractsDirectory": "src", "solidity.packageDefaultDependenciesDirectory": "lib", "solidity.remappings": ["./remappings.txt"], - "solidity.defaultCompiler": "remoteFile", "files.exclude": { "**/.git": true, "**/.svn": true, diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 4b146c01..a3a0c8f9 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -1,7 +1,7 @@ # Full reference /~https://github.com/foundry-rs/foundry/tree/master/config [profile.default] -auto_detect_solc = true +auto_detect_solc = true allow_paths = ["../node_modules", "lib"] bytecode_hash = "none" force = false @@ -23,4 +23,8 @@ verbosity = 1 [rpc_endpoints] mainnet = "${MAINNET_RPC_URL}" goerli = "${GOERLI_RPC_URL}" -optimism = "${OPTIMISM_RPC_URL}" \ No newline at end of file +optimism = "${OPTIMISM_RPC_URL}" + +[fmt] +number_underscore = "thousands" +wrap_comments = true diff --git a/contracts/package.json b/contracts/package.json index 36d2c440..5ad67eae 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -84,7 +84,6 @@ "shx": "^0.3.4", "solhint": "^3.6.2", "solhint-plugin-prettier": "^0.0.5", - "solidity-coverage": "^0.8.2", "solmate": "^6.2.0", "ts-node": "^10.9.1", "typechain": "^8.3.1", @@ -104,14 +103,14 @@ "build": "hardhat compile && pnpm tsc -p tsconfig.build.json && rollup -c && pnpm copy:contracts", "build:forge": "forge build", "clean": "rimraf cache out dist src/typechain src/abi", - "copy:contracts": "copyfiles -u 1 ./src/**/*.sol ./src/*.sol ./contracts", + "copy:contracts": "copyfiles -u 1 ./src/**/*.sol ./src/*.sol ./contracts", "docs": "hardhat dodoc", "lint": "pnpm lint:sol && pnpm prettier:check", - "lint:sol": "solhint -w 60 \"./{src,test/protocol,test/marketplace}/**/*.sol\"", + "lint:sol": "forge fmt --check && solhint \"./{src,test/protocol,test/marketplace}/**/*.sol\"", "prebuild": "pnpm clean", "prepublish": "pnpm build", - "prettier": "prettier --config \"./.prettierrc.yml\" --write \"**/*.{json,md,sol,yml}\"", - "prettier:check": "prettier --config \"./.prettierrc.yml\" --check \"**/*.{json,md,sol,yml}\"", + "prettier": "prettier --config \"./.prettierrc.yml\" --write \"**/*.{json,md,ts,yml}\"", + "prettier:check": "prettier --config \"./.prettierrc.yml\" --check \"**/*.{json,md,ts,yml}\"", "slither": "slither ./src", "test": "pnpm test:hardhat && pnpm test:forge", "test:forge": "forge test", diff --git a/contracts/src/marketplace/BatchOrderTypehashRegistry.sol b/contracts/src/marketplace/BatchOrderTypehashRegistry.sol index 13851212..9710a735 100644 --- a/contracts/src/marketplace/BatchOrderTypehashRegistry.sol +++ b/contracts/src/marketplace/BatchOrderTypehashRegistry.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.17; // Shared errors -import { MerkleProofTooLarge } from "./errors/SharedErrors.sol"; +import {MerkleProofTooLarge} from "./errors/SharedErrors.sol"; /** * @title BatchOrderTypehashRegistry @@ -22,9 +22,17 @@ contract BatchOrderTypehashRegistry { /** * @dev It looks like this for each height - * height == 1: BatchOrder(Maker[2] tree)Maker(uint8 quoteType,uint256 globalNonce,uint256 subsetNonce,uint256 orderNonce,uint256 strategyId,uint8 collectionType,address collection,address currency,address signer,uint256 startTime,uint256 endTime,uint256 price,uint256[] itemIds,uint256[] amounts,bytes additionalParameters) - * height == 2: BatchOrder(Maker[2][2] tree)Maker(uint8 quoteType,uint256 globalNonce,uint256 subsetNonce,uint256 orderNonce,uint256 strategyId,uint8 collectionType,address collection,address currency,address signer,uint256 startTime,uint256 endTime,uint256 price,uint256[] itemIds,uint256[] amounts,bytes additionalParameters) - * height == n: BatchOrder(Maker[2]...[2] tree)Maker(uint8 quoteType,uint256 globalNonce,uint256 subsetNonce,uint256 orderNonce,uint256 strategyId,uint8 collectionType,address collection,address currency,address signer,uint256 startTime,uint256 endTime,uint256 price,uint256[] itemIds,uint256[] amounts,bytes additionalParameters) + * height == 1: BatchOrder(Maker[2] tree)Maker(uint8 quoteType,uint256 globalNonce,uint256 subsetNonce,uint256 + * orderNonce,uint256 strategyId,uint8 collectionType,address collection,address currency,address signer,uint256 + * startTime,uint256 endTime,uint256 price,uint256[] itemIds,uint256[] amounts,bytes additionalParameters) + * height == 2: BatchOrder(Maker[2][2] tree)Maker(uint8 quoteType,uint256 globalNonce,uint256 + * subsetNonce,uint256 orderNonce,uint256 strategyId,uint8 collectionType,address collection,address + * currency,address signer,uint256 startTime,uint256 endTime,uint256 price,uint256[] itemIds,uint256[] amounts,bytes + * additionalParameters) + * height == n: BatchOrder(Maker[2]...[2] tree)Maker(uint8 quoteType,uint256 globalNonce,uint256 + * subsetNonce,uint256 orderNonce,uint256 strategyId,uint8 collectionType,address collection,address + * currency,address signer,uint256 startTime,uint256 endTime,uint256 price,uint256[] itemIds,uint256[] amounts,bytes + * additionalParameters) */ function _getBatchOrderTypehash(uint256 height) internal pure returns (bytes32 typehash) { if (height == 1) { diff --git a/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol b/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol index 4b5e6ef7..3a1de368 100644 --- a/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol +++ b/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol @@ -2,14 +2,14 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IERC2981 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC2981.sol"; +import {IERC2981} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC2981.sol"; // Interfaces -import { ICreatorFeeManager } from "./interfaces/ICreatorFeeManager.sol"; -import { IRoyaltyFeeRegistry } from "./interfaces/IRoyaltyFeeRegistry.sol"; +import {ICreatorFeeManager} from "./interfaces/ICreatorFeeManager.sol"; +import {IRoyaltyFeeRegistry} from "./interfaces/IRoyaltyFeeRegistry.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "./constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "./constants/NumericConstants.sol"; /** * @title CreatorFeeManagerWithRebates @@ -38,22 +38,21 @@ contract CreatorFeeManagerWithRebates is ICreatorFeeManager { /** * @inheritdoc ICreatorFeeManager */ - function viewCreatorFeeInfo( - address collection, - uint256 price, - uint256[] memory itemIds - ) external view returns (address creator, uint256 creatorFeeAmount) { + function viewCreatorFeeInfo(address collection, uint256 price, uint256[] memory itemIds) + external + view + returns (address creator, uint256 creatorFeeAmount) + { // Check if there is a royalty info in the system - (creator, ) = royaltyFeeRegistry.royaltyInfo(collection, price); + (creator,) = royaltyFeeRegistry.royaltyInfo(collection, price); if (creator == address(0)) { if (IERC2981(collection).supportsInterface(IERC2981.royaltyInfo.selector)) { uint256 length = itemIds.length; - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { try IERC2981(collection).royaltyInfo(itemIds[i], price) returns ( - address newCreator, - uint256 /* newCreatorFeeAmount */ + address newCreator, uint256 /* newCreatorFeeAmount */ ) { if (i == 0) { creator = newCreator; diff --git a/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol b/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol index ac72682d..a50dde6a 100644 --- a/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol +++ b/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol @@ -2,11 +2,11 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IERC2981 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC2981.sol"; +import {IERC2981} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC2981.sol"; // Interfaces -import { ICreatorFeeManager } from "./interfaces/ICreatorFeeManager.sol"; -import { IRoyaltyFeeRegistry } from "./interfaces/IRoyaltyFeeRegistry.sol"; +import {ICreatorFeeManager} from "./interfaces/ICreatorFeeManager.sol"; +import {IRoyaltyFeeRegistry} from "./interfaces/IRoyaltyFeeRegistry.sol"; /** * @title CreatorFeeManagerWithRoyalties @@ -44,11 +44,11 @@ contract CreatorFeeManagerWithRoyalties is ICreatorFeeManager { * (1) high royalties * (2) potential unexpected royalty changes that can occur after the creation of the order. */ - function viewCreatorFeeInfo( - address collection, - uint256 price, - uint256[] memory itemIds - ) external view returns (address creator, uint256 creatorFeeAmount) { + function viewCreatorFeeInfo(address collection, uint256 price, uint256[] memory itemIds) + external + view + returns (address creator, uint256 creatorFeeAmount) + { // Check if there is a royalty info in the system (creator, creatorFeeAmount) = royaltyFeeRegistry.royaltyInfo(collection, price); @@ -56,10 +56,9 @@ contract CreatorFeeManagerWithRoyalties is ICreatorFeeManager { if (IERC2981(collection).supportsInterface(IERC2981.royaltyInfo.selector)) { uint256 length = itemIds.length; - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { try IERC2981(collection).royaltyInfo(itemIds[i], price) returns ( - address newCreator, - uint256 newCreatorFeeAmount + address newCreator, uint256 newCreatorFeeAmount ) { if (i == 0) { creator = newCreator; diff --git a/contracts/src/marketplace/CurrencyManager.sol b/contracts/src/marketplace/CurrencyManager.sol index 103d0789..f72b5471 100644 --- a/contracts/src/marketplace/CurrencyManager.sol +++ b/contracts/src/marketplace/CurrencyManager.sol @@ -2,10 +2,10 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { OwnableTwoSteps } from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol"; +import {OwnableTwoSteps} from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol"; // Interfaces -import { ICurrencyManager } from "./interfaces/ICurrencyManager.sol"; +import {ICurrencyManager} from "./interfaces/ICurrencyManager.sol"; /** * @title CurrencyManager diff --git a/contracts/src/marketplace/ExecutionManager.sol b/contracts/src/marketplace/ExecutionManager.sol index 06de37c1..e3e132df 100644 --- a/contracts/src/marketplace/ExecutionManager.sol +++ b/contracts/src/marketplace/ExecutionManager.sol @@ -2,25 +2,31 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "./libraries/OrderStructs.sol"; +import {OrderStructs} from "./libraries/OrderStructs.sol"; // Interfaces -import { IExecutionManager } from "./interfaces/IExecutionManager.sol"; -import { ICreatorFeeManager } from "./interfaces/ICreatorFeeManager.sol"; +import {IExecutionManager} from "./interfaces/IExecutionManager.sol"; +import {ICreatorFeeManager} from "./interfaces/ICreatorFeeManager.sol"; // Direct dependencies -import { InheritedStrategy } from "./InheritedStrategy.sol"; -import { NonceManager } from "./NonceManager.sol"; -import { StrategyManager } from "./StrategyManager.sol"; +import {InheritedStrategy} from "./InheritedStrategy.sol"; +import {NonceManager} from "./NonceManager.sol"; +import {StrategyManager} from "./StrategyManager.sol"; // Assembly -import { NoSelectorForStrategy_error_selector, NoSelectorForStrategy_error_length, OutsideOfTimeRange_error_selector, OutsideOfTimeRange_error_length, Error_selector_offset } from "./constants/AssemblyConstants.sol"; +import { + NoSelectorForStrategy_error_selector, + NoSelectorForStrategy_error_length, + OutsideOfTimeRange_error_selector, + OutsideOfTimeRange_error_length, + Error_selector_offset +} from "./constants/AssemblyConstants.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "./constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "./constants/NumericConstants.sol"; // Enums -import { QuoteType } from "./enums/QuoteType.sol"; +import {QuoteType} from "./enums/QuoteType.sol"; /** * @title ExecutionManager @@ -39,7 +45,7 @@ contract ExecutionManager is InheritedStrategy, NonceManager, StrategyManager, I * @notice Maximum creator fee (in basis point). */ // TODO do we need a max? Is 1% max fair? - uint16 public maxCreatorFeeBp = 1_000; + uint16 public maxCreatorFeeBp = 1000; /** * @notice Creator fee manager. @@ -72,7 +78,7 @@ contract ExecutionManager is InheritedStrategy, NonceManager, StrategyManager, I * Only callable by owner. */ function updateMaxCreatorFeeBp(uint16 newMaxCreatorFeeBp) external onlyOwner { - if (newMaxCreatorFeeBp > 2_500) { + if (newMaxCreatorFeeBp > 2500) { revert CreatorFeeBpTooHigh(); } @@ -172,11 +178,8 @@ contract ExecutionManager is InheritedStrategy, NonceManager, StrategyManager, I } // Creator fee and adjustment of protocol fee - (recipients[1], feeAmounts[1]) = _getCreatorRecipientAndCalculateFeeAmount( - makerOrder.collection, - price, - itemIds - ); + (recipients[1], feeAmounts[1]) = + _getCreatorRecipientAndCalculateFeeAmount(makerOrder.collection, price, itemIds); if (makerOrder.quoteType == QuoteType.Bid) { _setTheRestOfFeeAmountsAndRecipients( makerOrder.strategyId, @@ -187,11 +190,7 @@ contract ExecutionManager is InheritedStrategy, NonceManager, StrategyManager, I ); } else { _setTheRestOfFeeAmountsAndRecipients( - makerOrder.strategyId, - price, - makerOrder.signer, - feeAmounts, - recipients + makerOrder.strategyId, price, makerOrder.signer, feeAmounts, recipients ); } } @@ -240,11 +239,11 @@ contract ExecutionManager is InheritedStrategy, NonceManager, StrategyManager, I * @return creator Creator recipient * @return creatorFeeAmount Creator fee amount */ - function _getCreatorRecipientAndCalculateFeeAmount( - address collection, - uint256 price, - uint256[] memory itemIds - ) private view returns (address creator, uint256 creatorFeeAmount) { + function _getCreatorRecipientAndCalculateFeeAmount(address collection, uint256 price, uint256[] memory itemIds) + private + view + returns (address creator, uint256 creatorFeeAmount) + { if (address(creatorFeeManager) != address(0)) { (creator, creatorFeeAmount) = creatorFeeManager.viewCreatorFeeInfo(collection, price, itemIds); diff --git a/contracts/src/marketplace/InheritedStrategy.sol b/contracts/src/marketplace/InheritedStrategy.sol index 9f84b5a1..93d09414 100644 --- a/contracts/src/marketplace/InheritedStrategy.sol +++ b/contracts/src/marketplace/InheritedStrategy.sol @@ -2,13 +2,18 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "./libraries/OrderStructs.sol"; +import {OrderStructs} from "./libraries/OrderStructs.sol"; // Shared errors -import { OrderInvalid } from "./errors/SharedErrors.sol"; +import {OrderInvalid} from "./errors/SharedErrors.sol"; // Assembly -import { OrderInvalid_error_selector, OrderInvalid_error_length, Error_selector_offset, OneWord } from "./constants/AssemblyConstants.sol"; +import { + OrderInvalid_error_selector, + OrderInvalid_error_length, + Error_selector_offset, + OneWord +} from "./constants/AssemblyConstants.sol"; /** * @title InheritedStrategy @@ -26,10 +31,10 @@ contract InheritedStrategy { * @param amounts Array of amounts * @param itemIds Array of item ids */ - function _verifyItemIdsAndAmountsEqualLengthsAndValidAmounts( - uint256[] calldata amounts, - uint256[] calldata itemIds - ) internal pure { + function _verifyItemIdsAndAmountsEqualLengthsAndValidAmounts(uint256[] calldata amounts, uint256[] calldata itemIds) + internal + pure + { assembly { let end { @@ -56,11 +61,7 @@ contract InheritedStrategy { let amountsOffset := amounts.offset - for { - - } end { - - } { + for {} end {} { /** * @dev Starting from the end of the array minus 32 bytes to load the last item, * ending with `end` equal to 0 to load the first item diff --git a/contracts/src/marketplace/LooksRareProtocol.sol b/contracts/src/marketplace/LooksRareProtocol.sol index 45c6331f..b60e6e30 100644 --- a/contracts/src/marketplace/LooksRareProtocol.sol +++ b/contracts/src/marketplace/LooksRareProtocol.sol @@ -2,32 +2,40 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { SignatureCheckerCalldata } from "@looksrare/contracts-libs/contracts/SignatureCheckerCalldata.sol"; -import { LowLevelETHReturnETHIfAnyExceptOneWei } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelETHReturnETHIfAnyExceptOneWei.sol"; -import { LowLevelWETH } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelWETH.sol"; -import { LowLevelERC20Transfer } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC20Transfer.sol"; +import {SignatureCheckerCalldata} from "@looksrare/contracts-libs/contracts/SignatureCheckerCalldata.sol"; +import {LowLevelETHReturnETHIfAnyExceptOneWei} from + "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelETHReturnETHIfAnyExceptOneWei.sol"; +import {LowLevelWETH} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelWETH.sol"; +import {LowLevelERC20Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC20Transfer.sol"; // OpenZeppelin's library (adjusted) for verifying Merkle proofs -import { MerkleProofCalldataWithNodes } from "./libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol"; +import {MerkleProofCalldataWithNodes} from "./libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol"; // Libraries -import { OrderStructs } from "./libraries/OrderStructs.sol"; +import {OrderStructs} from "./libraries/OrderStructs.sol"; // Interfaces -import { ILooksRareProtocol } from "./interfaces/ILooksRareProtocol.sol"; +import {ILooksRareProtocol} from "./interfaces/ILooksRareProtocol.sol"; // Shared errors -import { CallerInvalid, CurrencyInvalid, LengthsInvalid, MerkleProofInvalid, MerkleProofTooLarge, QuoteTypeInvalid } from "./errors/SharedErrors.sol"; +import { + CallerInvalid, + CurrencyInvalid, + LengthsInvalid, + MerkleProofInvalid, + MerkleProofTooLarge, + QuoteTypeInvalid +} from "./errors/SharedErrors.sol"; // Direct dependencies -import { TransferSelectorNFT } from "./TransferSelectorNFT.sol"; -import { BatchOrderTypehashRegistry } from "./BatchOrderTypehashRegistry.sol"; +import {TransferSelectorNFT} from "./TransferSelectorNFT.sol"; +import {BatchOrderTypehashRegistry} from "./BatchOrderTypehashRegistry.sol"; // Constants -import { MAX_CALLDATA_PROOF_LENGTH, ONE_HUNDRED_PERCENT_IN_BP } from "./constants/NumericConstants.sol"; +import {MAX_CALLDATA_PROOF_LENGTH, ONE_HUNDRED_PERCENT_IN_BP} from "./constants/NumericConstants.sol"; // Enums -import { QuoteType } from "./enums/QuoteType.sol"; +import {QuoteType} from "./enums/QuoteType.sol"; /** * @title LooksRareProtocol @@ -103,7 +111,7 @@ contract LooksRareProtocol is * If a standard ETH transfer fails within this gas limit, ETH will get wrapped to WETH * and transferred to the initial recipient. */ - uint256 private _gasLimitETHTransfer = 2_300; + uint256 private _gasLimitETHTransfer = 2300; /** * @notice Constructor @@ -112,12 +120,9 @@ contract LooksRareProtocol is * @param _transferManager Transfer manager address * @param _weth Wrapped ETH address */ - constructor( - address _owner, - address _protocolFeeRecipient, - address _transferManager, - address _weth - ) TransferSelectorNFT(_owner, _protocolFeeRecipient, _transferManager) { + constructor(address _owner, address _protocolFeeRecipient, address _transferManager, address _weth) + TransferSelectorNFT(_owner, _protocolFeeRecipient, _transferManager) + { _updateDomainSeparator(); WETH = _weth; } @@ -129,8 +134,7 @@ contract LooksRareProtocol is OrderStructs.Taker calldata takerAsk, OrderStructs.Maker calldata makerBid, bytes calldata makerSignature, - OrderStructs.MerkleTree calldata merkleTree, - address affiliate + OrderStructs.MerkleTree calldata merkleTree ) external nonReentrant { address currency = makerBid.currency; @@ -147,7 +151,7 @@ contract LooksRareProtocol is uint256 totalProtocolFeeAmount = _executeTakerAsk(takerAsk, makerBid, orderHash); // Pay protocol fee (and affiliate fee if any) - _payProtocolFeeAndAffiliateFee(currency, signer, affiliate, totalProtocolFeeAmount); + _payProtocolFeeAndAffiliateFee(currency, signer, totalProtocolFeeAmount); } /** @@ -157,8 +161,7 @@ contract LooksRareProtocol is OrderStructs.Taker calldata takerBid, OrderStructs.Maker calldata makerAsk, bytes calldata makerSignature, - OrderStructs.MerkleTree calldata merkleTree, - address affiliate + OrderStructs.MerkleTree calldata merkleTree ) external payable nonReentrant { address currency = makerAsk.currency; @@ -173,8 +176,8 @@ contract LooksRareProtocol is // Execute the transaction and fetch protocol fee amount uint256 totalProtocolFeeAmount = _executeTakerBid(takerBid, makerAsk, msg.sender, orderHash); - // Pay protocol fee amount (and affiliate fee if any) - _payProtocolFeeAndAffiliateFee(currency, msg.sender, affiliate, totalProtocolFeeAmount); + // Pay protocol fee amount + _payProtocolFeeAndAffiliateFee(currency, msg.sender, totalProtocolFeeAmount); // Return ETH if any _returnETHIfAnyWithOneWeiLeft(); @@ -188,13 +191,12 @@ contract LooksRareProtocol is OrderStructs.Maker[] calldata makerAsks, bytes[] calldata makerSignatures, OrderStructs.MerkleTree[] calldata merkleTrees, - address affiliate, bool isAtomic ) external payable nonReentrant { uint256 length = takerBids.length; if ( - length == 0 || - (makerAsks.length ^ length) | (makerSignatures.length ^ length) | (merkleTrees.length ^ length) != 0 + length == 0 + || (makerAsks.length ^ length) | (makerSignatures.length ^ length) | (merkleTrees.length ^ length) != 0 ) { revert LengthsInvalid(); } @@ -212,7 +214,7 @@ contract LooksRareProtocol is // If atomic, it uses the executeTakerBid function. // If not atomic, it uses a catch/revert pattern with external function. if (isAtomic) { - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { OrderStructs.Maker calldata makerAsk = makerAsks[i]; // Verify the currency is the same @@ -237,7 +239,7 @@ contract LooksRareProtocol is } } } else { - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { OrderStructs.Maker calldata makerAsk = makerAsks[i]; // Verify the currency is the same @@ -267,7 +269,7 @@ contract LooksRareProtocol is } // Pay protocol fee (and affiliate fee if any) - _payProtocolFeeAndAffiliateFee(currency, msg.sender, affiliate, totalProtocolFeeAmount); + _payProtocolFeeAndAffiliateFee(currency, msg.sender, totalProtocolFeeAmount); } // Return ETH if any @@ -316,7 +318,7 @@ contract LooksRareProtocol is * @dev Only callable by owner. */ function updateETHGasLimitForTransfer(uint256 newGasLimitETHTransfer) external onlyOwner { - if (newGasLimitETHTransfer < 2_300) { + if (newGasLimitETHTransfer < 2300) { revert NewGasLimitETHTransferTooLow(); } @@ -346,9 +348,9 @@ contract LooksRareProtocol is bytes32 userOrderNonceStatus = userOrderNonce[signer][makerBid.orderNonce]; // Verify nonces if ( - userBidAskNonces[signer].bidNonce != makerBid.globalNonce || - userSubsetNonce[signer][makerBid.subsetNonce] || - (userOrderNonceStatus != bytes32(0) && userOrderNonceStatus != orderHash) + userBidAskNonces[signer].bidNonce != makerBid.globalNonce + || userSubsetNonce[signer][makerBid.subsetNonce] + || (userOrderNonceStatus != bytes32(0) && userOrderNonceStatus != orderHash) ) { revert NoncesInvalid(); } @@ -416,9 +418,9 @@ contract LooksRareProtocol is bytes32 userOrderNonceStatus = userOrderNonce[signer][makerAsk.orderNonce]; if ( - userBidAskNonces[signer].askNonce != makerAsk.globalNonce || - userSubsetNonce[signer][makerAsk.subsetNonce] || - (userOrderNonceStatus != bytes32(0) && userOrderNonceStatus != orderHash) + userBidAskNonces[signer].askNonce != makerAsk.globalNonce + || userSubsetNonce[signer][makerAsk.subsetNonce] + || (userOrderNonceStatus != bytes32(0) && userOrderNonceStatus != orderHash) ) { revert NoncesInvalid(); } @@ -473,15 +475,11 @@ contract LooksRareProtocol is * @notice This function is internal and is used to pay the protocol fee and affiliate fee (if any). * @param currency Currency address to transfer (address(0) is ETH) * @param bidUser Bid user address - * @param affiliate Affiliate address (address(0) if none) * @param totalProtocolFeeAmount Total protocol fee amount (denominated in the currency) */ - function _payProtocolFeeAndAffiliateFee( - address currency, - address bidUser, - address affiliate, - uint256 totalProtocolFeeAmount - ) internal { + function _payProtocolFeeAndAffiliateFee(address currency, address bidUser, uint256 totalProtocolFeeAmount) + internal + { if (totalProtocolFeeAmount != 0) { // Transfer remaining protocol fee to the protocol fee recipient _transferFungibleTokens(currency, bidUser, protocolFeeRecipient, totalProtocolFeeAmount); @@ -563,12 +561,9 @@ contract LooksRareProtocol is * If it is equal to false, this function maps the order hash for this user order nonce * to prevent other order structs sharing the same order nonce to be executed. */ - function _updateUserOrderNonce( - bool isNonceInvalidated, - address signer, - uint256 orderNonce, - bytes32 orderHash - ) private { + function _updateUserOrderNonce(bool isNonceInvalidated, address signer, uint256 orderNonce, bytes32 orderHash) + private + { userOrderNonce[signer][orderNonce] = (isNonceInvalidated ? MAGIC_VALUE_ORDER_NONCE_EXECUTED : orderHash); } @@ -579,13 +574,14 @@ contract LooksRareProtocol is * @param makerSignature Signature of the maker * @param signer Signer address */ - function _computeDigestAndVerify(bytes32 computedHash, bytes calldata makerSignature, address signer) private view { + function _computeDigestAndVerify(bytes32 computedHash, bytes calldata makerSignature, address signer) + private + view + { if (chainId == block.chainid) { // \x19\x01 is the standard encoding prefix SignatureCheckerCalldata.verify( - keccak256(abi.encodePacked("\x19\x01", domainSeparator, computedHash)), - signer, - makerSignature + keccak256(abi.encodePacked("\x19\x01", domainSeparator, computedHash)), signer, makerSignature ); } else { revert ChainIdInvalid(); diff --git a/contracts/src/marketplace/NonceManager.sol b/contracts/src/marketplace/NonceManager.sol index bc3dda7a..d9a94cfc 100644 --- a/contracts/src/marketplace/NonceManager.sol +++ b/contracts/src/marketplace/NonceManager.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.17; // Interfaces and errors -import { INonceManager } from "./interfaces/INonceManager.sol"; -import { LengthsInvalid } from "./errors/SharedErrors.sol"; +import {INonceManager} from "./interfaces/INonceManager.sol"; +import {LengthsInvalid} from "./errors/SharedErrors.sol"; /** * @title NonceManager @@ -49,7 +49,7 @@ contract NonceManager is INonceManager { revert LengthsInvalid(); } - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { userOrderNonce[msg.sender][orderNonces[i]] = MAGIC_VALUE_ORDER_NONCE_EXECUTED; unchecked { ++i; @@ -71,7 +71,7 @@ contract NonceManager is INonceManager { revert LengthsInvalid(); } - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { userSubsetNonce[msg.sender][subsetNonces[i]] = true; unchecked { ++i; diff --git a/contracts/src/marketplace/ProtocolFeeRecipient.sol b/contracts/src/marketplace/ProtocolFeeRecipient.sol index 2d3d2c73..33cfceb4 100644 --- a/contracts/src/marketplace/ProtocolFeeRecipient.sol +++ b/contracts/src/marketplace/ProtocolFeeRecipient.sol @@ -2,9 +2,9 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { LowLevelERC20Transfer } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC20Transfer.sol"; -import { IWETH } from "@looksrare/contracts-libs/contracts/interfaces/generic/IWETH.sol"; -import { IERC20 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC20.sol"; +import {LowLevelERC20Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC20Transfer.sol"; +import {IWETH} from "@looksrare/contracts-libs/contracts/interfaces/generic/IWETH.sol"; +import {IERC20} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC20.sol"; /** * @title ProtocolFeeRecipient @@ -28,7 +28,7 @@ contract ProtocolFeeRecipient is LowLevelERC20Transfer { uint256 ethBalance = address(this).balance; if (ethBalance != 0) { - WETH.deposit{ value: ethBalance }(); + WETH.deposit{value: ethBalance}(); } uint256 wethBalance = IERC20(address(WETH)).balanceOf(address(this)); diff --git a/contracts/src/marketplace/StrategyManager.sol b/contracts/src/marketplace/StrategyManager.sol index c80af8df..4edb9d66 100644 --- a/contracts/src/marketplace/StrategyManager.sol +++ b/contracts/src/marketplace/StrategyManager.sol @@ -2,11 +2,11 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { CurrencyManager } from "./CurrencyManager.sol"; +import {CurrencyManager} from "./CurrencyManager.sol"; // Interfaces -import { IStrategy } from "./interfaces/IStrategy.sol"; -import { IStrategyManager } from "./interfaces/IStrategyManager.sol"; +import {IStrategy} from "./interfaces/IStrategy.sol"; +import {IStrategyManager} from "./interfaces/IStrategyManager.sol"; /** * @title StrategyManager @@ -103,12 +103,10 @@ contract StrategyManager is IStrategyManager, CurrencyManager { * @param newMinTotalFee New minimum total fee (in basis point) * @dev Only callable by owner. */ - function updateStrategy( - uint256 strategyId, - bool isActive, - uint16 newStandardProtocolFee, - uint16 newMinTotalFee - ) external onlyOwner { + function updateStrategy(uint256 strategyId, bool isActive, uint16 newStandardProtocolFee, uint16 newMinTotalFee) + external + onlyOwner + { if (strategyId >= _countStrategies) { revert StrategyNotUsed(); } diff --git a/contracts/src/marketplace/TransferManager.sol b/contracts/src/marketplace/TransferManager.sol index f0015e67..cc1c9578 100644 --- a/contracts/src/marketplace/TransferManager.sol +++ b/contracts/src/marketplace/TransferManager.sol @@ -2,23 +2,24 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { OwnableTwoSteps } from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol"; -import { LowLevelERC721Transfer } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC721Transfer.sol"; -import { LowLevelERC1155Transfer } from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC1155Transfer.sol"; +import {OwnableTwoSteps} from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol"; +import {LowLevelERC721Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC721Transfer.sol"; +import {LowLevelERC1155Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC1155Transfer.sol"; // Interfaces and errors -import { ITransferManager } from "./interfaces/ITransferManager.sol"; -import { AmountInvalid, LengthsInvalid } from "./errors/SharedErrors.sol"; +import {ITransferManager} from "./interfaces/ITransferManager.sol"; +import {AmountInvalid, LengthsInvalid} from "./errors/SharedErrors.sol"; // Libraries -import { OrderStructs } from "./libraries/OrderStructs.sol"; +import {OrderStructs} from "./libraries/OrderStructs.sol"; // Enums -import { CollectionType } from "./enums/CollectionType.sol"; +import {CollectionType} from "./enums/CollectionType.sol"; /** * @title TransferManager - * @notice This contract provides the transfer functions for ERC721/ERC1155/Hypercert/Hyperboard for contracts that require them. + * @notice This contract provides the transfer functions for ERC721/ERC1155/Hypercert/Hyperboard for contracts that + * require them. * Collection type "0" refers to ERC721 transfer functions. * Collection type "1" refers to ERC1155 transfer functions. * Collection type "2" refers to Hypercert transfer functions. @@ -68,7 +69,7 @@ contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelER _isOperatorValidForTransfer(from, msg.sender); - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { if (amounts[i] != 1) { revert AmountInvalid(); } @@ -109,7 +110,7 @@ contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelER } _executeERC1155SafeTransferFrom(collection, from, to, itemIds[0], amounts[0]); } else { - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { if (amounts[i] == 0) { revert AmountInvalid(); } @@ -152,7 +153,7 @@ contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelER } _executeERC1155SafeTransferFrom(collection, from, to, itemIds[0], amounts[0]); } else { - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { if (amounts[i] == 0) { revert AmountInvalid(); } @@ -195,7 +196,7 @@ contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelER } _executeERC1155SafeTransferFrom(collection, from, to, itemIds[0], amounts[0]); } else { - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { if (amounts[i] == 0) { revert AmountInvalid(); } @@ -214,11 +215,9 @@ contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelER * @param from Sender address * @param to Recipient address */ - function transferBatchItemsAcrossCollections( - BatchTransferItem[] calldata items, - address from, - address to - ) external { + function transferBatchItemsAcrossCollections(BatchTransferItem[] calldata items, address from, address to) + external + { uint256 itemsLength = items.length; if (itemsLength == 0) { @@ -229,7 +228,7 @@ contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelER _isOperatorValidForTransfer(from, msg.sender); } - for (uint256 i; i < itemsLength; ) { + for (uint256 i; i < itemsLength;) { uint256[] calldata itemIds = items[i].itemIds; uint256 itemIdsLengthForSingleCollection = itemIds.length; uint256[] calldata amounts = items[i].amounts; @@ -240,7 +239,7 @@ contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelER CollectionType collectionType = items[i].collectionType; if (collectionType == CollectionType.ERC721) { - for (uint256 j; j < itemIdsLengthForSingleCollection; ) { + for (uint256 j; j < itemIdsLengthForSingleCollection;) { if (amounts[j] != 1) { revert AmountInvalid(); } @@ -250,7 +249,7 @@ contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelER } } } else if (collectionType == CollectionType.ERC1155) { - for (uint256 j; j < itemIdsLengthForSingleCollection; ) { + for (uint256 j; j < itemIdsLengthForSingleCollection;) { if (amounts[j] == 0) { revert AmountInvalid(); } @@ -281,7 +280,7 @@ contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelER revert LengthsInvalid(); } - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { address operator = operators[i]; if (!isOperatorAllowed[operator]) { @@ -313,7 +312,7 @@ contract TransferManager is ITransferManager, LowLevelERC721Transfer, LowLevelER revert LengthsInvalid(); } - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { address operator = operators[i]; if (!hasUserApprovedOperator[msg.sender][operator]) { diff --git a/contracts/src/marketplace/TransferSelectorNFT.sol b/contracts/src/marketplace/TransferSelectorNFT.sol index 5e504203..8b4d201c 100644 --- a/contracts/src/marketplace/TransferSelectorNFT.sol +++ b/contracts/src/marketplace/TransferSelectorNFT.sol @@ -2,15 +2,15 @@ pragma solidity 0.8.17; // Direct dependencies -import { PackableReentrancyGuard } from "@looksrare/contracts-libs/contracts/PackableReentrancyGuard.sol"; -import { ExecutionManager } from "./ExecutionManager.sol"; -import { TransferManager } from "./TransferManager.sol"; +import {PackableReentrancyGuard} from "@looksrare/contracts-libs/contracts/PackableReentrancyGuard.sol"; +import {ExecutionManager} from "./ExecutionManager.sol"; +import {TransferManager} from "./TransferManager.sol"; // Libraries -import { OrderStructs } from "./libraries/OrderStructs.sol"; +import {OrderStructs} from "./libraries/OrderStructs.sol"; // Enums -import { CollectionType } from "./enums/CollectionType.sol"; +import {CollectionType} from "./enums/CollectionType.sol"; /** * @title TransferSelectorNFT @@ -31,11 +31,9 @@ contract TransferSelectorNFT is ExecutionManager, PackableReentrancyGuard { * @param _protocolFeeRecipient Protocol fee recipient address * @param _transferManager Address of the transfer manager for ERC721/ERC1155 */ - constructor( - address _owner, - address _protocolFeeRecipient, - address _transferManager - ) ExecutionManager(_owner, _protocolFeeRecipient) { + constructor(address _owner, address _protocolFeeRecipient, address _transferManager) + ExecutionManager(_owner, _protocolFeeRecipient) + { transferManager = TransferManager(_transferManager); } diff --git a/contracts/src/marketplace/executionStrategies/BaseStrategy.sol b/contracts/src/marketplace/executionStrategies/BaseStrategy.sol index 75ce5f87..9d0bec3c 100644 --- a/contracts/src/marketplace/executionStrategies/BaseStrategy.sol +++ b/contracts/src/marketplace/executionStrategies/BaseStrategy.sol @@ -2,16 +2,16 @@ pragma solidity 0.8.17; // Interfaces -import { IStrategy } from "../interfaces/IStrategy.sol"; +import {IStrategy} from "../interfaces/IStrategy.sol"; // Assembly constants -import { OrderInvalid_error_selector } from "../constants/AssemblyConstants.sol"; +import {OrderInvalid_error_selector} from "../constants/AssemblyConstants.sol"; // Libraries -import { OrderStructs } from "../libraries/OrderStructs.sol"; +import {OrderStructs} from "../libraries/OrderStructs.sol"; // Enums -import { CollectionType } from "../enums/CollectionType.sol"; +import {CollectionType} from "../enums/CollectionType.sol"; /** * @title BaseStrategy diff --git a/contracts/src/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.sol b/contracts/src/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.sol index f95a5c12..09cb3dc3 100644 --- a/contracts/src/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.sol +++ b/contracts/src/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { OwnableTwoSteps } from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol"; +import {OwnableTwoSteps} from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol"; /** * @title BaseStrategyChainlinkPriceLatency diff --git a/contracts/src/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol b/contracts/src/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol index ad6b9f9d..137c1e86 100644 --- a/contracts/src/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol +++ b/contracts/src/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol @@ -2,22 +2,28 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "../../libraries/OrderStructs.sol"; -import { CurrencyValidator } from "../../libraries/CurrencyValidator.sol"; +import {OrderStructs} from "../../libraries/OrderStructs.sol"; +import {CurrencyValidator} from "../../libraries/CurrencyValidator.sol"; // Interfaces -import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; +import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; // Enums -import { QuoteType } from "../../enums/QuoteType.sol"; +import {QuoteType} from "../../enums/QuoteType.sol"; // Shared errors -import { BidTooLow, OrderInvalid, CurrencyInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "../../errors/SharedErrors.sol"; -import { ChainlinkPriceInvalid, PriceFeedNotAvailable, PriceNotRecentEnough } from "../../errors/ChainlinkErrors.sol"; +import { + BidTooLow, + OrderInvalid, + CurrencyInvalid, + FunctionSelectorInvalid, + QuoteTypeInvalid +} from "../../errors/SharedErrors.sol"; +import {ChainlinkPriceInvalid, PriceFeedNotAvailable, PriceNotRecentEnough} from "../../errors/ChainlinkErrors.sol"; // Base strategy contracts -import { BaseStrategy, IStrategy } from "../BaseStrategy.sol"; -import { BaseStrategyChainlinkPriceLatency } from "./BaseStrategyChainlinkPriceLatency.sol"; +import {BaseStrategy, IStrategy} from "../BaseStrategy.sol"; +import {BaseStrategyChainlinkPriceLatency} from "./BaseStrategyChainlinkPriceLatency.sol"; /** * @title StrategyChainlinkUSDDynamicAsk @@ -47,7 +53,7 @@ contract StrategyChainlinkUSDDynamicAsk is BaseStrategy, BaseStrategyChainlinkPr * @param _owner Owner address * @param _priceFeed Address of the ETH/USD price feed */ - constructor(address _owner, address _weth, address _priceFeed) BaseStrategyChainlinkPriceLatency(_owner, 3_600) { + constructor(address _owner, address _weth, address _priceFeed) BaseStrategyChainlinkPriceLatency(_owner, 3600) { WETH = _weth; priceFeed = AggregatorV3Interface(_priceFeed); } @@ -61,10 +67,7 @@ contract StrategyChainlinkUSDDynamicAsk is BaseStrategy, BaseStrategyChainlinkPr * @param makerAsk Maker ask struct (maker ask-specific parameters for the execution) * @dev The client has to provide the seller's desired sale price in USD as the additionalParameters */ - function executeStrategyWithTakerBid( - OrderStructs.Taker calldata takerBid, - OrderStructs.Maker calldata makerAsk - ) + function executeStrategyWithTakerBid(OrderStructs.Taker calldata takerBid, OrderStructs.Maker calldata makerAsk) external view returns (uint256 price, uint256[] memory itemIds, uint256[] memory amounts, bool isNonceInvalidated) @@ -77,7 +80,7 @@ contract StrategyChainlinkUSDDynamicAsk is BaseStrategy, BaseStrategyChainlinkPr CurrencyValidator.allowNativeOrAllowedCurrency(makerAsk.currency, WETH); - (, int256 answer, , uint256 updatedAt, ) = priceFeed.latestRoundData(); + (, int256 answer,, uint256 updatedAt,) = priceFeed.latestRoundData(); if (answer <= 0) { revert ChainlinkPriceInvalid(); @@ -113,10 +116,12 @@ contract StrategyChainlinkUSDDynamicAsk is BaseStrategy, BaseStrategyChainlinkPr /** * @inheritdoc IStrategy */ - function isMakerOrderValid( - OrderStructs.Maker calldata makerAsk, - bytes4 functionSelector - ) external view override returns (bool isValid, bytes4 errorSelector) { + function isMakerOrderValid(OrderStructs.Maker calldata makerAsk, bytes4 functionSelector) + external + view + override + returns (bool isValid, bytes4 errorSelector) + { if (functionSelector != StrategyChainlinkUSDDynamicAsk.executeStrategyWithTakerBid.selector) { return (isValid, FunctionSelectorInvalid.selector); } @@ -131,7 +136,7 @@ contract StrategyChainlinkUSDDynamicAsk is BaseStrategy, BaseStrategyChainlinkPr return (isValid, OrderInvalid.selector); } - for (uint256 i; i < itemIdsLength; ) { + for (uint256 i; i < itemIdsLength;) { _validateAmountNoRevert(makerAsk.amounts[i], makerAsk.collectionType); unchecked { ++i; @@ -144,7 +149,7 @@ contract StrategyChainlinkUSDDynamicAsk is BaseStrategy, BaseStrategyChainlinkPr } } - (, int256 answer, , uint256 updatedAt, ) = priceFeed.latestRoundData(); + (, int256 answer,, uint256 updatedAt,) = priceFeed.latestRoundData(); if (answer <= 0) { return (isValid, ChainlinkPriceInvalid.selector); diff --git a/contracts/src/marketplace/executionStrategies/StrategyCollectionOffer.sol b/contracts/src/marketplace/executionStrategies/StrategyCollectionOffer.sol index 90b3b872..9f0d04bf 100644 --- a/contracts/src/marketplace/executionStrategies/StrategyCollectionOffer.sol +++ b/contracts/src/marketplace/executionStrategies/StrategyCollectionOffer.sol @@ -2,19 +2,19 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "../libraries/OrderStructs.sol"; +import {OrderStructs} from "../libraries/OrderStructs.sol"; // OpenZeppelin's library for verifying Merkle proofs -import { MerkleProofMemory } from "../libraries/OpenZeppelin/MerkleProofMemory.sol"; +import {MerkleProofMemory} from "../libraries/OpenZeppelin/MerkleProofMemory.sol"; // Enums -import { QuoteType } from "../enums/QuoteType.sol"; +import {QuoteType} from "../enums/QuoteType.sol"; // Shared errors -import { OrderInvalid, FunctionSelectorInvalid, MerkleProofInvalid, QuoteTypeInvalid } from "../errors/SharedErrors.sol"; +import {OrderInvalid, FunctionSelectorInvalid, MerkleProofInvalid, QuoteTypeInvalid} from "../errors/SharedErrors.sol"; // Base strategy contracts -import { BaseStrategy, IStrategy } from "./BaseStrategy.sol"; +import {BaseStrategy, IStrategy} from "./BaseStrategy.sol"; /** * @title StrategyCollectionOffer @@ -83,10 +83,8 @@ contract StrategyCollectionOffer is BaseStrategy { revert OrderInvalid(); } - (uint256 offeredItemId, bytes32[] memory proof) = abi.decode( - takerAsk.additionalParameters, - (uint256, bytes32[]) - ); + (uint256 offeredItemId, bytes32[] memory proof) = + abi.decode(takerAsk.additionalParameters, (uint256, bytes32[])); itemIds = new uint256[](1); itemIds[0] = offeredItemId; isNonceInvalidated = true; @@ -103,13 +101,15 @@ contract StrategyCollectionOffer is BaseStrategy { /** * @inheritdoc IStrategy */ - function isMakerOrderValid( - OrderStructs.Maker calldata makerBid, - bytes4 functionSelector - ) external pure override returns (bool isValid, bytes4 errorSelector) { + function isMakerOrderValid(OrderStructs.Maker calldata makerBid, bytes4 functionSelector) + external + pure + override + returns (bool isValid, bytes4 errorSelector) + { if ( - functionSelector != StrategyCollectionOffer.executeCollectionStrategyWithTakerAskWithProof.selector && - functionSelector != StrategyCollectionOffer.executeCollectionStrategyWithTakerAsk.selector + functionSelector != StrategyCollectionOffer.executeCollectionStrategyWithTakerAskWithProof.selector + && functionSelector != StrategyCollectionOffer.executeCollectionStrategyWithTakerAsk.selector ) { return (isValid, FunctionSelectorInvalid.selector); } @@ -127,8 +127,8 @@ contract StrategyCollectionOffer is BaseStrategy { // If no root is provided or invalid length, it should be invalid. // @dev It does not mean the merkle root is valid against a specific itemId that exists in the collection. if ( - functionSelector == StrategyCollectionOffer.executeCollectionStrategyWithTakerAskWithProof.selector && - makerBid.additionalParameters.length != 32 + functionSelector == StrategyCollectionOffer.executeCollectionStrategyWithTakerAskWithProof.selector + && makerBid.additionalParameters.length != 32 ) { return (isValid, OrderInvalid.selector); } diff --git a/contracts/src/marketplace/executionStrategies/StrategyDutchAuction.sol b/contracts/src/marketplace/executionStrategies/StrategyDutchAuction.sol index 377539c0..3c4fcf27 100644 --- a/contracts/src/marketplace/executionStrategies/StrategyDutchAuction.sol +++ b/contracts/src/marketplace/executionStrategies/StrategyDutchAuction.sol @@ -2,16 +2,16 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "../libraries/OrderStructs.sol"; +import {OrderStructs} from "../libraries/OrderStructs.sol"; // Enums -import { QuoteType } from "../enums/QuoteType.sol"; +import {QuoteType} from "../enums/QuoteType.sol"; // Shared errors -import { BidTooLow, OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "../errors/SharedErrors.sol"; +import {BidTooLow, OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid} from "../errors/SharedErrors.sol"; // Base strategy contracts -import { BaseStrategy, IStrategy } from "./BaseStrategy.sol"; +import {BaseStrategy, IStrategy} from "./BaseStrategy.sol"; /** * @title StrategyDutchAuction @@ -27,10 +27,7 @@ contract StrategyDutchAuction is BaseStrategy { * @param makerAsk Maker ask struct (maker bid-specific parameters for the execution) * @dev The client has to provide the seller's desired initial start price as the additionalParameters. */ - function executeStrategyWithTakerBid( - OrderStructs.Taker calldata takerBid, - OrderStructs.Maker calldata makerAsk - ) + function executeStrategyWithTakerBid(OrderStructs.Taker calldata takerBid, OrderStructs.Maker calldata makerAsk) external view returns (uint256 price, uint256[] memory itemIds, uint256[] memory amounts, bool isNonceInvalidated) @@ -50,9 +47,8 @@ contract StrategyDutchAuction is BaseStrategy { uint256 startTime = makerAsk.startTime; uint256 endTime = makerAsk.endTime; - price = - ((endTime - block.timestamp) * startPrice + (block.timestamp - startTime) * makerAsk.price) / - (endTime - startTime); + price = ((endTime - block.timestamp) * startPrice + (block.timestamp - startTime) * makerAsk.price) + / (endTime - startTime); uint256 maxPrice = abi.decode(takerBid.additionalParameters, (uint256)); if (maxPrice < price) { @@ -68,10 +64,12 @@ contract StrategyDutchAuction is BaseStrategy { /** * @inheritdoc IStrategy */ - function isMakerOrderValid( - OrderStructs.Maker calldata makerAsk, - bytes4 functionSelector - ) external pure override returns (bool isValid, bytes4 errorSelector) { + function isMakerOrderValid(OrderStructs.Maker calldata makerAsk, bytes4 functionSelector) + external + pure + override + returns (bool isValid, bytes4 errorSelector) + { if (functionSelector != StrategyDutchAuction.executeStrategyWithTakerBid.selector) { return (isValid, FunctionSelectorInvalid.selector); } @@ -86,7 +84,7 @@ contract StrategyDutchAuction is BaseStrategy { return (isValid, OrderInvalid.selector); } - for (uint256 i; i < itemIdsLength; ) { + for (uint256 i; i < itemIdsLength;) { _validateAmountNoRevert(makerAsk.amounts[i], makerAsk.collectionType); unchecked { ++i; diff --git a/contracts/src/marketplace/executionStrategies/StrategyItemIdsRange.sol b/contracts/src/marketplace/executionStrategies/StrategyItemIdsRange.sol index 81ffd51d..96470011 100644 --- a/contracts/src/marketplace/executionStrategies/StrategyItemIdsRange.sol +++ b/contracts/src/marketplace/executionStrategies/StrategyItemIdsRange.sol @@ -2,16 +2,16 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "../libraries/OrderStructs.sol"; +import {OrderStructs} from "../libraries/OrderStructs.sol"; // Enums -import { QuoteType } from "../enums/QuoteType.sol"; +import {QuoteType} from "../enums/QuoteType.sol"; // Shared errors -import { OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "../errors/SharedErrors.sol"; +import {OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid} from "../errors/SharedErrors.sol"; // Base strategy contracts -import { BaseStrategy, IStrategy } from "./BaseStrategy.sol"; +import {BaseStrategy, IStrategy} from "./BaseStrategy.sol"; /** * @title StrategyItemIdsRange @@ -29,10 +29,7 @@ contract StrategyItemIdsRange is BaseStrategy { * @param takerAsk Taker ask struct (taker ask-specific parameters for the execution) * @param makerBid Maker bid struct (maker bid-specific parameters for the execution) */ - function executeStrategyWithTakerAsk( - OrderStructs.Taker calldata takerAsk, - OrderStructs.Maker calldata makerBid - ) + function executeStrategyWithTakerAsk(OrderStructs.Taker calldata takerAsk, OrderStructs.Maker calldata makerBid) external pure returns (uint256 price, uint256[] memory itemIds, uint256[] memory amounts, bool isNonceInvalidated) @@ -43,10 +40,8 @@ contract StrategyItemIdsRange is BaseStrategy { revert OrderInvalid(); } - (uint256 minItemId, uint256 maxItemId, uint256 desiredAmount) = abi.decode( - makerBid.additionalParameters, - (uint256, uint256, uint256) - ); + (uint256 minItemId, uint256 maxItemId, uint256 desiredAmount) = + abi.decode(makerBid.additionalParameters, (uint256, uint256, uint256)); if (minItemId >= maxItemId || desiredAmount == 0) { revert OrderInvalid(); @@ -55,7 +50,7 @@ contract StrategyItemIdsRange is BaseStrategy { uint256 totalOfferedAmount; uint256 lastItemId; - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { uint256 offeredItemId = itemIds[i]; // Force the client to sort the item ids in ascending order, // in order to prevent taker ask from providing duplicated @@ -90,10 +85,12 @@ contract StrategyItemIdsRange is BaseStrategy { /** * @inheritdoc IStrategy */ - function isMakerOrderValid( - OrderStructs.Maker calldata makerBid, - bytes4 functionSelector - ) external pure override returns (bool isValid, bytes4 errorSelector) { + function isMakerOrderValid(OrderStructs.Maker calldata makerBid, bytes4 functionSelector) + external + pure + override + returns (bool isValid, bytes4 errorSelector) + { if (functionSelector != StrategyItemIdsRange.executeStrategyWithTakerAsk.selector) { return (isValid, FunctionSelectorInvalid.selector); } @@ -102,10 +99,8 @@ contract StrategyItemIdsRange is BaseStrategy { return (isValid, QuoteTypeInvalid.selector); } - (uint256 minItemId, uint256 maxItemId, uint256 desiredAmount) = abi.decode( - makerBid.additionalParameters, - (uint256, uint256, uint256) - ); + (uint256 minItemId, uint256 maxItemId, uint256 desiredAmount) = + abi.decode(makerBid.additionalParameters, (uint256, uint256, uint256)); if (minItemId >= maxItemId || desiredAmount == 0) { return (isValid, OrderInvalid.selector); diff --git a/contracts/src/marketplace/helpers/OrderValidatorV2A.sol b/contracts/src/marketplace/helpers/OrderValidatorV2A.sol index 2d917b34..808a8386 100644 --- a/contracts/src/marketplace/helpers/OrderValidatorV2A.sol +++ b/contracts/src/marketplace/helpers/OrderValidatorV2A.sol @@ -2,35 +2,35 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IERC165 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC165.sol"; -import { IERC20 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC20.sol"; -import { IERC721 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC721.sol"; -import { IERC1155 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC1155.sol"; -import { IERC1271 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC1271.sol"; +import {IERC165} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC165.sol"; +import {IERC20} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC20.sol"; +import {IERC721} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC721.sol"; +import {IERC1155} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC1155.sol"; +import {IERC1271} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC1271.sol"; // Libraries -import { OrderStructs } from "../libraries/OrderStructs.sol"; -import { MerkleProofCalldataWithNodes } from "../libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol"; +import {OrderStructs} from "../libraries/OrderStructs.sol"; +import {MerkleProofCalldataWithNodes} from "../libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol"; // Interfaces -import { ICreatorFeeManager } from "../interfaces/ICreatorFeeManager.sol"; -import { IStrategy } from "../interfaces/IStrategy.sol"; -import { IRoyaltyFeeRegistry } from "../interfaces/IRoyaltyFeeRegistry.sol"; +import {ICreatorFeeManager} from "../interfaces/ICreatorFeeManager.sol"; +import {IStrategy} from "../interfaces/IStrategy.sol"; +import {IRoyaltyFeeRegistry} from "../interfaces/IRoyaltyFeeRegistry.sol"; // Shared errors -import { OrderInvalid } from "../errors/SharedErrors.sol"; +import {OrderInvalid} from "../errors/SharedErrors.sol"; // Other dependencies -import { LooksRareProtocol } from "../LooksRareProtocol.sol"; -import { TransferManager } from "../TransferManager.sol"; +import {LooksRareProtocol} from "../LooksRareProtocol.sol"; +import {TransferManager} from "../TransferManager.sol"; // Constants import "../constants/ValidationCodeConstants.sol"; -import { MAX_CALLDATA_PROOF_LENGTH, ONE_HUNDRED_PERCENT_IN_BP } from "../constants/NumericConstants.sol"; +import {MAX_CALLDATA_PROOF_LENGTH, ONE_HUNDRED_PERCENT_IN_BP} from "../constants/NumericConstants.sol"; // Enums -import { CollectionType } from "../enums/CollectionType.sol"; -import { QuoteType } from "../enums/QuoteType.sol"; +import {CollectionType} from "../enums/CollectionType.sol"; +import {QuoteType} from "../enums/QuoteType.sol"; /** * @title OrderValidatorV2A @@ -138,7 +138,7 @@ contract OrderValidatorV2A { validationCodes = new uint256[CRITERIA_GROUPS][](length); - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { validationCodes[i] = checkMakerOrderValidity(makerOrders[i], signatures[i], merkleTrees[i]); unchecked { ++i; @@ -160,11 +160,8 @@ contract OrderValidatorV2A { ) public view returns (uint256[9] memory validationCodes) { bytes32 orderHash = makerOrder.hash(); - validationCodes[0] = _checkValidityCurrencyAndStrategy( - makerOrder.quoteType, - makerOrder.currency, - makerOrder.strategyId - ); + validationCodes[0] = + _checkValidityCurrencyAndStrategy(makerOrder.quoteType, makerOrder.currency, makerOrder.strategyId); // It will exit here if the strategy does not exist. // However, if the strategy is implemented but invalid (except if wrong quote type), @@ -181,7 +178,7 @@ contract OrderValidatorV2A { if (makerOrder.quoteType == QuoteType.Ask) { (validationCode1, itemIds, amounts, price) = _checkValidityMakerAskItemIdsAndAmountsAndPrice(makerOrder); } else { - (validationCode1, itemIds, , price) = _checkValidityMakerBidItemIdsAndAmountsAndPrice(makerOrder); + (validationCode1, itemIds,, price) = _checkValidityMakerBidItemIdsAndAmountsAndPrice(makerOrder); } validationCodes[1] = validationCode1; @@ -205,11 +202,7 @@ contract OrderValidatorV2A { validationCodes[5] = _checkValidityMakerBidERC20Assets(makerOrder.currency, makerOrder.signer, price); } else { validationCodes[5] = _checkValidityMakerAskNFTAssets( - makerOrder.collection, - makerOrder.collectionType, - makerOrder.signer, - itemIds, - amounts + makerOrder.collection, makerOrder.collectionType, makerOrder.signer, itemIds, amounts ); } @@ -284,11 +277,11 @@ contract OrderValidatorV2A { * @param strategyId Strategy id * @return validationCode Validation code */ - function _checkValidityCurrencyAndStrategy( - QuoteType quoteType, - address currency, - uint256 strategyId - ) private view returns (uint256 validationCode) { + function _checkValidityCurrencyAndStrategy(QuoteType quoteType, address currency, uint256 strategyId) + private + view + returns (uint256 validationCode) + { // 1. Verify whether the currency is allowed if (!looksRareProtocol.isCurrencyAllowed(currency)) { return CURRENCY_NOT_ALLOWED; @@ -299,8 +292,8 @@ contract OrderValidatorV2A { } // 2. Verify whether the strategy is valid - (bool strategyIsActive, , , , , bool strategyIsMakerBid, address strategyImplementation) = looksRareProtocol - .strategyInfo(strategyId); + (bool strategyIsActive,,,,, bool strategyIsMakerBid, address strategyImplementation) = + looksRareProtocol.strategyInfo(strategyId); if (strategyId != 0 && strategyImplementation == address(0)) { return STRATEGY_NOT_IMPLEMENTED; @@ -308,8 +301,8 @@ contract OrderValidatorV2A { if (strategyId != 0) { if ( - (strategyIsMakerBid && quoteType != QuoteType.Bid) || - (!strategyIsMakerBid && quoteType != QuoteType.Ask) + (strategyIsMakerBid && quoteType != QuoteType.Bid) + || (!strategyIsMakerBid && quoteType != QuoteType.Ask) ) { return STRATEGY_INVALID_QUOTE_TYPE; } @@ -326,10 +319,11 @@ contract OrderValidatorV2A { * @param endTime End time * @return validationCode Validation code */ - function _checkValidityTimestamps( - uint256 startTime, - uint256 endTime - ) private view returns (uint256 validationCode) { + function _checkValidityTimestamps(uint256 startTime, uint256 endTime) + private + view + returns (uint256 validationCode) + { // @dev It is possible for startTime to be equal to endTime. // If so, the execution only succeeds when the startTime = endTime = block.timestamp. // For order invalidation, if the call succeeds, it is already too late for later execution since the @@ -355,13 +349,14 @@ contract OrderValidatorV2A { * (i.e. collections that are tradable but do not implement the proper interfaceId). * If ERC165 is not implemented, it will revert. */ - function _checkIfPotentialInvalidCollectionTypes( - address collection, - CollectionType collectionType - ) private view returns (uint256 validationCode) { + function _checkIfPotentialInvalidCollectionTypes(address collection, CollectionType collectionType) + private + view + returns (uint256 validationCode) + { if (collectionType == CollectionType.ERC721) { - bool isERC721 = IERC165(collection).supportsInterface(ERC721_INTERFACE_ID_1) || - IERC165(collection).supportsInterface(ERC721_INTERFACE_ID_2); + bool isERC721 = IERC165(collection).supportsInterface(ERC721_INTERFACE_ID_1) + || IERC165(collection).supportsInterface(ERC721_INTERFACE_ID_2); if (!isERC721) { return POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC721; @@ -381,11 +376,11 @@ contract OrderValidatorV2A { * @param price Price (defined by the maker order) * @return validationCode Validation code */ - function _checkValidityMakerBidERC20Assets( - address currency, - address user, - uint256 price - ) private view returns (uint256 validationCode) { + function _checkValidityMakerBidERC20Assets(address currency, address user, uint256 price) + private + view + returns (uint256 validationCode) + { if (currency != address(0)) { if (IERC20(currency).balanceOf(user) < price) { return ERC20_BALANCE_INFERIOR_TO_PRICE; @@ -434,18 +429,18 @@ contract OrderValidatorV2A { * @param itemIds Array of item ids * @return validationCode Validation code */ - function _checkValidityERC721AndEquivalents( - address collection, - address user, - uint256[] memory itemIds - ) private view returns (uint256 validationCode) { + function _checkValidityERC721AndEquivalents(address collection, address user, uint256[] memory itemIds) + private + view + returns (uint256 validationCode) + { // 1. Verify itemId is owned by user and catch revertion if ERC721 ownerOf fails uint256 length = itemIds.length; bool success; bytes memory data; - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { (success, data) = collection.staticcall(abi.encodeCall(IERC721.ownerOf, (itemIds[i]))); if (!success) { @@ -462,9 +457,8 @@ contract OrderValidatorV2A { } // 2. Verify if collection is approved by transfer manager - (success, data) = collection.staticcall( - abi.encodeCall(IERC721.isApprovedForAll, (user, address(transferManager))) - ); + (success, data) = + collection.staticcall(abi.encodeCall(IERC721.isApprovedForAll, (user, address(transferManager)))); bool isApprovedAll; if (success) { @@ -472,7 +466,7 @@ contract OrderValidatorV2A { } if (!isApprovedAll) { - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { // 3. If collection is not approved by transfer manager, try to see if it is approved individually (success, data) = collection.staticcall(abi.encodeCall(IERC721.getApproved, (itemIds[i]))); @@ -502,12 +496,11 @@ contract OrderValidatorV2A { * @param amounts Array of amounts * @return validationCode Validation code */ - function _checkValidityERC1155( - address collection, - address user, - uint256[] memory itemIds, - uint256[] memory amounts - ) private view returns (uint256 validationCode) { + function _checkValidityERC1155(address collection, address user, uint256[] memory itemIds, uint256[] memory amounts) + private + view + returns (uint256 validationCode) + { // 1. Verify each itemId is owned by user and catch revertion if ERC1155 ownerOf fails address[] memory users = new address[](1); users[0] = user; @@ -515,13 +508,12 @@ contract OrderValidatorV2A { uint256 length = itemIds.length; // 1.1 Use balanceOfBatch - (bool success, bytes memory data) = collection.staticcall( - abi.encodeCall(IERC1155.balanceOfBatch, (users, itemIds)) - ); + (bool success, bytes memory data) = + collection.staticcall(abi.encodeCall(IERC1155.balanceOfBatch, (users, itemIds))); if (success) { uint256[] memory balances = abi.decode(data, (uint256[])); - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { if (balances[i] < amounts[i]) { return ERC1155_BALANCE_OF_ITEM_ID_INFERIOR_TO_AMOUNT; } @@ -531,7 +523,7 @@ contract OrderValidatorV2A { } } else { // 1.2 If the balanceOfBatch does not work, use loop with balanceOf function - for (uint256 i; i < length; ) { + for (uint256 i; i < length;) { (success, data) = collection.staticcall(abi.encodeCall(IERC1155.balanceOf, (user, itemIds[i]))); if (!success) { @@ -549,9 +541,8 @@ contract OrderValidatorV2A { } // 2. Verify if collection is approved by transfer manager - (success, data) = collection.staticcall( - abi.encodeCall(IERC1155.isApprovedForAll, (user, address(transferManager))) - ); + (success, data) = + collection.staticcall(abi.encodeCall(IERC1155.isApprovedForAll, (user, address(transferManager)))); if (!success) { return ERC1155_IS_APPROVED_FOR_ALL_DOES_NOT_EXIST; @@ -599,11 +590,11 @@ contract OrderValidatorV2A { * @param itemIds Item ids * @return validationCode Validation code */ - function _checkValidityCreatorFee( - address collection, - uint256 price, - uint256[] memory itemIds - ) private view returns (uint256 validationCode) { + function _checkValidityCreatorFee(address collection, uint256 price, uint256[] memory itemIds) + private + view + returns (uint256 validationCode) + { if (address(creatorFeeManager) != address(0)) { (bool status, bytes memory data) = address(creatorFeeManager).staticcall( abi.encodeCall(ICreatorFeeManager.viewCreatorFeeInfo, (collection, price, itemIds)) @@ -631,17 +622,14 @@ contract OrderValidatorV2A { * @param signer Signer address * @return validationCode Validation code */ - function _computeDigestAndVerify( - bytes32 computedHash, - bytes calldata makerSignature, - address signer - ) private view returns (uint256 validationCode) { - return - _validateSignature( - keccak256(abi.encodePacked("\x19\x01", domainSeparator, computedHash)), - makerSignature, - signer - ); + function _computeDigestAndVerify(bytes32 computedHash, bytes calldata makerSignature, address signer) + private + view + returns (uint256 validationCode) + { + return _validateSignature( + keccak256(abi.encodePacked("\x19\x01", domainSeparator, computedHash)), makerSignature, signer + ); } /** @@ -651,11 +639,11 @@ contract OrderValidatorV2A { * @param signer Signer address * @return validationCode Validation code */ - function _validateSignature( - bytes32 hash, - bytes calldata signature, - address signer - ) private view returns (uint256 validationCode) { + function _validateSignature(bytes32 hash, bytes calldata signature, address signer) + private + view + returns (uint256 validationCode) + { // Logic if EOA if (signer.code.length == 0) { bytes32 r; @@ -699,9 +687,8 @@ contract OrderValidatorV2A { } } else { // Logic if ERC1271 - (bool success, bytes memory data) = signer.staticcall( - abi.encodeCall(IERC1271.isValidSignature, (hash, signature)) - ); + (bool success, bytes memory data) = + signer.staticcall(abi.encodeCall(IERC1271.isValidSignature, (hash, signature))); if (!success) { return MISSING_IS_VALID_SIGNATURE_FUNCTION_EIP1271; @@ -728,64 +715,56 @@ contract OrderValidatorV2A { } } - function _checkValidityMakerAskItemIdsAndAmountsAndPrice( - OrderStructs.Maker memory makerAsk - ) private view returns (uint256 validationCode, uint256[] memory itemIds, uint256[] memory amounts, uint256 price) { + function _checkValidityMakerAskItemIdsAndAmountsAndPrice(OrderStructs.Maker memory makerAsk) + private + view + returns (uint256 validationCode, uint256[] memory itemIds, uint256[] memory amounts, uint256 price) + { if (makerAsk.strategyId == 0) { itemIds = makerAsk.itemIds; amounts = makerAsk.amounts; price = makerAsk.price; - validationCode = _getOrderValidationCodeForStandardStrategy( - makerAsk.collectionType, - itemIds.length, - amounts - ); + validationCode = + _getOrderValidationCodeForStandardStrategy(makerAsk.collectionType, itemIds.length, amounts); } else { itemIds = makerAsk.itemIds; amounts = makerAsk.amounts; // @dev It should ideally be adjusted by real price price = makerAsk.price; - (, , , , bytes4 strategySelector, , address strategyImplementation) = looksRareProtocol.strategyInfo( - makerAsk.strategyId - ); + (,,,, bytes4 strategySelector,, address strategyImplementation) = + looksRareProtocol.strategyInfo(makerAsk.strategyId); - (bool isValid, bytes4 errorSelector) = IStrategy(strategyImplementation).isMakerOrderValid( - makerAsk, - strategySelector - ); + (bool isValid, bytes4 errorSelector) = + IStrategy(strategyImplementation).isMakerOrderValid(makerAsk, strategySelector); validationCode = _getOrderValidationCodeForNonStandardStrategies(isValid, errorSelector); } } - function _checkValidityMakerBidItemIdsAndAmountsAndPrice( - OrderStructs.Maker memory makerBid - ) private view returns (uint256 validationCode, uint256[] memory itemIds, uint256[] memory amounts, uint256 price) { + function _checkValidityMakerBidItemIdsAndAmountsAndPrice(OrderStructs.Maker memory makerBid) + private + view + returns (uint256 validationCode, uint256[] memory itemIds, uint256[] memory amounts, uint256 price) + { if (makerBid.strategyId == 0) { itemIds = makerBid.itemIds; amounts = makerBid.amounts; price = makerBid.price; - validationCode = _getOrderValidationCodeForStandardStrategy( - makerBid.collectionType, - itemIds.length, - amounts - ); + validationCode = + _getOrderValidationCodeForStandardStrategy(makerBid.collectionType, itemIds.length, amounts); } else { // @dev It should ideally be adjusted by real price // amounts and itemIds are not used since most non-native maker bids won't target a single item price = makerBid.price; - (, , , , bytes4 strategySelector, , address strategyImplementation) = looksRareProtocol.strategyInfo( - makerBid.strategyId - ); + (,,,, bytes4 strategySelector,, address strategyImplementation) = + looksRareProtocol.strategyInfo(makerBid.strategyId); - (bool isValid, bytes4 errorSelector) = IStrategy(strategyImplementation).isMakerOrderValid( - makerBid, - strategySelector - ); + (bool isValid, bytes4 errorSelector) = + IStrategy(strategyImplementation).isMakerOrderValid(makerBid, strategySelector); validationCode = _getOrderValidationCodeForNonStandardStrategies(isValid, errorSelector); } @@ -804,8 +783,8 @@ contract OrderValidatorV2A { // Only check if length of array is greater than 1 if (length > 1) { - for (uint256 i = 0; i < length - 1; ) { - for (uint256 j = i + 1; j < length; ) { + for (uint256 i = 0; i < length - 1;) { + for (uint256 j = i + 1; j < length;) { if (itemIds[i] == itemIds[j]) { return SAME_ITEM_ID_IN_BUNDLE; } @@ -830,7 +809,7 @@ contract OrderValidatorV2A { if (expectedLength == 0 || (amounts.length != expectedLength)) { validationCode = MAKER_ORDER_INVALID_STANDARD_SALE; } else { - for (uint256 i; i < expectedLength; ) { + for (uint256 i; i < expectedLength;) { uint256 amount = amounts[i]; if (amount == 0) { @@ -848,10 +827,11 @@ contract OrderValidatorV2A { } } - function _getOrderValidationCodeForNonStandardStrategies( - bool isValid, - bytes4 errorSelector - ) private pure returns (uint256 validationCode) { + function _getOrderValidationCodeForNonStandardStrategies(bool isValid, bytes4 errorSelector) + private + pure + returns (uint256 validationCode) + { if (isValid) { validationCode = ORDER_EXPECTED_TO_BE_VALID; } else { diff --git a/contracts/src/marketplace/helpers/ProtocolHelpers.sol b/contracts/src/marketplace/helpers/ProtocolHelpers.sol index 01162985..99c37c0d 100644 --- a/contracts/src/marketplace/helpers/ProtocolHelpers.sol +++ b/contracts/src/marketplace/helpers/ProtocolHelpers.sol @@ -2,13 +2,13 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { SignatureCheckerCalldata } from "@looksrare/contracts-libs/contracts/SignatureCheckerCalldata.sol"; +import {SignatureCheckerCalldata} from "@looksrare/contracts-libs/contracts/SignatureCheckerCalldata.sol"; // Libraries -import { OrderStructs } from "../libraries/OrderStructs.sol"; +import {OrderStructs} from "../libraries/OrderStructs.sol"; // Other dependencies -import { LooksRareProtocol } from "../LooksRareProtocol.sol"; +import {LooksRareProtocol} from "../LooksRareProtocol.sol"; /** * @title ProtocolHelpers @@ -60,11 +60,11 @@ contract ProtocolHelpers { * @param signer Signer address * @dev It returns true only if the SignatureCheckerCalldata does not revert before. */ - function verifyMakerSignature( - OrderStructs.Maker memory maker, - bytes calldata makerSignature, - address signer - ) public view returns (bool) { + function verifyMakerSignature(OrderStructs.Maker memory maker, bytes calldata makerSignature, address signer) + public + view + returns (bool) + { bytes32 digest = computeMakerDigest(maker); SignatureCheckerCalldata.verify(digest, signer, makerSignature); return true; @@ -77,11 +77,11 @@ contract ProtocolHelpers { * @param signer Signer address * @dev It returns true only if the SignatureCheckerCalldata does not revert before. */ - function verifyMerkleTree( - OrderStructs.MerkleTree memory merkleTree, - bytes calldata makerSignature, - address signer - ) public view returns (bool) { + function verifyMerkleTree(OrderStructs.MerkleTree memory merkleTree, bytes calldata makerSignature, address signer) + public + view + returns (bool) + { bytes32 digest = computeDigestMerkleTree(merkleTree); SignatureCheckerCalldata.verify(digest, signer, makerSignature); return true; diff --git a/contracts/src/marketplace/interfaces/ICreatorFeeManager.sol b/contracts/src/marketplace/interfaces/ICreatorFeeManager.sol index d469ff27..6b6728e7 100644 --- a/contracts/src/marketplace/interfaces/ICreatorFeeManager.sol +++ b/contracts/src/marketplace/interfaces/ICreatorFeeManager.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.17; // Interfaces -import { IRoyaltyFeeRegistry } from "./IRoyaltyFeeRegistry.sol"; +import {IRoyaltyFeeRegistry} from "./IRoyaltyFeeRegistry.sol"; /** * @title ICreatorFeeManager @@ -28,9 +28,8 @@ interface ICreatorFeeManager { * @return creator Creator address * @return creatorFeeAmount Creator fee amount */ - function viewCreatorFeeInfo( - address collection, - uint256 price, - uint256[] memory itemIds - ) external view returns (address creator, uint256 creatorFeeAmount); + function viewCreatorFeeInfo(address collection, uint256 price, uint256[] memory itemIds) + external + view + returns (address creator, uint256 creatorFeeAmount); } diff --git a/contracts/src/marketplace/interfaces/IImmutableCreate2Factory.sol b/contracts/src/marketplace/interfaces/IImmutableCreate2Factory.sol index 9071ab43..efbecb66 100644 --- a/contracts/src/marketplace/interfaces/IImmutableCreate2Factory.sol +++ b/contracts/src/marketplace/interfaces/IImmutableCreate2Factory.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.17; interface IImmutableCreate2Factory { - function safeCreate2( - bytes32 salt, - bytes calldata initializationCode - ) external payable returns (address deploymentAddress); + function safeCreate2(bytes32 salt, bytes calldata initializationCode) + external + payable + returns (address deploymentAddress); } diff --git a/contracts/src/marketplace/interfaces/ILooksRareProtocol.sol b/contracts/src/marketplace/interfaces/ILooksRareProtocol.sol index 09722537..e2a52119 100644 --- a/contracts/src/marketplace/interfaces/ILooksRareProtocol.sol +++ b/contracts/src/marketplace/interfaces/ILooksRareProtocol.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "../libraries/OrderStructs.sol"; +import {OrderStructs} from "../libraries/OrderStructs.sol"; /** * @title ILooksRareProtocol @@ -22,14 +22,6 @@ interface ILooksRareProtocol { bool isNonceInvalidated; } - /** - * @notice It is emitted when there is an affiliate fee paid. - * @param affiliate Affiliate address - * @param currency Address of the currency - * @param affiliateFee Affiliate fee (in the currency) - */ - event AffiliatePayment(address affiliate, address currency, uint256 affiliateFee); - /** * @notice It is emitted if there is a change in the domain separator. */ @@ -60,8 +52,8 @@ interface ILooksRareProtocol { * feeAmounts[2] Protocol fee amount prior to adjustment for a potential affiliate payment */ // maker (receives the NFT) + // taker (initiates the transaction) event TakerAsk( - // taker (initiates the transaction) NonceInvalidationParameters nonceInvalidationParameters, address askUser, address bidUser, @@ -93,8 +85,8 @@ interface ILooksRareProtocol { * feeAmounts[2] Protocol fee amount prior to adjustment for a potential affiliate payment */ // taker (receives the NFT) + // taker (initiates the transaction) event TakerBid( - // taker (initiates the transaction) NonceInvalidationParameters nonceInvalidationParameters, address bidUser, address bidRecipient, @@ -133,14 +125,12 @@ interface ILooksRareProtocol { * @param makerBid Maker bid struct * @param makerSignature Maker signature * @param merkleTree Merkle tree struct (if the signature contains multiple maker orders) - * @param affiliate Affiliate address */ function executeTakerAsk( OrderStructs.Taker calldata takerAsk, OrderStructs.Maker calldata makerBid, bytes calldata makerSignature, - OrderStructs.MerkleTree calldata merkleTree, - address affiliate + OrderStructs.MerkleTree calldata merkleTree ) external; /** @@ -149,14 +139,12 @@ interface ILooksRareProtocol { * @param makerAsk Maker ask struct * @param makerSignature Maker signature * @param merkleTree Merkle tree struct (if the signature contains multiple maker orders) - * @param affiliate Affiliate address */ function executeTakerBid( OrderStructs.Taker calldata takerBid, OrderStructs.Maker calldata makerAsk, bytes calldata makerSignature, - OrderStructs.MerkleTree calldata merkleTree, - address affiliate + OrderStructs.MerkleTree calldata merkleTree ) external payable; /** @@ -165,7 +153,6 @@ interface ILooksRareProtocol { * @param makerAsks Array of maker ask structs * @param makerSignatures Array of maker signatures * @param merkleTrees Array of merkle tree structs if the signature contains multiple maker orders - * @param affiliate Affiliate address * @param isAtomic Whether the execution should be atomic * i.e. whether it should revert if 1 or more transactions fail */ @@ -174,7 +161,6 @@ interface ILooksRareProtocol { OrderStructs.Maker[] calldata makerAsks, bytes[] calldata makerSignatures, OrderStructs.MerkleTree[] calldata merkleTrees, - address affiliate, bool isAtomic ) external payable; } diff --git a/contracts/src/marketplace/interfaces/IRoyaltyFeeRegistry.sol b/contracts/src/marketplace/interfaces/IRoyaltyFeeRegistry.sol index a76c84cb..766d4603 100644 --- a/contracts/src/marketplace/interfaces/IRoyaltyFeeRegistry.sol +++ b/contracts/src/marketplace/interfaces/IRoyaltyFeeRegistry.sol @@ -13,8 +13,8 @@ interface IRoyaltyFeeRegistry { * @return receiver Receiver address * @return royaltyFee Royalty fee amount */ - function royaltyInfo( - address collection, - uint256 price - ) external view returns (address receiver, uint256 royaltyFee); + function royaltyInfo(address collection, uint256 price) + external + view + returns (address receiver, uint256 royaltyFee); } diff --git a/contracts/src/marketplace/interfaces/IStrategy.sol b/contracts/src/marketplace/interfaces/IStrategy.sol index 39585c5f..a9b7e450 100644 --- a/contracts/src/marketplace/interfaces/IStrategy.sol +++ b/contracts/src/marketplace/interfaces/IStrategy.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "../libraries/OrderStructs.sol"; +import {OrderStructs} from "../libraries/OrderStructs.sol"; /** * @title IStrategy @@ -17,10 +17,10 @@ interface IStrategy { * @return isValid Whether the maker struct is valid * @return errorSelector If isValid is false, it returns the error's 4 bytes selector */ - function isMakerOrderValid( - OrderStructs.Maker calldata makerOrder, - bytes4 functionSelector - ) external view returns (bool isValid, bytes4 errorSelector); + function isMakerOrderValid(OrderStructs.Maker calldata makerOrder, bytes4 functionSelector) + external + view + returns (bool isValid, bytes4 errorSelector); /** * @notice This function acts as a safety check for the protocol's owner when adding new execution strategies. diff --git a/contracts/src/marketplace/interfaces/ITransferManager.sol b/contracts/src/marketplace/interfaces/ITransferManager.sol index 56f70e19..8f19f9a4 100644 --- a/contracts/src/marketplace/interfaces/ITransferManager.sol +++ b/contracts/src/marketplace/interfaces/ITransferManager.sol @@ -2,10 +2,10 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "../libraries/OrderStructs.sol"; +import {OrderStructs} from "../libraries/OrderStructs.sol"; // Enums -import { CollectionType } from "../enums/CollectionType.sol"; +import {CollectionType} from "../enums/CollectionType.sol"; /** * @title ITransferManager diff --git a/contracts/src/marketplace/libraries/CurrencyValidator.sol b/contracts/src/marketplace/libraries/CurrencyValidator.sol index d7523744..61208646 100644 --- a/contracts/src/marketplace/libraries/CurrencyValidator.sol +++ b/contracts/src/marketplace/libraries/CurrencyValidator.sol @@ -2,7 +2,11 @@ pragma solidity 0.8.17; // Assembly -import { CurrencyInvalid_error_selector, CurrencyInvalid_error_length, Error_selector_offset } from "../constants/AssemblyConstants.sol"; +import { + CurrencyInvalid_error_selector, + CurrencyInvalid_error_length, + Error_selector_offset +} from "../constants/AssemblyConstants.sol"; /** * @title CurrencyValidator diff --git a/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol b/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol index d3d04cfe..f3af4e8b 100644 --- a/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol +++ b/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "../../libraries/OrderStructs.sol"; +import {OrderStructs} from "../../libraries/OrderStructs.sol"; /** * @title MerkleProofCalldataWithNodes @@ -16,11 +16,11 @@ library MerkleProofCalldataWithNodes { * For this, a `proof` must be provided, containing sibling hashes on the branch from the leaf to the * root of the tree. Each pair of leaves and each pair of pre-images are assumed to be sorted. */ - function verifyCalldata( - OrderStructs.MerkleTreeNode[] calldata proof, - bytes32 root, - bytes32 leaf - ) internal pure returns (bool) { + function verifyCalldata(OrderStructs.MerkleTreeNode[] calldata proof, bytes32 root, bytes32 leaf) + internal + pure + returns (bool) + { return processProofCalldata(proof, leaf) == root; } @@ -29,14 +29,15 @@ library MerkleProofCalldataWithNodes { * A `proof` is valid if and only if the rebuilt hash matches the root of the tree. * When processing the proof, the pairs of leafs & pre-images are assumed to be sorted. */ - function processProofCalldata( - OrderStructs.MerkleTreeNode[] calldata proof, - bytes32 leaf - ) internal pure returns (bytes32) { + function processProofCalldata(OrderStructs.MerkleTreeNode[] calldata proof, bytes32 leaf) + internal + pure + returns (bytes32) + { bytes32 computedHash = leaf; uint256 length = proof.length; - for (uint256 i = 0; i < length; ) { + for (uint256 i = 0; i < length;) { if (proof[i].position == OrderStructs.MerkleTreeNodePosition.Left) { computedHash = _efficientHash(proof[i].value, computedHash); } else { diff --git a/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofMemory.sol b/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofMemory.sol index 1e00db5a..02ab8737 100644 --- a/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofMemory.sol +++ b/contracts/src/marketplace/libraries/OpenZeppelin/MerkleProofMemory.sol @@ -27,7 +27,7 @@ library MerkleProofMemory { bytes32 computedHash = leaf; uint256 length = proof.length; - for (uint256 i = 0; i < length; ) { + for (uint256 i = 0; i < length;) { computedHash = _hashPair(computedHash, proof[i]); unchecked { ++i; diff --git a/contracts/src/marketplace/libraries/OrderStructs.sol b/contracts/src/marketplace/libraries/OrderStructs.sol index e7600695..19b3a88d 100644 --- a/contracts/src/marketplace/libraries/OrderStructs.sol +++ b/contracts/src/marketplace/libraries/OrderStructs.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.17; // Enums -import { CollectionType } from "../enums/CollectionType.sol"; -import { QuoteType } from "../enums/QuoteType.sol"; +import {CollectionType} from "../enums/CollectionType.sol"; +import {QuoteType} from "../enums/QuoteType.sol"; /** * @title OrderStructs @@ -106,26 +106,12 @@ library OrderStructs { /** * @notice This is the type hash constant used to compute the maker order hash. */ - bytes32 internal constant _MAKER_TYPEHASH = - keccak256( - "Maker(" - "uint8 quoteType," - "uint256 globalNonce," - "uint256 subsetNonce," - "uint256 orderNonce," - "uint256 strategyId," - "uint8 collectionType," - "address collection," - "address currency," - "address signer," - "uint256 startTime," - "uint256 endTime," - "uint256 price," - "uint256[] itemIds," - "uint256[] amounts," - "bytes additionalParameters" - ")" - ); + bytes32 internal constant _MAKER_TYPEHASH = keccak256( + "Maker(" "uint8 quoteType," "uint256 globalNonce," "uint256 subsetNonce," "uint256 orderNonce," + "uint256 strategyId," "uint8 collectionType," "address collection," "address currency," "address signer," + "uint256 startTime," "uint256 endTime," "uint256 price," "uint256[] itemIds," "uint256[] amounts," + "bytes additionalParameters" ")" + ); /** * 5. Hash functions @@ -138,30 +124,29 @@ library OrderStructs { */ function hash(Maker memory maker) internal pure returns (bytes32) { // Encoding is done into two parts to avoid stack too deep issues - return - keccak256( - bytes.concat( - abi.encode( - _MAKER_TYPEHASH, - maker.quoteType, - maker.globalNonce, - maker.subsetNonce, - maker.orderNonce, - maker.strategyId, - maker.collectionType, - maker.collection, - maker.currency - ), - abi.encode( - maker.signer, - maker.startTime, - maker.endTime, - maker.price, - keccak256(abi.encodePacked(maker.itemIds)), - keccak256(abi.encodePacked(maker.amounts)), - keccak256(maker.additionalParameters) - ) + return keccak256( + bytes.concat( + abi.encode( + _MAKER_TYPEHASH, + maker.quoteType, + maker.globalNonce, + maker.subsetNonce, + maker.orderNonce, + maker.strategyId, + maker.collectionType, + maker.collection, + maker.currency + ), + abi.encode( + maker.signer, + maker.startTime, + maker.endTime, + maker.price, + keccak256(abi.encodePacked(maker.itemIds)), + keccak256(abi.encodePacked(maker.amounts)), + keccak256(maker.additionalParameters) ) - ); + ) + ); } } diff --git a/contracts/src/protocol/AllowlistMinter.sol b/contracts/src/protocol/AllowlistMinter.sol index 576b45ee..599831cb 100644 --- a/contracts/src/protocol/AllowlistMinter.sol +++ b/contracts/src/protocol/AllowlistMinter.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.16; -import { MerkleProofUpgradeable } from "oz-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol"; -import { IAllowlist } from "./interfaces/IAllowlist.sol"; +import {MerkleProofUpgradeable} from "oz-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol"; +import {IAllowlist} from "./interfaces/IAllowlist.sol"; -import { Errors } from "./libs/Errors.sol"; +import {Errors} from "./libs/Errors.sol"; /// @title Interface for hypercert token interactions /// @author bitbeckers @@ -19,11 +19,11 @@ contract AllowlistMinter is IAllowlist { mapping(uint256 => uint256) internal maxUnits; mapping(uint256 => uint256) internal minted; - function isAllowedToClaim( - bytes32[] calldata proof, - uint256 claimID, - bytes32 leaf - ) external view returns (bool isAllowed) { + function isAllowedToClaim(bytes32[] calldata proof, uint256 claimID, bytes32 leaf) + external + view + returns (bool isAllowed) + { if (merkleRoots[claimID].length == 0) revert Errors.DoesNotExist(); isAllowed = MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf); } @@ -44,8 +44,8 @@ contract AllowlistMinter is IAllowlist { if (hasBeenClaimed[claimID][leaf]) revert Errors.AlreadyClaimed(); if ( - !MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf) || - (minted[claimID] + amount) > maxUnits[claimID] + !MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf) + || (minted[claimID] + amount) > maxUnits[claimID] ) revert Errors.Invalid(); hasBeenClaimed[claimID][leaf] = true; diff --git a/contracts/src/protocol/HypercertMinter.sol b/contracts/src/protocol/HypercertMinter.sol index 4a2e274d..cf387a86 100644 --- a/contracts/src/protocol/HypercertMinter.sol +++ b/contracts/src/protocol/HypercertMinter.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.16; -import { IHypercertToken } from "./interfaces/IHypercertToken.sol"; -import { SemiFungible1155 } from "./SemiFungible1155.sol"; -import { AllowlistMinter } from "./AllowlistMinter.sol"; -import { PausableUpgradeable } from "oz-upgradeable/security/PausableUpgradeable.sol"; +import {IHypercertToken} from "./interfaces/IHypercertToken.sol"; +import {SemiFungible1155} from "./SemiFungible1155.sol"; +import {AllowlistMinter} from "./AllowlistMinter.sol"; +import {PausableUpgradeable} from "oz-upgradeable/security/PausableUpgradeable.sol"; -import { Errors } from "./libs/Errors.sol"; +import {Errors} from "./libs/Errors.sol"; /// @title Contract for managing hypercert claims and whitelists /// @author bitbeckers @@ -37,12 +37,11 @@ contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, /// @notice Mint a semi-fungible token for the impact claim referenced via `uri` /// @dev see {IHypercertToken} - function mintClaim( - address account, - uint256 units, - string memory _uri, - TransferRestrictions restrictions - ) external override whenNotPaused { + function mintClaim(address account, uint256 units, string memory _uri, TransferRestrictions restrictions) + external + override + whenNotPaused + { // This enables us to release this restriction in the future if (msg.sender != account) revert Errors.NotAllowed(); uint256 claimID = _mintNewTypeWithToken(account, units, _uri); @@ -72,12 +71,10 @@ contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, /// @notice Mint a semi-fungible token representing a fraction of the claim /// @dev Calls AllowlistMinter to verify `proof`. /// @dev Mints the `amount` of units for the hypercert stored under `claimID` - function mintClaimFromAllowlist( - address account, - bytes32[] calldata proof, - uint256 claimID, - uint256 units - ) external whenNotPaused { + function mintClaimFromAllowlist(address account, bytes32[] calldata proof, uint256 claimID, uint256 units) + external + whenNotPaused + { _processClaim(proof, claimID, units); _mintToken(account, claimID, units); } @@ -92,7 +89,7 @@ contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, uint256[] calldata units ) external whenNotPaused { uint256 len = claimIDs.length; - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { _processClaim(proofs[i], claimIDs[i], units[i]); unchecked { ++i; @@ -119,11 +116,10 @@ contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, /// @notice Split a claimtokens value into parts with summed value equal to the original /// @dev see {IHypercertToken} - function splitFraction( - address _account, - uint256 _tokenID, - uint256[] calldata _newFractions - ) external whenNotPaused { + function splitFraction(address _account, uint256 _tokenID, uint256[] calldata _newFractions) + external + whenNotPaused + { _splitTokenUnits(_account, _tokenID, _newFractions); } @@ -147,13 +143,17 @@ contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, /// @notice Burn a claimtoken; override is needed to update units/values /// @dev see {ERC1155Burnable} - function burn(address account, uint256 id, uint256 value) public override whenNotPaused { + function burn(address account, uint256 id, uint256 /*value*/ ) public override whenNotPaused { _burnToken(account, id); } /// @notice Batch burn claimtokens; override is needed to update units/values /// @dev see {ERC1155Burnable} - function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public override whenNotPaused { + function burnBatch(address account, uint256[] memory ids, uint256[] memory /*values*/ ) + public + override + whenNotPaused + { _batchBurnToken(account, ids); } @@ -180,7 +180,12 @@ contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, /// METADATA /// @dev see { IHypercertMetadata} - function uri(uint256 tokenID) public view override(IHypercertToken, SemiFungible1155) returns (string memory _uri) { + function uri(uint256 tokenID) + public + view + override(IHypercertToken, SemiFungible1155) + returns (string memory _uri) + { _uri = SemiFungible1155.uri(tokenID); } @@ -222,7 +227,7 @@ contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, // Transfer case, where to and from are non-zero uint256 len = ids.length; - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { uint256 typeID = getBaseType(ids[i]); TransferRestrictions policy = typeRestrictions[typeID]; if (policy == TransferRestrictions.DisallowAll) { diff --git a/contracts/src/protocol/SemiFungible1155.sol b/contracts/src/protocol/SemiFungible1155.sol index fba07983..fb409bbe 100644 --- a/contracts/src/protocol/SemiFungible1155.sol +++ b/contracts/src/protocol/SemiFungible1155.sol @@ -3,13 +3,13 @@ // /~https://github.com/enjin/erc-1155/blob/master/contracts/ERC1155MixedFungibleMintable.sol pragma solidity 0.8.16; -import { ERC1155Upgradeable } from "oz-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; -import { ERC1155BurnableUpgradeable } from "oz-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol"; -import { ERC1155URIStorageUpgradeable } from "oz-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol"; -import { OwnableUpgradeable } from "oz-upgradeable/access/OwnableUpgradeable.sol"; -import { Initializable } from "oz-upgradeable/proxy/utils/Initializable.sol"; -import { UUPSUpgradeable } from "oz-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { Errors } from "./libs/Errors.sol"; +import {ERC1155Upgradeable} from "oz-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; +import {ERC1155BurnableUpgradeable} from "oz-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol"; +import {ERC1155URIStorageUpgradeable} from "oz-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol"; +import {OwnableUpgradeable} from "oz-upgradeable/access/OwnableUpgradeable.sol"; +import {Initializable} from "oz-upgradeable/proxy/utils/Initializable.sol"; +import {UUPSUpgradeable} from "oz-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {Errors} from "./libs/Errors.sol"; /// @title Contract for minting semi-fungible EIP1155 tokens /// @author bitbeckers @@ -163,17 +163,18 @@ contract SemiFungible1155 is * @param _units The number of units associated with the new token. * @param _uri The URI for the metadata associated with the new token. * @return typeID The new token type ID. - * @dev This function creates a new token type ID by calling the `_createTokenType` function and then mints a new token with the new type ID. + * @dev This function creates a new token type ID by calling the `_createTokenType` function and then mints a new + * token with the new type ID. * @dev The `tokenID` is calculated by adding the `typeID` to the current maximum index for the `typeID`. * @dev The `tokenValues` mapping is updated with the number of units associated with the new token. - * @dev A `ValueTransfer` event is emitted to indicate that a new token has been minted and assigned to the specified account. + * @dev A `ValueTransfer` event is emitted to indicate that a new token has been minted and assigned to the + * specified account. * @dev If `_units` is zero, the function will revert with an error. */ - function _mintNewTypeWithToken( - address _account, - uint256 _units, - string memory _uri - ) internal returns (uint256 typeID) { + function _mintNewTypeWithToken(address _account, uint256 _units, string memory _uri) + internal + returns (uint256 typeID) + { if (_units == 0) { revert Errors.NotAllowed(); } @@ -193,18 +194,20 @@ contract SemiFungible1155 is * @param _fractions An array of values associated with the new token. * @param _uri The URI for the metadata associated with the new token. * @return typeID The new token type ID. - * @dev This function creates a new token type ID by calling the `_createTokenType` function and then mints a new token with the new type ID. + * @dev This function creates a new token type ID by calling the `_createTokenType` function and then mints a new + * token with the new type ID. * @dev The `tokenID` is calculated by adding the `typeID` to the current maximum index for the `typeID`. * @dev The `tokenValues` mapping is updated with the number of units associated with the new token. - * @dev A `ValueTransfer` event is emitted to indicate that a new token has been minted and assigned to the specified account. + * @dev A `ValueTransfer` event is emitted to indicate that a new token has been minted and assigned to the + * specified account. * @dev If any of the fractional values in `_fractions` are zero, the function will revert with an error. - * @dev This function also calls the `_splitTokenUnits` function to split the new token into multiple sub-tokens with the specified fractional values. + * @dev This function also calls the `_splitTokenUnits` function to split the new token into multiple sub-tokens + * with the specified fractional values. */ - function _mintNewTypeWithTokens( - address _account, - uint256[] calldata _fractions, - string memory _uri - ) internal returns (uint256 typeID) { + function _mintNewTypeWithTokens(address _account, uint256[] calldata _fractions, string memory _uri) + internal + returns (uint256 typeID) + { typeID = _mintNewTypeWithToken(_account, _getSum(_fractions), _uri); _splitTokenUnits(_account, typeID + maxIndex[typeID], _fractions); } @@ -215,10 +218,13 @@ contract SemiFungible1155 is * @param _typeID The ID of the token type to mint. * @param _units The number of units associated with the new token. * @return tokenID The ID of the newly minted token. - * @dev This function checks that the specified token type ID is a base type and that the maximum number of tokens for the token type has not been reached. - * @dev The function then calculates the new token ID by adding the specified token type ID to the current maximum index for the token type. + * @dev This function checks that the specified token type ID is a base type and that the maximum number of tokens + * for the token type has not been reached. + * @dev The function then calculates the new token ID by adding the specified token type ID to the current maximum + * index for the token type. * @dev The `tokenValues` mapping is updated with the number of units associated with the new token. - * @dev A `ValueTransfer` event is emitted to indicate that a new token has been minted and assigned to the specified account. + * @dev A `ValueTransfer` event is emitted to indicate that a new token has been minted and assigned to the + * specified account. */ function _mintToken(address _account, uint256 _typeID, uint256 _units) internal returns (uint256 tokenID) { if (!isBaseType(_typeID)) revert Errors.NotAllowed(); @@ -241,23 +247,25 @@ contract SemiFungible1155 is * @param _typeIDs An array of token type IDs to mint. * @param _units An array of numbers of units associated with the new tokens. * @return tokenIDs An array of the IDs of the newly minted tokens. - * @dev This function checks that each specified token type ID is a base type and that the maximum number of tokens for each token type has not been reached. - * @dev The function then calculates the new token IDs by adding the specified token type IDs to the current maximum index for each token type. + * @dev This function checks that each specified token type ID is a base type and that the maximum number of tokens + * for each token type has not been reached. + * @dev The function then calculates the new token IDs by adding the specified token type IDs to the current maximum + * index for each token type. * @dev The `tokenValues` mapping is updated with the number of units associated with each new token. - * @dev A `BatchValueTransfer` event is emitted to indicate that new tokens have been minted and assigned to the specified account. + * @dev A `BatchValueTransfer` event is emitted to indicate that new tokens have been minted and assigned to the + * specified account. */ - function _batchMintTokens( - address _account, - uint256[] calldata _typeIDs, - uint256[] calldata _units - ) internal returns (uint256[] memory tokenIDs) { + function _batchMintTokens(address _account, uint256[] calldata _typeIDs, uint256[] calldata _units) + internal + returns (uint256[] memory tokenIDs) + { uint256 len = _typeIDs.length; tokenIDs = new uint256[](len); uint256[] memory amounts = new uint256[](len); uint256[] memory zeroes = new uint256[](len); - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { uint256 _typeID = _typeIDs[i]; if (!isBaseType(_typeID)) revert Errors.NotAllowed(); _notMaxItem(maxIndex[_typeID]); @@ -282,9 +290,12 @@ contract SemiFungible1155 is * @param _values An array of numbers of units associated with the new tokens. * @dev This function splits a token into multiple tokens with different unit values. * @dev The `_values` array specifies the number of units associated with each new token. - * @dev The function checks that the length of the `_values` array is between 2 and `FRACTION_LIMIT`, and that the sum of the values in the `_values` array is equal to the number of units associated with the original token. - * @dev The function then creates new tokens with the specified unit values and assigns them to the specified account. - * @dev A `BatchValueTransfer` event is emitted to indicate that the original token has been split into multiple tokens. + * @dev The function checks that the length of the `_values` array is between 2 and `FRACTION_LIMIT`, and that the + * sum of the values in the `_values` array is equal to the number of units associated with the original token. + * @dev The function then creates new tokens with the specified unit values and assigns them to the specified + * account. + * @dev A `BatchValueTransfer` event is emitted to indicate that the original token has been split into multiple + * tokens. */ function _splitTokenUnits(address _account, uint256 _tokenID, uint256[] calldata _values) internal { if (_values.length > FRACTION_LIMIT || _values.length < 2) revert Errors.ArraySize(); @@ -309,7 +320,7 @@ contract SemiFungible1155 is _valuesCache[len] = _valuesCache[0]; _valuesCache[0] = swapValue; - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { _notMaxItem(maxIndex[_typeID]); typeIDs[i] = _typeID; @@ -326,7 +337,7 @@ contract SemiFungible1155 is _beforeUnitTransfer(_msgSender(), owners[_tokenID], fromIDs, toIDs, values, ""); - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { valueLeft -= values[i]; tokenValues[toIDs[i]] = values[i]; @@ -350,7 +361,8 @@ contract SemiFungible1155 is * @dev This function merges the units of multiple tokens into a single token. * @dev The `_fractionIDs` array specifies the IDs of the tokens to merge. * @dev The function checks that the length of the `_fractionIDs` array is between 2 and `FRACTION_LIMIT`. - * @dev The function then calculates the total value of the merged token by summing the values of the tokens to be merged. + * @dev The function then calculates the total value of the merged token by summing the values of the tokens to be + * merged. * @dev The `tokenValues` mapping is updated with the total value of the merged token. * @dev The tokens to be merged are burned except the last one that receives all the units. * @dev A `BatchValueTransfer` event is emitted to indicate that the tokens have been merged into a single token. @@ -370,7 +382,7 @@ contract SemiFungible1155 is uint256[] memory amounts = new uint256[](len); { - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { uint256 _fractionID = _fractionIDs[i]; fromIDs[i] = _fractionID; toIDs[i] = target; @@ -385,7 +397,7 @@ contract SemiFungible1155 is _beforeUnitTransfer(_msgSender(), _account, fromIDs, toIDs, values, ""); - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { _totalValue += values[i]; delete tokenValues[fromIDs[i]]; @@ -404,8 +416,10 @@ contract SemiFungible1155 is * @param _account The address of the account that owns the token to burn. * @param _tokenID The ID of the token to burn. * @dev This function burns a single token with the specified ID and emits a `ValueTransfer` event `toTokenID` 0. - * @dev The function checks that the caller is the owner of the token or is approved to burn the token on behalf of the owner. - * @dev The function then deletes the token from the `tokenValues` mapping and calls the `_burn` function to burn the token. + * @dev The function checks that the caller is the owner of the token or is approved to burn the token on behalf of + * the owner. + * @dev The function then deletes the token from the `tokenValues` mapping and calls the `_burn` function to burn + * the token. */ function _burnToken(address _account, uint256 _tokenID) internal { if (_account != _msgSender() && !isApprovedForAll(_account, _msgSender())) revert Errors.NotApprovedOrOwner(); @@ -423,9 +437,12 @@ contract SemiFungible1155 is * @param _account The address of the account that owns the tokens to burn. * @param _tokenIDs An array of token IDs to burn. * @dev This function burns multiple tokens with the specified IDs and emits a `BatchValueTransfer` event. - * @dev The function checks that the caller is the owner of the tokens or is approved to burn the tokens on behalf of the owner. - * @dev The function then deletes the tokens from the `tokenValues` mapping and calls the `_burnBatch` function to burn the tokens. - * @dev Finally, the function emits a `BatchValueTransfer` event with a value of 1 and `toTokenIDs` as 0 for each token burned to indicate that the tokens have been burned. + * @dev The function checks that the caller is the owner of the tokens or is approved to burn the tokens on behalf + * of the owner. + * @dev The function then deletes the tokens from the `tokenValues` mapping and calls the `_burnBatch` function to + * burn the tokens. + * @dev Finally, the function emits a `BatchValueTransfer` event with a value of 1 and `toTokenIDs` as 0 for each + * token burned to indicate that the tokens have been burned. */ function _batchBurnToken(address _account, uint256[] memory _tokenIDs) internal { if (_account != _msgSender() && !isApprovedForAll(_account, _msgSender())) revert Errors.NotApprovedOrOwner(); @@ -478,7 +495,7 @@ contract SemiFungible1155 is uint256 len = ids.length; - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { owners[ids[i]] = to; unchecked { ++i; @@ -488,25 +505,26 @@ contract SemiFungible1155 is /** * @dev Called before a batch of tokens is transferred. - * @param operator The address of the operator performing the transfer. + * @param {operator} The address of the operator performing the transfer. * @param from The address of the sender of the tokens. * @param fromIDs An array of token IDs that are being transferred. * @param toIDs An array of token IDs that the tokens are being transferred to. - * @param values An array of token amounts that are being transferred. - * @param data Additional data that was passed along with the transfer. - * @dev This function checks that the transfer is allowed by verifying that the sender is approved to transfer the tokens and that the tokens being transferred are of the same base type. + * @param {values} An array of token amounts that are being transferred. + * @param {data} Additional data that was passed along with the transfer. + * @dev This function checks that the transfer is allowed by verifying that the sender is approved to transfer the + * tokens and that the tokens being transferred are of the same base type. */ function _beforeUnitTransfer( - address operator, + address, /*operator*/ address from, uint256[] memory fromIDs, uint256[] memory toIDs, - uint256[] memory values, - bytes memory data + uint256[] memory, /*values*/ + bytes memory /*data*/ ) internal virtual { uint256 len = fromIDs.length; - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { uint256 _from = fromIDs[i]; uint256 _to = toIDs[i]; @@ -525,13 +543,19 @@ contract SemiFungible1155 is * @dev Returns the metadata URI for a given token ID. * @param tokenID The ID of the token to retrieve the metadata URI for. * @return _uri The metadata URI for the specified token ID. - * @dev This function retrieves the metadata URI for the specified token ID by calling the `uri` function of the `ERC1155URIStorageUpgradeable` contract. - * @dev The metadata URI is a string that points to a JSON file containing information about the token, such as its name, symbol, and image. + * @dev This function retrieves the metadata URI for the specified token ID by calling the `uri` function of the + * `ERC1155URIStorageUpgradeable` contract. + * @dev The metadata URI is a string that points to a JSON file containing information about the token, such as its + * name, symbol, and image. * @dev This function always returns the URI for the basetype so that it's managed in one place. */ - function uri( - uint256 tokenID - ) public view virtual override(ERC1155Upgradeable, ERC1155URIStorageUpgradeable) returns (string memory _uri) { + function uri(uint256 tokenID) + public + view + virtual + override(ERC1155Upgradeable, ERC1155URIStorageUpgradeable) + returns (string memory _uri) + { // All tokens share the same metadata at the moment _uri = ERC1155URIStorageUpgradeable.uri(getBaseType(tokenID)); } @@ -541,7 +565,8 @@ contract SemiFungible1155 is /** * @dev Checks if the specified token ID is below the maximum item index. * @param tokenID The ID of the token to check. - * @dev This function checks if the specified token ID is below the maximum item index by converting the token ID to a `uint128` value and incrementing it. + * @dev This function checks if the specified token ID is below the maximum item index by converting the token ID to + * a `uint128` value and incrementing it. * @dev If the token ID is greater than or equal to the maximum item index, the function will revert with an error. */ function _notMaxItem(uint256 tokenID) private pure { @@ -552,7 +577,8 @@ contract SemiFungible1155 is /** * @dev Checks if the specified token ID is below the maximum type index. * @param tokenID The ID of the token to check. - * @dev This function checks if the specified token ID is below the maximum type index by shifting the token ID right by 128 bits to get the type ID and converting it to a `uint128` value. + * @dev This function checks if the specified token ID is below the maximum type index by shifting the token ID + * right by 128 bits to get the type ID and converting it to a `uint128` value. * @dev If the type ID is greater than or equal to the maximum type index, the function will revert with an error. */ function _notMaxType(uint256 tokenID) private pure { @@ -564,12 +590,13 @@ contract SemiFungible1155 is * @dev Calculates the sum of the elements of an array. * @param array The array of uint256 values to sum. * @return sum The sum of the elements of the array. - * @dev This function calculates the sum of the elements of the specified array by iterating over the array and adding each element to a running total. + * @dev This function calculates the sum of the elements of the specified array by iterating over the array and + * adding each element to a running total. * @dev If an element in the array is 0, the function will revert with an error. */ function _getSum(uint256[] memory array) internal pure returns (uint256 sum) { uint256 len = array.length; - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { if (array[i] == 0) revert Errors.NotAllowed(); sum += array[i]; unchecked { @@ -582,7 +609,8 @@ contract SemiFungible1155 is * @dev Returns an array containing a single element. * @param element The element to include in the array. * @return An array containing a single element. - * @dev This function returns an array containing a single element by creating a new array with a length of 1 and setting the first element to the specified value. + * @dev This function returns an array containing a single element by creating a new array with a length of 1 and + * setting the first element to the specified value. */ function _getSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); diff --git a/contracts/src/protocol/interfaces/IAllowlist.sol b/contracts/src/protocol/interfaces/IAllowlist.sol index fe4a9ec4..2ce9a044 100644 --- a/contracts/src/protocol/interfaces/IAllowlist.sol +++ b/contracts/src/protocol/interfaces/IAllowlist.sol @@ -6,9 +6,8 @@ pragma solidity 0.8.16; /// @notice This interface declares the required functionality for a hypercert token /// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) interface IAllowlist { - function isAllowedToClaim( - bytes32[] calldata proof, - uint256 tokenID, - bytes32 leaf - ) external view returns (bool isAllowed); + function isAllowedToClaim(bytes32[] calldata proof, uint256 tokenID, bytes32 leaf) + external + view + returns (bool isAllowed); } diff --git a/contracts/test/foundry/marketplace/BatchMakerCollectionOrders.t.sol b/contracts/test/foundry/marketplace/BatchMakerCollectionOrders.t.sol index 9222bd04..8810028b 100644 --- a/contracts/test/foundry/marketplace/BatchMakerCollectionOrders.t.sol +++ b/contracts/test/foundry/marketplace/BatchMakerCollectionOrders.t.sol @@ -2,23 +2,23 @@ pragma solidity 0.8.17; // Strategies -import { StrategyCollectionOffer } from "@hypercerts/marketplace/executionStrategies/StrategyCollectionOffer.sol"; +import {StrategyCollectionOffer} from "@hypercerts/marketplace/executionStrategies/StrategyCollectionOffer.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Helpers -import { EIP712MerkleTree } from "./utils/EIP712MerkleTree.sol"; +import {EIP712MerkleTree} from "./utils/EIP712MerkleTree.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract BatchMakerCollectionOrdersTest is ProtocolBase { StrategyCollectionOffer private strategy; @@ -50,7 +50,7 @@ contract BatchMakerCollectionOrdersTest is ProtocolBase { OrderStructs.Maker[] memory makerBids = _createBatchMakerBids(numberOrders); - (bytes memory signature, ) = eip712MerkleTree.sign(makerUserPK, makerBids, 0); + (bytes memory signature,) = eip712MerkleTree.sign(makerUserPK, makerBids, 0); for (uint256 i; i < numberOrders; i++) { // To prove that we only need 1 signature for multiple collection offers, @@ -66,7 +66,7 @@ contract BatchMakerCollectionOrdersTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerOrder, makerBidToExecute, signature, merkleTree, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerOrder, makerBidToExecute, signature, merkleTree); // Maker user has received the asset assertEq(mockERC721.ownerOf(i), makerUser); @@ -80,15 +80,12 @@ contract BatchMakerCollectionOrdersTest is ProtocolBase { uint256 totalValue = price * numberOrders; assertEq( - weth.balanceOf(makerUser), - _initialWETHBalanceUser - totalValue, - "Maker bid user should pay the whole price" + weth.balanceOf(makerUser), _initialWETHBalanceUser - totalValue, "Maker bid user should pay the whole price" ); assertEq( weth.balanceOf(takerUser), - _initialWETHBalanceUser + - (totalValue * _sellerProceedBpWithStandardProtocolFeeBp) / - ONE_HUNDRED_PERCENT_IN_BP, + _initialWETHBalanceUser + + (totalValue * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP, "Taker ask user should receive 99.5% of the whole price (0.5% protocol)" ); } diff --git a/contracts/test/foundry/marketplace/BatchMakerOrders.t.sol b/contracts/test/foundry/marketplace/BatchMakerOrders.t.sol index fabceaae..35bb3570 100644 --- a/contracts/test/foundry/marketplace/BatchMakerOrders.t.sol +++ b/contracts/test/foundry/marketplace/BatchMakerOrders.t.sol @@ -2,25 +2,31 @@ pragma solidity 0.8.17; // Murky (third-party) library is used to compute Merkle trees in Solidity -import { Merkle } from "murky/Merkle.sol"; +import {Merkle} from "murky/Merkle.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Errors and constants -import { MerkleProofTooLarge, MerkleProofInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; -import { MERKLE_PROOF_PROOF_TOO_LARGE, ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; -import { ONE_HUNDRED_PERCENT_IN_BP, MAX_CALLDATA_PROOF_LENGTH } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {MerkleProofTooLarge, MerkleProofInvalid} from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { + MERKLE_PROOF_PROOF_TOO_LARGE, + ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE +} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import { + ONE_HUNDRED_PERCENT_IN_BP, + MAX_CALLDATA_PROOF_LENGTH +} from "@hypercerts/marketplace/constants/NumericConstants.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Helpers -import { EIP712MerkleTree } from "./utils/EIP712MerkleTree.sol"; +import {EIP712MerkleTree} from "./utils/EIP712MerkleTree.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract BatchMakerOrdersTest is ProtocolBase { uint256 private constant price = 1.2222 ether; // Fixed price of sale @@ -39,11 +45,8 @@ contract BatchMakerOrdersTest is ProtocolBase { OrderStructs.Maker[] memory makerAsks = _createBatchMakerAsks(numberOrders); - (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( - makerUserPK, - makerAsks, - orderIndex - ); + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = + eip712MerkleTree.sign(makerUserPK, makerAsks, orderIndex); OrderStructs.Maker memory makerAskToExecute = makerAsks[orderIndex]; @@ -52,13 +55,7 @@ contract BatchMakerOrdersTest is ProtocolBase { // Execute taker bid transaction vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - _genericTakerOrder(), - makerAskToExecute, - signature, - merkleTree, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(_genericTakerOrder(), makerAskToExecute, signature, merkleTree); // Taker user has received the asset assertEq(mockERC721.ownerOf(orderIndex), takerUser); @@ -73,8 +70,7 @@ contract BatchMakerOrdersTest is ProtocolBase { assertEq(address(looksRareProtocol).balance, 0); // Verify the nonce is marked as executed assertEq( - looksRareProtocol.userOrderNonce(makerUser, makerAskToExecute.orderNonce), - MAGIC_VALUE_ORDER_NONCE_EXECUTED + looksRareProtocol.userOrderNonce(makerUser, makerAskToExecute.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED ); } @@ -85,11 +81,8 @@ contract BatchMakerOrdersTest is ProtocolBase { OrderStructs.Maker[] memory makerBids = _createBatchMakerBids(numberOrders); - (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( - makerUserPK, - makerBids, - orderIndex - ); + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = + eip712MerkleTree.sign(makerUserPK, makerBids, orderIndex); OrderStructs.Maker memory makerBidToExecute = makerBids[orderIndex]; @@ -98,13 +91,7 @@ contract BatchMakerOrdersTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk( - _genericTakerOrder(), - makerBidToExecute, - signature, - merkleTree, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerAsk(_genericTakerOrder(), makerBidToExecute, signature, merkleTree); // Maker user has received the asset assertEq(mockERC721.ownerOf(orderIndex), makerUser); @@ -117,23 +104,21 @@ contract BatchMakerOrdersTest is ProtocolBase { ); // Verify the nonce is marked as executed assertEq( - looksRareProtocol.userOrderNonce(makerUser, makerBidToExecute.orderNonce), - MAGIC_VALUE_ORDER_NONCE_EXECUTED + looksRareProtocol.userOrderNonce(makerUser, makerBidToExecute.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED ); } - function testTakerBidMultipleOrdersSignedERC721MerkleProofInvalid(uint256 numberOrders, uint256 orderIndex) public { + function testTakerBidMultipleOrdersSignedERC721MerkleProofInvalid(uint256 numberOrders, uint256 orderIndex) + public + { _assertMerkleTreeAssumptions(numberOrders, orderIndex); mockERC721.batchMint(makerUser, numberOrders); OrderStructs.Maker[] memory makerAsks = _createBatchMakerAsks(numberOrders); - (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( - makerUserPK, - makerAsks, - orderIndex - ); + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = + eip712MerkleTree.sign(makerUserPK, makerAsks, orderIndex); bytes32 tamperedRoot = bytes32(uint256(merkleTree.root) + 1); merkleTree.root = tamperedRoot; @@ -142,35 +127,25 @@ contract BatchMakerOrdersTest is ProtocolBase { // Verify invalidity of maker ask order _assertMakerOrderReturnValidationCodeWithMerkleTree( - makerAskToExecute, - signature, - merkleTree, - ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE + makerAskToExecute, signature, merkleTree, ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE ); vm.prank(takerUser); vm.expectRevert(MerkleProofInvalid.selector); - looksRareProtocol.executeTakerBid{ value: price }( - _genericTakerOrder(), - makerAskToExecute, - signature, - merkleTree, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(_genericTakerOrder(), makerAskToExecute, signature, merkleTree); } - function testTakerAskMultipleOrdersSignedERC721MerkleProofInvalid(uint256 numberOrders, uint256 orderIndex) public { + function testTakerAskMultipleOrdersSignedERC721MerkleProofInvalid(uint256 numberOrders, uint256 orderIndex) + public + { _assertMerkleTreeAssumptions(numberOrders, orderIndex); mockERC721.batchMint(takerUser, numberOrders); OrderStructs.Maker[] memory makerBids = _createBatchMakerBids(numberOrders); - (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( - makerUserPK, - makerBids, - orderIndex - ); + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = + eip712MerkleTree.sign(makerUserPK, makerBids, orderIndex); bytes32 tamperedRoot = bytes32(uint256(merkleTree.root) + 1); merkleTree.root = tamperedRoot; @@ -179,38 +154,25 @@ contract BatchMakerOrdersTest is ProtocolBase { // Verify invalidity of maker bid order _assertMakerOrderReturnValidationCodeWithMerkleTree( - makerBidToExecute, - signature, - merkleTree, - ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE + makerBidToExecute, signature, merkleTree, ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE ); vm.prank(takerUser); vm.expectRevert(MerkleProofInvalid.selector); - looksRareProtocol.executeTakerAsk( - _genericTakerOrder(), - makerBidToExecute, - signature, - merkleTree, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerAsk(_genericTakerOrder(), makerBidToExecute, signature, merkleTree); } - function testTakerBidMultipleOrdersSignedERC721MerkleProofWrongPosition( - uint256 numberOrders, - uint256 orderIndex - ) public { + function testTakerBidMultipleOrdersSignedERC721MerkleProofWrongPosition(uint256 numberOrders, uint256 orderIndex) + public + { _assertMerkleTreeAssumptions(numberOrders, orderIndex); mockERC721.batchMint(makerUser, numberOrders); OrderStructs.Maker[] memory makerAsks = _createBatchMakerAsks(numberOrders); - (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( - makerUserPK, - makerAsks, - orderIndex - ); + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = + eip712MerkleTree.sign(makerUserPK, makerAsks, orderIndex); // Swap every node's position OrderStructs.MerkleTreeNode[] memory proof = merkleTree.proof; @@ -226,38 +188,25 @@ contract BatchMakerOrdersTest is ProtocolBase { // Verify invalidity of maker ask order _assertMakerOrderReturnValidationCodeWithMerkleTree( - makerAskToExecute, - signature, - merkleTree, - ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE + makerAskToExecute, signature, merkleTree, ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE ); vm.prank(takerUser); vm.expectRevert(MerkleProofInvalid.selector); - looksRareProtocol.executeTakerBid{ value: price }( - _genericTakerOrder(), - makerAskToExecute, - signature, - merkleTree, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(_genericTakerOrder(), makerAskToExecute, signature, merkleTree); } - function testTakerAskMultipleOrdersSignedERC721MerkleProofWrongPosition( - uint256 numberOrders, - uint256 orderIndex - ) public { + function testTakerAskMultipleOrdersSignedERC721MerkleProofWrongPosition(uint256 numberOrders, uint256 orderIndex) + public + { _assertMerkleTreeAssumptions(numberOrders, orderIndex); mockERC721.batchMint(takerUser, numberOrders); OrderStructs.Maker[] memory makerBids = _createBatchMakerBids(numberOrders); - (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( - makerUserPK, - makerBids, - orderIndex - ); + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = + eip712MerkleTree.sign(makerUserPK, makerBids, orderIndex); // Swap every node's position OrderStructs.MerkleTreeNode[] memory proof = merkleTree.proof; @@ -273,21 +222,12 @@ contract BatchMakerOrdersTest is ProtocolBase { // Verify invalidity of maker bid order _assertMakerOrderReturnValidationCodeWithMerkleTree( - makerBidToExecute, - signature, - merkleTree, - ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE + makerBidToExecute, signature, merkleTree, ORDER_HASH_PROOF_NOT_IN_MERKLE_TREE ); vm.prank(takerUser); vm.expectRevert(MerkleProofInvalid.selector); - looksRareProtocol.executeTakerAsk( - _genericTakerOrder(), - makerBidToExecute, - signature, - merkleTree, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerAsk(_genericTakerOrder(), makerBidToExecute, signature, merkleTree); } function testTakerBidRevertsIfProofTooLarge() public { @@ -301,30 +241,20 @@ contract BatchMakerOrdersTest is ProtocolBase { OrderStructs.Maker[] memory makerAsks = _createBatchMakerAsks(numberOrders); - (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( - makerUserPK, - makerAsks, - orderIndex - ); + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = + eip712MerkleTree.sign(makerUserPK, makerAsks, orderIndex); OrderStructs.Maker memory makerAskToExecute = makerAsks[orderIndex]; // Verify validity _assertMakerOrderReturnValidationCodeWithMerkleTree( - makerAskToExecute, - signature, - merkleTree, - MERKLE_PROOF_PROOF_TOO_LARGE + makerAskToExecute, signature, merkleTree, MERKLE_PROOF_PROOF_TOO_LARGE ); vm.prank(takerUser); vm.expectRevert(abi.encodeWithSelector(MerkleProofTooLarge.selector, proofLength)); - looksRareProtocol.executeTakerBid{ value: price }( - _genericTakerOrder(), - makerAskToExecute, - signature, - merkleTree, - _EMPTY_AFFILIATE + looksRareProtocol.executeTakerBid{value: price}( + _genericTakerOrder(), makerAskToExecute, signature, merkleTree ); } } @@ -340,30 +270,20 @@ contract BatchMakerOrdersTest is ProtocolBase { OrderStructs.Maker[] memory makerBids = _createBatchMakerBids(numberOrders); - (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = eip712MerkleTree.sign( - makerUserPK, - makerBids, - orderIndex - ); + (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) = + eip712MerkleTree.sign(makerUserPK, makerBids, orderIndex); OrderStructs.Maker memory makerBidToExecute = makerBids[orderIndex]; // Verify validity _assertMakerOrderReturnValidationCodeWithMerkleTree( - makerBidToExecute, - signature, - merkleTree, - MERKLE_PROOF_PROOF_TOO_LARGE + makerBidToExecute, signature, merkleTree, MERKLE_PROOF_PROOF_TOO_LARGE ); vm.prank(takerUser); vm.expectRevert(abi.encodeWithSelector(MerkleProofTooLarge.selector, proofLength)); - looksRareProtocol.executeTakerBid{ value: price }( - _genericTakerOrder(), - makerBidToExecute, - signature, - merkleTree, - _EMPTY_AFFILIATE + looksRareProtocol.executeTakerBid{value: price}( + _genericTakerOrder(), makerBidToExecute, signature, merkleTree ); } } diff --git a/contracts/test/foundry/marketplace/BatchOrderTypehashRegistry.t.sol b/contracts/test/foundry/marketplace/BatchOrderTypehashRegistry.t.sol index cbbf7cb3..e44c2af4 100644 --- a/contracts/test/foundry/marketplace/BatchOrderTypehashRegistry.t.sol +++ b/contracts/test/foundry/marketplace/BatchOrderTypehashRegistry.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { Test } from "forge-std/Test.sol"; +import {Test} from "forge-std/Test.sol"; -import { BatchOrderTypehashRegistry } from "@hypercerts/marketplace/BatchOrderTypehashRegistry.sol"; +import {BatchOrderTypehashRegistry} from "@hypercerts/marketplace/BatchOrderTypehashRegistry.sol"; // Shared errors -import { MerkleProofTooLarge } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import {MerkleProofTooLarge} from "@hypercerts/marketplace/errors/SharedErrors.sol"; contract BatchOrderTypehashRegistryInheriter is BatchOrderTypehashRegistry { function getBatchOrderTypehash(uint256 height) external pure returns (bytes32 typehash) { @@ -19,67 +19,44 @@ contract BatchOrderTypehashRegistryTest is Test { BatchOrderTypehashRegistryInheriter registry = new BatchOrderTypehashRegistryInheriter(); bytes32 root = hex"6942000000000000000000000000000000000000000000000000000000000000"; assertEq( - registry.hashBatchOrder(root, 1), - hex"8f0c85a215cff55fe39cf62ee7a1e0b5205a8ade02ff12ffee9ece02d626ffc3" + registry.hashBatchOrder(root, 1), hex"8f0c85a215cff55fe39cf62ee7a1e0b5205a8ade02ff12ffee9ece02d626ffc3" ); assertEq( - registry.hashBatchOrder(root, 2), - hex"f04a7d8a4688cf084b00b51ed583de7e5a19e59b073635e00a45a474899e89ec" + registry.hashBatchOrder(root, 2), hex"f04a7d8a4688cf084b00b51ed583de7e5a19e59b073635e00a45a474899e89ec" ); assertEq( - registry.hashBatchOrder(root, 3), - hex"56ef3bb8c564d19cfe494776934aa5e7ed84c41ae609d5f10e726f76281dd30b" + registry.hashBatchOrder(root, 3), hex"56ef3bb8c564d19cfe494776934aa5e7ed84c41ae609d5f10e726f76281dd30b" ); assertEq( - registry.hashBatchOrder(root, 4), - hex"2b0cb021eacab73e36d9ac9a04c1cf58589ff5bb4dc0d9b88ec29f67358ca812" + registry.hashBatchOrder(root, 4), hex"2b0cb021eacab73e36d9ac9a04c1cf58589ff5bb4dc0d9b88ec29f67358ca812" ); assertEq( - registry.hashBatchOrder(root, 5), - hex"253b3cc8d591a8b01fc8967cefe3ac3d0e078b884d96aa589f1ffd4536921bbb" + registry.hashBatchOrder(root, 5), hex"253b3cc8d591a8b01fc8967cefe3ac3d0e078b884d96aa589f1ffd4536921bbb" ); assertEq( - registry.hashBatchOrder(root, 6), - hex"7e4c4a2c5806fc4765bca325e8b78ccf9633bd1c7643144a56210293daefcbca" + registry.hashBatchOrder(root, 6), hex"7e4c4a2c5806fc4765bca325e8b78ccf9633bd1c7643144a56210293daefcbca" ); assertEq( - registry.hashBatchOrder(root, 7), - hex"e8e39cebe7137f0fadf6b88ba611044ac79c0168444eab66ca53bddd0c5fb717" + registry.hashBatchOrder(root, 7), hex"e8e39cebe7137f0fadf6b88ba611044ac79c0168444eab66ca53bddd0c5fb717" ); assertEq( - registry.hashBatchOrder(root, 8), - hex"6e02f123509255ed381c7552de5e2ac1c1ea401a23e026e2452f01b70564affb" + registry.hashBatchOrder(root, 8), hex"6e02f123509255ed381c7552de5e2ac1c1ea401a23e026e2452f01b70564affb" ); assertEq( - registry.hashBatchOrder(root, 9), - hex"7eeb4a7fe4655841fdd66f8ecfcf6cd261d50eafabbaebb10f63f5fe84ddddc9" + registry.hashBatchOrder(root, 9), hex"7eeb4a7fe4655841fdd66f8ecfcf6cd261d50eafabbaebb10f63f5fe84ddddc9" ); assertEq( - registry.hashBatchOrder(root, 10), - hex"a96dee8b7b88deda5d50b55f641ca08c1ee00825eeb1db7a324f392fa0b8bb83" + registry.hashBatchOrder(root, 10), hex"a96dee8b7b88deda5d50b55f641ca08c1ee00825eeb1db7a324f392fa0b8bb83" ); } function testGetTypehash() public { BatchOrderTypehashRegistryInheriter registry = new BatchOrderTypehashRegistryInheriter(); bytes memory makerOrderString = bytes( - "Maker(" - "uint8 quoteType," - "uint256 globalNonce," - "uint256 subsetNonce," - "uint256 orderNonce," - "uint256 strategyId," - "uint8 collectionType," - "address collection," - "address currency," - "address signer," - "uint256 startTime," - "uint256 endTime," - "uint256 price," - "uint256[] itemIds," - "uint256[] amounts," - "bytes additionalParameters" - ")" + "Maker(" "uint8 quoteType," "uint256 globalNonce," "uint256 subsetNonce," "uint256 orderNonce," + "uint256 strategyId," "uint8 collectionType," "address collection," "address currency," "address signer," + "uint256 startTime," "uint256 endTime," "uint256 price," "uint256[] itemIds," "uint256[] amounts," + "bytes additionalParameters" ")" ); assertEq( diff --git a/contracts/test/foundry/marketplace/BundleTransactions.t.sol b/contracts/test/foundry/marketplace/BundleTransactions.t.sol index c7331cd3..62ffccf9 100644 --- a/contracts/test/foundry/marketplace/BundleTransactions.t.sol +++ b/contracts/test/foundry/marketplace/BundleTransactions.t.sol @@ -2,13 +2,13 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Other tests -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; contract BundleTransactionsTest is ProtocolBase { function setUp() public { @@ -19,10 +19,8 @@ contract BundleTransactionsTest is ProtocolBase { _setUpUsers(); uint256 numberItemsInBundle = 5; - ( - OrderStructs.Maker memory makerBid, - OrderStructs.Taker memory takerAsk - ) = _createMockMakerBidAndTakerAskWithBundle(address(mockERC721), address(weth), numberItemsInBundle); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAskWithBundle(address(mockERC721), address(weth), numberItemsInBundle); // Sign the order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -35,7 +33,7 @@ contract BundleTransactionsTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); _assertMockERC721Ownership(makerBid.itemIds, makerUser); @@ -46,10 +44,8 @@ contract BundleTransactionsTest is ProtocolBase { _setUpUsers(); uint256 numberItemsInBundle = 5; - ( - OrderStructs.Maker memory makerBid, - OrderStructs.Taker memory takerAsk - ) = _createMockMakerBidAndTakerAskWithBundle(address(mockERC1155), address(weth), numberItemsInBundle); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAskWithBundle(address(mockERC1155), address(weth), numberItemsInBundle); // Sign the order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -62,7 +58,7 @@ contract BundleTransactionsTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); for (uint256 i; i < makerBid.itemIds.length; i++) { // Maker user has received all the assets in the bundle @@ -77,10 +73,8 @@ contract BundleTransactionsTest is ProtocolBase { _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); uint256 numberItemsInBundle = 5; - ( - OrderStructs.Maker memory makerBid, - OrderStructs.Taker memory takerAsk - ) = _createMockMakerBidAndTakerAskWithBundle(address(mockERC721), address(weth), numberItemsInBundle); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAskWithBundle(address(mockERC721), address(weth), numberItemsInBundle); uint256 price = makerBid.price; @@ -95,7 +89,7 @@ contract BundleTransactionsTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); _assertMockERC721Ownership(makerBid.itemIds, makerUser); @@ -124,10 +118,8 @@ contract BundleTransactionsTest is ProtocolBase { _setUpUsers(); uint256 numberItemsInBundle = 5; - ( - OrderStructs.Maker memory makerAsk, - OrderStructs.Taker memory takerBid - ) = _createMockMakerAskAndTakerBidWithBundle(address(mockERC721), numberItemsInBundle); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBidWithBundle(address(mockERC721), numberItemsInBundle); uint256 price = makerAsk.price; @@ -140,13 +132,7 @@ contract BundleTransactionsTest is ProtocolBase { // Execute taker bid transaction vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); _assertMockERC721Ownership(makerAsk.itemIds, takerUser); @@ -157,10 +143,8 @@ contract BundleTransactionsTest is ProtocolBase { _setUpUsers(); uint256 numberItemsInBundle = 5; - ( - OrderStructs.Maker memory makerAsk, - OrderStructs.Taker memory takerBid - ) = _createMockMakerAskAndTakerBidWithBundle(address(mockERC1155), numberItemsInBundle); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBidWithBundle(address(mockERC1155), numberItemsInBundle); uint256 price = makerAsk.price; @@ -173,13 +157,7 @@ contract BundleTransactionsTest is ProtocolBase { // Execute taker bid transaction vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); for (uint256 i; i < makerAsk.itemIds.length; i++) { // Taker user has received all the assets in the bundle @@ -194,10 +172,8 @@ contract BundleTransactionsTest is ProtocolBase { _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); uint256 numberItemsInBundle = 5; - ( - OrderStructs.Maker memory makerAsk, - OrderStructs.Taker memory takerBid - ) = _createMockMakerAskAndTakerBidWithBundle(address(mockERC721), numberItemsInBundle); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBidWithBundle(address(mockERC721), numberItemsInBundle); uint256 price = makerAsk.price; @@ -211,13 +187,7 @@ contract BundleTransactionsTest is ProtocolBase { // Execute taker bid transaction vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); _assertMockERC721Ownership(makerAsk.itemIds, takerUser); diff --git a/contracts/test/foundry/marketplace/CreatorFeeManagerWithRebates.t.sol b/contracts/test/foundry/marketplace/CreatorFeeManagerWithRebates.t.sol index 6a3b7ac0..93a552db 100644 --- a/contracts/test/foundry/marketplace/CreatorFeeManagerWithRebates.t.sol +++ b/contracts/test/foundry/marketplace/CreatorFeeManagerWithRebates.t.sol @@ -2,23 +2,23 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IERC721 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC721.sol"; +import {IERC721} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC721.sol"; -import { CreatorFeeManagerWithRebates } from "@hypercerts/marketplace/CreatorFeeManagerWithRebates.sol"; +import {CreatorFeeManagerWithRebates} from "@hypercerts/marketplace/CreatorFeeManagerWithRebates.sol"; // Libraries and interfaces -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { ICreatorFeeManager } from "@hypercerts/marketplace/interfaces/ICreatorFeeManager.sol"; -import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {ICreatorFeeManager} from "@hypercerts/marketplace/interfaces/ICreatorFeeManager.sol"; +import {IExecutionManager} from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; // Shared errors -import { BUNDLE_ERC2981_NOT_SUPPORTED } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import {BUNDLE_ERC2981_NOT_SUPPORTED} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; contract CreatorFeeManagerWithRebatesTest is ProtocolBase { function setUp() public { @@ -32,20 +32,15 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { function _setUpRoyaltiesRegistry(uint256 fee) private { vm.prank(_owner); royaltyFeeRegistry.updateRoyaltyInfoForCollection( - address(mockERC721), - _royaltyRecipient, - _royaltyRecipient, - fee + address(mockERC721), _royaltyRecipient, _royaltyRecipient, fee ); } function _testCreatorFeeRebatesArePaid(address erc721) private { _setUpUsers(); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - erc721, - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(erc721, address(weth)); bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -57,9 +52,7 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { } else if (erc721 == address(mockERC721WithRoyalties)) { // Adjust ERC721 with royalties mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( - makerBid.itemIds[0], - _royaltyRecipient, - _standardRoyaltyFee + makerBid.itemIds[0], _royaltyRecipient, _standardRoyaltyFee ); // Mint asset mockERC721WithRoyalties.mint(takerUser, makerBid.itemIds[0]); @@ -69,7 +62,7 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // Verify ownership is transferred assertEq(IERC721(erc721).ownerOf(makerBid.itemIds[0]), makerUser); @@ -84,10 +77,8 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { uint256 numberItemsInBundle = 5; // Create order - ( - OrderStructs.Maker memory makerBid, - OrderStructs.Taker memory takerAsk - ) = _createMockMakerBidAndTakerAskWithBundle(erc721, address(weth), numberItemsInBundle); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAskWithBundle(erc721, address(weth), numberItemsInBundle); if (erc721 == address(mockERC721)) { // Adjust royalties @@ -98,9 +89,7 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { // Adjust ERC721 with royalties for (uint256 i; i < makerBid.itemIds.length; i++) { mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( - makerBid.itemIds[i], - _royaltyRecipient, - _standardRoyaltyFee + makerBid.itemIds[i], _royaltyRecipient, _standardRoyaltyFee ); } // Mint the items @@ -116,7 +105,7 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { vm.prank(takerUser); // Execute taker ask transaction - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // Verify ownership is transferred for (uint256 i; i < makerBid.itemIds.length; i++) { @@ -147,14 +136,8 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { uint256 numberItemsInBundle = 5; - ( - OrderStructs.Maker memory makerBid, - OrderStructs.Taker memory takerAsk - ) = _createMockMakerBidAndTakerAskWithBundle( - address(mockERC721WithRoyalties), - address(weth), - numberItemsInBundle - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAskWithBundle(address(mockERC721WithRoyalties), address(weth), numberItemsInBundle); // Sign the order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -171,9 +154,7 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { // Adjust ERC721 with royalties for (uint256 i; i < makerBid.itemIds.length; i++) { mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( - makerBid.itemIds[i], - i == 0 ? _royaltyRecipient : address(50), - 50 + makerBid.itemIds[i], i == 0 ? _royaltyRecipient : address(50), 50 ); } @@ -182,11 +163,10 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert( abi.encodeWithSelector( - ICreatorFeeManager.BundleEIP2981NotAllowed.selector, - address(mockERC721WithRoyalties) + ICreatorFeeManager.BundleEIP2981NotAllowed.selector, address(mockERC721WithRoyalties) ) ); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testCreatorRoyaltiesRevertForEIP2981WithBundlesIfAtLeastOneCallReverts(uint256 revertIndex) public { @@ -195,14 +175,8 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { uint256 numberItemsInBundle = 5; vm.assume(revertIndex < numberItemsInBundle); - ( - OrderStructs.Maker memory makerBid, - OrderStructs.Taker memory takerAsk - ) = _createMockMakerBidAndTakerAskWithBundle( - address(mockERC721WithRoyalties), - address(weth), - numberItemsInBundle - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAskWithBundle(address(mockERC721WithRoyalties), address(weth), numberItemsInBundle); // Sign the order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -227,11 +201,10 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert( abi.encodeWithSelector( - ICreatorFeeManager.BundleEIP2981NotAllowed.selector, - address(mockERC721WithRoyalties) + ICreatorFeeManager.BundleEIP2981NotAllowed.selector, address(mockERC721WithRoyalties) ) ); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function _assertSuccessfulTakerAsk(OrderStructs.Maker memory makerBid) private { @@ -246,7 +219,7 @@ contract CreatorFeeManagerWithRebatesTest is ProtocolBase { ); assertEq( weth.balanceOf(takerUser), - _initialWETHBalanceUser + (price * 9_900) / ONE_HUNDRED_PERCENT_IN_BP, + _initialWETHBalanceUser + (price * 9900) / ONE_HUNDRED_PERCENT_IN_BP, "Taker ask user should receive 99% of the whole price" ); assertEq( diff --git a/contracts/test/foundry/marketplace/CreatorFeeManagerWithRoyalties.t.sol b/contracts/test/foundry/marketplace/CreatorFeeManagerWithRoyalties.t.sol index d4fea298..3ba84222 100644 --- a/contracts/test/foundry/marketplace/CreatorFeeManagerWithRoyalties.t.sol +++ b/contracts/test/foundry/marketplace/CreatorFeeManagerWithRoyalties.t.sol @@ -2,21 +2,24 @@ pragma solidity 0.8.17; // Libraries and interfaces -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { ICreatorFeeManager } from "@hypercerts/marketplace/interfaces/ICreatorFeeManager.sol"; -import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {ICreatorFeeManager} from "@hypercerts/marketplace/interfaces/ICreatorFeeManager.sol"; +import {IExecutionManager} from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; // Core contract -import { CreatorFeeManagerWithRoyalties } from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; +import {CreatorFeeManagerWithRoyalties} from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; // Shared errors -import { BUNDLE_ERC2981_NOT_SUPPORTED, CREATOR_FEE_TOO_HIGH } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import { + BUNDLE_ERC2981_NOT_SUPPORTED, + CREATOR_FEE_TOO_HIGH +} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { CreatorFeeManagerWithRoyalties public creatorFeeManagerWithRoyalties; @@ -30,10 +33,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { function _setUpRoyaltiesRegistry(uint256 fee) internal { vm.prank(_owner); royaltyFeeRegistry.updateRoyaltyInfoForCollection( - address(mockERC721), - _royaltyRecipient, - _royaltyRecipient, - fee + address(mockERC721), _royaltyRecipient, _royaltyRecipient, fee ); } @@ -56,7 +56,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { // Adjust royalties _setUpRoyaltiesRegistry(_newCreatorRoyaltyFee); - (OrderStructs.Maker memory makerBid, ) = _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); + (OrderStructs.Maker memory makerBid,) = _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); // Sign order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -68,13 +68,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk( - _genericTakerOrder(), - makerBid, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerAsk(_genericTakerOrder(), makerBid, signature, _EMPTY_MERKLE_TREE); // Taker user has received the asset assertEq(mockERC721.ownerOf(makerBid.itemIds[0]), makerUser); @@ -84,16 +78,12 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { function testCreatorRoyaltiesGetPaidForERC2981() public { _setUpUsers(); - (OrderStructs.Maker memory makerBid, ) = _createMockMakerBidAndTakerAsk( - address(mockERC721WithRoyalties), - address(weth) - ); + (OrderStructs.Maker memory makerBid,) = + _createMockMakerBidAndTakerAsk(address(mockERC721WithRoyalties), address(weth)); // Adjust ERC721 with royalties mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( - makerBid.itemIds[0], - _royaltyRecipient, - _newCreatorRoyaltyFee + makerBid.itemIds[0], _royaltyRecipient, _newCreatorRoyaltyFee ); // Sign order @@ -106,13 +96,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk( - _genericTakerOrder(), - makerBid, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerAsk(_genericTakerOrder(), makerBid, signature, _EMPTY_MERKLE_TREE); // Taker user has received the asset assertEq(mockERC721WithRoyalties.ownerOf(makerBid.itemIds[0]), makerUser); @@ -127,10 +111,8 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { uint256 numberItemsInBundle = 5; - ( - OrderStructs.Maker memory makerBid, - OrderStructs.Taker memory takerAsk - ) = _createMockMakerBidAndTakerAskWithBundle(address(mockERC721), address(weth), numberItemsInBundle); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAskWithBundle(address(mockERC721), address(weth), numberItemsInBundle); // Sign the order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -145,7 +127,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { vm.prank(takerUser); // Execute taker ask transaction - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); _assertMockERC721Ownership(makerBid.itemIds, makerUser); @@ -157,14 +139,8 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { uint256 numberItemsInBundle = 5; - ( - OrderStructs.Maker memory makerBid, - OrderStructs.Taker memory takerAsk - ) = _createMockMakerBidAndTakerAskWithBundle( - address(mockERC721WithRoyalties), - address(weth), - numberItemsInBundle - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAskWithBundle(address(mockERC721WithRoyalties), address(weth), numberItemsInBundle); // Sign the order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -175,9 +151,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { // Adjust ERC721 with royalties for (uint256 i; i < makerBid.itemIds.length; i++) { mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( - makerBid.itemIds[i], - _royaltyRecipient, - _newCreatorRoyaltyFee + makerBid.itemIds[i], _royaltyRecipient, _newCreatorRoyaltyFee ); } @@ -187,7 +161,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { vm.prank(takerUser); // Execute taker ask transaction - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); _assertSuccessfulTakerAskBundle(makerBid); } @@ -197,14 +171,8 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { uint256 numberItemsInBundle = 5; - ( - OrderStructs.Maker memory makerBid, - OrderStructs.Taker memory takerAsk - ) = _createMockMakerBidAndTakerAskWithBundle( - address(mockERC721WithRoyalties), - address(weth), - numberItemsInBundle - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAskWithBundle(address(mockERC721WithRoyalties), address(weth), numberItemsInBundle); // Sign the order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -231,12 +199,11 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert( abi.encodeWithSelector( - ICreatorFeeManager.BundleEIP2981NotAllowed.selector, - address(mockERC721WithRoyalties) + ICreatorFeeManager.BundleEIP2981NotAllowed.selector, address(mockERC721WithRoyalties) ) ); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); /** * 2. Same fee structure but different recipient @@ -244,9 +211,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { // Adjust ERC721 with royalties for (uint256 i; i < makerBid.itemIds.length; i++) { mockERC721WithRoyalties.addCustomRoyaltyInformationForTokenId( - makerBid.itemIds[i], - i == 0 ? _royaltyRecipient : address(50), - _newCreatorRoyaltyFee + makerBid.itemIds[i], i == 0 ? _royaltyRecipient : address(50), _newCreatorRoyaltyFee ); } @@ -255,12 +220,11 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert( abi.encodeWithSelector( - ICreatorFeeManager.BundleEIP2981NotAllowed.selector, - address(mockERC721WithRoyalties) + ICreatorFeeManager.BundleEIP2981NotAllowed.selector, address(mockERC721WithRoyalties) ) ); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testCreatorRoyaltiesRevertForEIP2981WithBundlesIfAtLeastOneCallReverts(uint256 revertIndex) public { @@ -269,14 +233,8 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { uint256 numberItemsInBundle = 5; vm.assume(revertIndex < numberItemsInBundle); - ( - OrderStructs.Maker memory makerBid, - OrderStructs.Taker memory takerAsk - ) = _createMockMakerBidAndTakerAskWithBundle( - address(mockERC721WithRoyalties), - address(weth), - numberItemsInBundle - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAskWithBundle(address(mockERC721WithRoyalties), address(weth), numberItemsInBundle); // Sign the order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -300,12 +258,11 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert( abi.encodeWithSelector( - ICreatorFeeManager.BundleEIP2981NotAllowed.selector, - address(mockERC721WithRoyalties) + ICreatorFeeManager.BundleEIP2981NotAllowed.selector, address(mockERC721WithRoyalties) ) ); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testCreatorRoyaltiesRevertIfFeeHigherThanLimit() public { @@ -315,10 +272,8 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { // Adjust royalties _setUpRoyaltiesRegistry(_creatorRoyaltyFeeTooHigh); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -329,16 +284,15 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { vm.expectRevert(IExecutionManager.CreatorFeeBpTooHigh.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // 2. Maker ask // Mint asset mockERC721.mint(makerUser, 1); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); // The itemId changes as it is already minted before makerAsk.itemIds[0] = 1; @@ -349,13 +303,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { vm.expectRevert(IExecutionManager.CreatorFeeBpTooHigh.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: 1 ether }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: 1 ether}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function _assertSuccessfulTakerAsk(OrderStructs.Maker memory makerBid) private { @@ -369,7 +317,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { "ProtocolFeeRecipient should receive 2% of the whole price" ); // Taker ask user receives 95% of the whole price - assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser + (price * 9_500) / ONE_HUNDRED_PERCENT_IN_BP); + assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser + (price * 9500) / ONE_HUNDRED_PERCENT_IN_BP); // Royalty recipient receives 3% of the whole price assertEq( weth.balanceOf(_royaltyRecipient), @@ -395,7 +343,7 @@ contract CreatorFeeManagerWithRoyaltiesTest is ProtocolBase { "ProtocolFeeRecipient should receive protocol fee" ); // Taker ask user receives 95% of the whole price - assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser + (price * 9_500) / ONE_HUNDRED_PERCENT_IN_BP); + assertEq(weth.balanceOf(takerUser), _initialWETHBalanceUser + (price * 9500) / ONE_HUNDRED_PERCENT_IN_BP); // Verify the nonce is marked as executed assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); } diff --git a/contracts/test/foundry/marketplace/CurrencyManager.t.sol b/contracts/test/foundry/marketplace/CurrencyManager.t.sol index 3b00915a..8c410dca 100644 --- a/contracts/test/foundry/marketplace/CurrencyManager.t.sol +++ b/contracts/test/foundry/marketplace/CurrencyManager.t.sol @@ -2,15 +2,15 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; +import {IOwnableTwoSteps} from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; // Core contracts -import { CurrencyManager, ICurrencyManager } from "@hypercerts/marketplace/CurrencyManager.sol"; +import {CurrencyManager, ICurrencyManager} from "@hypercerts/marketplace/CurrencyManager.sol"; // Other mocks and utils -import { TestHelpers } from "./utils/TestHelpers.sol"; -import { TestParameters } from "./utils/TestParameters.sol"; -import { MockERC20 } from "../../mock/MockERC20.sol"; +import {TestHelpers} from "./utils/TestHelpers.sol"; +import {TestParameters} from "./utils/TestParameters.sol"; +import {MockERC20} from "../../mock/MockERC20.sol"; contract CurrencyManagerTest is TestHelpers, TestParameters, ICurrencyManager { CurrencyManager private currencyManager; diff --git a/contracts/test/foundry/marketplace/DelegationRecipientsTaker.t.sol b/contracts/test/foundry/marketplace/DelegationRecipientsTaker.t.sol index b052c146..ea5e6445 100644 --- a/contracts/test/foundry/marketplace/DelegationRecipientsTaker.t.sol +++ b/contracts/test/foundry/marketplace/DelegationRecipientsTaker.t.sol @@ -2,14 +2,14 @@ pragma solidity 0.8.17; // Libraries and interfaces -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { CreatorFeeManagerWithRoyalties } from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {CreatorFeeManagerWithRoyalties} from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; contract DelegationRecipientsTakerTest is ProtocolBase { function setUp() public { @@ -32,10 +32,8 @@ contract DelegationRecipientsTakerTest is ProtocolBase { _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); address randomRecipientSaleProceeds = address(420); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -77,7 +75,7 @@ contract DelegationRecipientsTakerTest is ProtocolBase { expectedRecipients, expectedFees ); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // Taker user has received the asset assertEq(mockERC721.ownerOf(makerBid.itemIds[0]), makerUser); @@ -107,9 +105,8 @@ contract DelegationRecipientsTakerTest is ProtocolBase { _setUpUsers(); _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); // Mint asset mockERC721.mint(makerUser, makerAsk.itemIds[0]); @@ -151,13 +148,7 @@ contract DelegationRecipientsTakerTest is ProtocolBase { expectedFees ); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // Random recipient user has received the asset assertEq(mockERC721.ownerOf(makerAsk.itemIds[0]), randomRecipientNFT); diff --git a/contracts/test/foundry/marketplace/DomainSeparatorUpdates.t.sol b/contracts/test/foundry/marketplace/DomainSeparatorUpdates.t.sol index 3936ba5a..c1ed9701 100644 --- a/contracts/test/foundry/marketplace/DomainSeparatorUpdates.t.sol +++ b/contracts/test/foundry/marketplace/DomainSeparatorUpdates.t.sol @@ -2,15 +2,15 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; -import { SignatureEOAInvalid } from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; +import {IOwnableTwoSteps} from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; +import {SignatureEOAInvalid} from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; // Libraries and interfaces -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { ILooksRareProtocol } from "@hypercerts/marketplace/interfaces/ILooksRareProtocol.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {ILooksRareProtocol} from "@hypercerts/marketplace/interfaces/ILooksRareProtocol.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; contract DomainSeparatorUpdatesTest is ProtocolBase { function setUp() public { @@ -51,9 +51,8 @@ contract DomainSeparatorUpdatesTest is ProtocolBase { vm.prank(_owner); looksRareProtocol.updateDomainSeparator(); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); @@ -62,13 +61,7 @@ contract DomainSeparatorUpdatesTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(SignatureEOAInvalid.selector); - looksRareProtocol.executeTakerBid{ value: makerAsk.price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: makerAsk.price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testCannotTradeIfChainIdHasChanged(uint64 newChainId) public { @@ -79,9 +72,8 @@ contract DomainSeparatorUpdatesTest is ProtocolBase { // ChainId update vm.chainId(newChainId); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); @@ -90,13 +82,7 @@ contract DomainSeparatorUpdatesTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(ILooksRareProtocol.ChainIdInvalid.selector); - looksRareProtocol.executeTakerBid{ value: makerAsk.price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: makerAsk.price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testUpdateDomainSeparatorSameDomainSeparator() public asPrankedUser(_owner) { diff --git a/contracts/test/foundry/marketplace/ExecutionManager.t.sol b/contracts/test/foundry/marketplace/ExecutionManager.t.sol index edc413af..b330d91a 100644 --- a/contracts/test/foundry/marketplace/ExecutionManager.t.sol +++ b/contracts/test/foundry/marketplace/ExecutionManager.t.sol @@ -2,19 +2,27 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; +import {IOwnableTwoSteps} from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; // Libraries and interfaces -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; -import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {IExecutionManager} from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import {IStrategyManager} from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; // Shared errors -import { OrderInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; -import { MAKER_ORDER_INVALID_STANDARD_SALE, STRATEGY_INVALID_QUOTE_TYPE, STRATEGY_INVALID_QUOTE_TYPE, STRATEGY_NOT_ACTIVE, START_TIME_GREATER_THAN_END_TIME, TOO_LATE_TO_EXECUTE_ORDER, TOO_EARLY_TO_EXECUTE_ORDER } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import {OrderInvalid} from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { + MAKER_ORDER_INVALID_STANDARD_SALE, + STRATEGY_INVALID_QUOTE_TYPE, + STRATEGY_INVALID_QUOTE_TYPE, + STRATEGY_NOT_ACTIVE, + START_TIME_GREATER_THAN_END_TIME, + TOO_LATE_TO_EXECUTE_ORDER, + TOO_EARLY_TO_EXECUTE_ORDER +} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManager { function setUp() public { @@ -34,7 +42,7 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag } function testUpdateMaxCreatorFeeBp(uint16 newMaxCreatorFeeBp) public asPrankedUser(_owner) { - vm.assume(newMaxCreatorFeeBp <= 2_500); + vm.assume(newMaxCreatorFeeBp <= 2500); vm.expectEmit(true, false, false, true); emit NewMaxCreatorFeeBp(newMaxCreatorFeeBp); looksRareProtocol.updateMaxCreatorFeeBp(newMaxCreatorFeeBp); @@ -43,11 +51,11 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag function testUpdateMaxCreatorFeeBpNotOwner() public { vm.expectRevert(IOwnableTwoSteps.NotOwner.selector); - looksRareProtocol.updateMaxCreatorFeeBp(uint16(2_500)); + looksRareProtocol.updateMaxCreatorFeeBp(uint16(2500)); } function testUpdateMaxCreatorFeeBpTooHigh(uint16 newMaxCreatorFeeBp) public asPrankedUser(_owner) { - vm.assume(newMaxCreatorFeeBp > 2_500); + vm.assume(newMaxCreatorFeeBp > 2500); vm.expectRevert(CreatorFeeBpTooHigh.selector); looksRareProtocol.updateMaxCreatorFeeBp(newMaxCreatorFeeBp); } @@ -75,10 +83,8 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag // Change timestamp to avoid underflow issues vm.warp(timestamp); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); makerBid.startTime = block.timestamp; makerBid.endTime = block.timestamp + 1 seconds; @@ -91,7 +97,7 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag // Maker bid is invalid if its start time is not within 5 minutes into the future vm.warp(makerBid.startTime - 5 minutes - 1 seconds); vm.expectRevert(OutsideOfTimeRange.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testCannotValidateOrderIfTooLateToExecute(uint256 timestamp) public asPrankedUser(takerUser) { @@ -99,10 +105,8 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag // Change timestamp to avoid underflow issues vm.warp(timestamp); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); makerBid.startTime = block.timestamp - 1 seconds; makerBid.endTime = block.timestamp; @@ -113,7 +117,7 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag vm.warp(block.timestamp + 1 seconds); vm.expectRevert(OutsideOfTimeRange.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testCannotValidateOrderIfStartTimeLaterThanEndTime(uint256 timestamp) public asPrankedUser(takerUser) { @@ -121,10 +125,8 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag // Change timestamp to avoid underflow issues vm.warp(timestamp); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); makerBid.startTime = block.timestamp + 1 seconds; makerBid.endTime = block.timestamp; @@ -133,14 +135,12 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag _assertMakerOrderReturnValidationCode(makerBid, signature, START_TIME_GREATER_THAN_END_TIME); vm.expectRevert(OutsideOfTimeRange.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testCannotValidateOrderIfMakerBidItemIdsIsEmpty() public { - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); uint256[] memory itemIds = new uint256[](0); makerBid.itemIds = itemIds; @@ -149,18 +149,17 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_INVALID_STANDARD_SALE); vm.expectRevert(OrderInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } - function testCannotValidateOrderIfMakerBidItemIdsLengthMismatch( - uint256 makerBidItemIdsLength - ) public asPrankedUser(takerUser) { + function testCannotValidateOrderIfMakerBidItemIdsLengthMismatch(uint256 makerBidItemIdsLength) + public + asPrankedUser(takerUser) + { vm.assume(makerBidItemIdsLength > 1 && makerBidItemIdsLength < 100_000); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); uint256[] memory itemIds = new uint256[](makerBidItemIdsLength); makerBid.itemIds = itemIds; @@ -169,15 +168,14 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_INVALID_STANDARD_SALE); vm.expectRevert(OrderInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testCannotValidateOrderIfMakerAskItemIdsIsEmpty() public asPrankedUser(takerUser) { vm.deal(takerUser, 100 ether); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); // Change maker itemIds array to make its length equal to 0 uint256[] memory itemIds = new uint256[](0); @@ -187,25 +185,19 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_INVALID_STANDARD_SALE); vm.expectRevert(OrderInvalid.selector); - looksRareProtocol.executeTakerBid{ value: makerAsk.price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: makerAsk.price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } - function testCannotValidateOrderIfMakerAskItemIdsLengthMismatch( - uint256 makerAskItemIdsLength - ) public asPrankedUser(takerUser) { + function testCannotValidateOrderIfMakerAskItemIdsLengthMismatch(uint256 makerAskItemIdsLength) + public + asPrankedUser(takerUser) + { vm.deal(takerUser, 100 ether); vm.assume(makerAskItemIdsLength > 1 && makerAskItemIdsLength < 100_000); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); uint256[] memory itemIds = new uint256[](makerAskItemIdsLength); makerAsk.itemIds = itemIds; @@ -214,13 +206,7 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag _assertMakerOrderReturnValidationCode(makerAsk, signature, MAKER_ORDER_INVALID_STANDARD_SALE); vm.expectRevert(OrderInvalid.selector); - looksRareProtocol.executeTakerBid{ value: makerAsk.price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: makerAsk.price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } // TODO check is we need this test and replace the chainlink floor strategy @@ -255,7 +241,7 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag // vm.prank(takerUser); // vm.expectRevert(IExecutionManager.NoSelectorForStrategy.selector); // looksRareProtocol.executeTakerBid{value: makerAsk.price}( - // takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE + // takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE // ); // } @@ -291,6 +277,6 @@ contract ExecutionManagerTest is ProtocolBase, IExecutionManager, IStrategyManag // vm.prank(takerUser); // vm.expectRevert(IExecutionManager.NoSelectorForStrategy.selector); - // looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + // looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // } } diff --git a/contracts/test/foundry/marketplace/GasGriefing.t.sol b/contracts/test/foundry/marketplace/GasGriefing.t.sol index 31852b5a..b973ddff 100644 --- a/contracts/test/foundry/marketplace/GasGriefing.t.sol +++ b/contracts/test/foundry/marketplace/GasGriefing.t.sol @@ -2,21 +2,21 @@ pragma solidity 0.8.17; // Libraries and interfaces -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { WETH } from "solmate/src/tokens/WETH.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {WETH} from "solmate/src/tokens/WETH.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Mocks and other utils -import { GasGriefer } from "./utils/GasGriefer.sol"; +import {GasGriefer} from "./utils/GasGriefer.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract GasGriefingTest is ProtocolBase { uint256 private constant price = 1 ether; // Fixed price of sale @@ -36,9 +36,8 @@ contract GasGriefingTest is ProtocolBase { function testTakerBidGasGriefing() public { _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); makerAsk.signer = gasGriefer; // Mint asset @@ -56,13 +55,7 @@ contract GasGriefingTest is ProtocolBase { vm.prank(takerUser); // Execute taker bid transaction - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // Taker user has received the asset assertEq(mockERC721.ownerOf(makerAsk.itemIds[0]), takerUser); @@ -122,13 +115,8 @@ contract GasGriefingTest is ProtocolBase { vm.prank(takerUser); // Execute taker bid transaction - looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); for (uint256 i; i < numberPurchases; i++) { diff --git a/contracts/test/foundry/marketplace/InitialStates.t.sol b/contracts/test/foundry/marketplace/InitialStates.t.sol index c17f827b..5817a403 100644 --- a/contracts/test/foundry/marketplace/InitialStates.t.sol +++ b/contracts/test/foundry/marketplace/InitialStates.t.sol @@ -2,10 +2,10 @@ pragma solidity 0.8.17; // Interfaces -import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; +import {IStrategyManager} from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; contract InitialStatesTest is ProtocolBase, IStrategyManager { function setUp() public { diff --git a/contracts/test/foundry/marketplace/LooksRareProtocol.t.sol b/contracts/test/foundry/marketplace/LooksRareProtocol.t.sol index 73027c4b..5f685cec 100644 --- a/contracts/test/foundry/marketplace/LooksRareProtocol.t.sol +++ b/contracts/test/foundry/marketplace/LooksRareProtocol.t.sol @@ -2,24 +2,33 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; +import {IOwnableTwoSteps} from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Shared errors -import { AmountInvalid, CallerInvalid, CurrencyInvalid, OrderInvalid, QuoteTypeInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; -import { CURRENCY_NOT_ALLOWED, MAKER_ORDER_INVALID_STANDARD_SALE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import { + AmountInvalid, + CallerInvalid, + CurrencyInvalid, + OrderInvalid, + QuoteTypeInvalid +} from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { + CURRENCY_NOT_ALLOWED, + MAKER_ORDER_INVALID_STANDARD_SALE +} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Other mocks and utils -import { MockERC20 } from "../../mock/MockERC20.sol"; +import {MockERC20} from "../../mock/MockERC20.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract LooksRareProtocolTest is ProtocolBase { // Fixed price of sale @@ -37,9 +46,8 @@ contract LooksRareProtocolTest is ProtocolBase { function testCannotTradeIfInvalidAmounts() public { _setUpUsers(); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); // Mint asset mockERC721.mint(makerUser, makerAsk.itemIds[0]); @@ -54,13 +62,7 @@ contract LooksRareProtocolTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(OrderInvalid.selector); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // 2. Amount > 1 for ERC721 makerAsk.amounts[0] = 2; @@ -72,21 +74,14 @@ contract LooksRareProtocolTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(AmountInvalid.selector); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testCannotTradeIfCurrencyInvalid() public { _setUpUsers(); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); makerAsk.currency = address(mockERC20); // Mint asset @@ -100,13 +95,7 @@ contract LooksRareProtocolTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(CurrencyInvalid.selector); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); OrderStructs.Maker[] memory makerAsks = new OrderStructs.Maker[](1); OrderStructs.Taker[] memory takerBids = new OrderStructs.Taker[](1); @@ -119,32 +108,28 @@ contract LooksRareProtocolTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(CurrencyInvalid.selector); - looksRareProtocol.executeMultipleTakerBids{ value: price }( + looksRareProtocol.executeMultipleTakerBids{value: price}( takerBids, makerAsks, signatures, merkleTrees, - _EMPTY_AFFILIATE, true // Atomic ); vm.prank(takerUser); vm.expectRevert(CurrencyInvalid.selector); - looksRareProtocol.executeMultipleTakerBids{ value: price }( + looksRareProtocol.executeMultipleTakerBids{value: price}( takerBids, makerAsks, signatures, merkleTrees, - _EMPTY_AFFILIATE, false // Non-atomic ); } function testCannotTradeIfETHIsUsedForMakerBid() public { - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - ETH - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), ETH); // Sign order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -158,27 +143,24 @@ contract LooksRareProtocolTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); vm.expectRevert(CurrencyInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testCannotTradeIfInvalidQuoteType() public { // 1. QuoteType = BID but executeTakerBid - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); // Sign order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); vm.prank(takerUser); vm.expectRevert(QuoteTypeInvalid.selector); - looksRareProtocol.executeTakerBid(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // 2. QuoteType = ASK but executeTakerAsk - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); makerAsk.currency = address(weth); // Sign order @@ -186,7 +168,7 @@ contract LooksRareProtocolTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(QuoteTypeInvalid.selector); - looksRareProtocol.executeTakerAsk(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testUpdateETHGasLimitForTransfer() public asPrankedUser(_owner) { @@ -197,7 +179,7 @@ contract LooksRareProtocolTest is ProtocolBase { } function testUpdateETHGasLimitForTransferRevertsIfTooLow() public asPrankedUser(_owner) { - uint256 newGasLimitETHTransfer = 2_300; + uint256 newGasLimitETHTransfer = 2300; vm.expectRevert(NewGasLimitETHTransferTooLow.selector); looksRareProtocol.updateETHGasLimitForTransfer(newGasLimitETHTransfer - 1); @@ -213,9 +195,8 @@ contract LooksRareProtocolTest is ProtocolBase { function testCannotCallRestrictedExecuteTakerBid() public { _setUpUsers(); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); // Mint asset mockERC721.mint(makerUser, makerAsk.itemIds[0]); @@ -280,13 +261,8 @@ contract LooksRareProtocolTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(CurrencyInvalid.selector); - looksRareProtocol.executeMultipleTakerBids{ value: price }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - isAtomic + looksRareProtocol.executeMultipleTakerBids{value: price}( + takerBids, makerAsks, signatures, merkleTrees, isAtomic ); } } diff --git a/contracts/test/foundry/marketplace/NonceInvalidation.t.sol b/contracts/test/foundry/marketplace/NonceInvalidation.t.sol index 594ec13a..ae497f79 100644 --- a/contracts/test/foundry/marketplace/NonceInvalidation.t.sol +++ b/contracts/test/foundry/marketplace/NonceInvalidation.t.sol @@ -2,18 +2,24 @@ pragma solidity 0.8.17; // Libraries, interfaces, errors -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { INonceManager } from "@hypercerts/marketplace/interfaces/INonceManager.sol"; -import { LengthsInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; -import { INVALID_USER_GLOBAL_BID_NONCE, INVALID_USER_GLOBAL_ASK_NONCE, USER_SUBSET_NONCE_CANCELLED, USER_ORDER_NONCE_IN_EXECUTION_WITH_OTHER_HASH, USER_ORDER_NONCE_EXECUTED_OR_CANCELLED } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {INonceManager} from "@hypercerts/marketplace/interfaces/INonceManager.sol"; +import {LengthsInvalid} from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { + INVALID_USER_GLOBAL_BID_NONCE, + INVALID_USER_GLOBAL_ASK_NONCE, + USER_SUBSET_NONCE_CANCELLED, + USER_ORDER_NONCE_IN_EXECUTION_WITH_OTHER_HASH, + USER_ORDER_NONCE_EXECUTED_OR_CANCELLED +} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Other utils and tests -import { StrategyTestMultiFillCollectionOrder } from "./utils/StrategyTestMultiFillCollectionOrder.sol"; -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {StrategyTestMultiFillCollectionOrder} from "./utils/StrategyTestMultiFillCollectionOrder.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract NonceInvalidationTest is INonceManager, ProtocolBase { uint256 private constant price = 1 ether; // Fixed price of sale @@ -31,9 +37,8 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { // Mint asset mockERC721.mint(makerUser, itemId); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); makerAsk.subsetNonce = subsetNonce; // Sign order @@ -55,20 +60,14 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { // Taker user actions vm.prank(takerUser); vm.expectRevert(NoncesInvalid.selector); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } /** * Cannot execute an order if maker is at a different global ask nonce than signed */ function testCannotExecuteOrderIfInvalidUserGlobalAskNonce(uint256 userGlobalAskNonce) public { - uint256 quasiRandomNumber = 54570651553685478358117286254199992264; + uint256 quasiRandomNumber = 54_570_651_553_685_478_358_117_286_254_199_992_264; vm.assume(userGlobalAskNonce < quasiRandomNumber); // Change block number vm.roll(1); @@ -81,9 +80,8 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { emit NewBidAskNonces(makerUser, 0, newAskNonce); looksRareProtocol.incrementBidAskNonces(false, true); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); // Mint asset mockERC721.mint(makerUser, makerAsk.itemIds[0]); @@ -99,20 +97,14 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { // Taker user actions vm.prank(takerUser); vm.expectRevert(NoncesInvalid.selector); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } /** * Cannot execute an order if maker is at a different global bid nonce than signed */ function testCannotExecuteOrderIfInvalidUserGlobalBidNonce(uint256 userGlobalBidNonce) public { - uint256 quasiRandomNumber = 54570651553685478358117286254199992264; + uint256 quasiRandomNumber = 54_570_651_553_685_478_358_117_286_254_199_992_264; vm.assume(userGlobalBidNonce < quasiRandomNumber); // Change block number vm.roll(1); @@ -153,13 +145,7 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { // Taker user actions vm.prank(takerUser); vm.expectRevert(NoncesInvalid.selector); - looksRareProtocol.executeTakerAsk( - _genericTakerOrder(), - makerBid, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerAsk(_genericTakerOrder(), makerBid, signature, _EMPTY_MERKLE_TREE); } /** @@ -169,10 +155,8 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { _setUpUsers(); _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); // Sign order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -184,13 +168,13 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { vm.startPrank(takerUser); { - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); _assertMakerOrderReturnValidationCode(makerBid, signature, USER_ORDER_NONCE_EXECUTED_OR_CANCELLED); // Second one fails vm.expectRevert(NoncesInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } vm.stopPrank(); @@ -205,7 +189,8 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { // 0. Add the new strategy bytes4 selector = StrategyTestMultiFillCollectionOrder.executeStrategyWithTakerAsk.selector; - StrategyTestMultiFillCollectionOrder strategyMultiFillCollectionOrder = new StrategyTestMultiFillCollectionOrder( + StrategyTestMultiFillCollectionOrder strategyMultiFillCollectionOrder = + new StrategyTestMultiFillCollectionOrder( address(looksRareProtocol) ); @@ -253,7 +238,7 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { vm.prank(takerUser); // Execute taker ask transaction - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } // 2. Second maker order is signed sharing the same order nonce as the first one @@ -287,16 +272,14 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { _assertMakerOrderReturnValidationCode(makerBid, signature, USER_ORDER_NONCE_IN_EXECUTION_WITH_OTHER_HASH); // Prepare the taker ask - OrderStructs.Taker memory takerAsk = OrderStructs.Taker( - takerUser, - abi.encode(new uint256[](0), new uint256[](0)) - ); + OrderStructs.Taker memory takerAsk = + OrderStructs.Taker(takerUser, abi.encode(new uint256[](0), new uint256[](0))); vm.prank(takerUser); // Second one fails when a taker user tries to execute vm.expectRevert(NoncesInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } } @@ -352,14 +335,12 @@ contract NonceInvalidationTest is INonceManager, ProtocolBase { mockERC721.mint(takerUser, itemId); // Prepare the taker ask - OrderStructs.Taker memory takerAsk = OrderStructs.Taker( - takerUser, - abi.encode(new uint256[](0), new uint256[](0)) - ); + OrderStructs.Taker memory takerAsk = + OrderStructs.Taker(takerUser, abi.encode(new uint256[](0), new uint256[](0))); vm.prank(takerUser); vm.expectRevert(NoncesInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testCancelNoncesRevertIfEmptyArrays() public { diff --git a/contracts/test/foundry/marketplace/OrderValidatorV2A.t.sol b/contracts/test/foundry/marketplace/OrderValidatorV2A.t.sol index 604c9006..ca9a5c9c 100644 --- a/contracts/test/foundry/marketplace/OrderValidatorV2A.t.sol +++ b/contracts/test/foundry/marketplace/OrderValidatorV2A.t.sol @@ -1,35 +1,49 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { LooksRareProtocol } from "@hypercerts/marketplace/LooksRareProtocol.sol"; -import { TransferManager } from "@hypercerts/marketplace/TransferManager.sol"; -import { CreatorFeeManagerWithRoyalties } from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; +import {LooksRareProtocol} from "@hypercerts/marketplace/LooksRareProtocol.sol"; +import {TransferManager} from "@hypercerts/marketplace/TransferManager.sol"; +import {CreatorFeeManagerWithRoyalties} from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; -import { OrderValidatorV2A } from "@hypercerts/marketplace/helpers/OrderValidatorV2A.sol"; +import {OrderValidatorV2A} from "@hypercerts/marketplace/helpers/OrderValidatorV2A.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Shared errors -import { ERC20_APPROVAL_INFERIOR_TO_PRICE, ERC721_ITEM_ID_NOT_IN_BALANCE, ERC721_NO_APPROVAL_FOR_ALL_OR_ITEM_ID, ERC1155_BALANCE_OF_DOES_NOT_EXIST, ERC1155_BALANCE_OF_ITEM_ID_INFERIOR_TO_AMOUNT, ERC1155_IS_APPROVED_FOR_ALL_DOES_NOT_EXIST, ERC1155_NO_APPROVAL_FOR_ALL, MAKER_ORDER_INVALID_STANDARD_SALE, MISSING_IS_VALID_SIGNATURE_FUNCTION_EIP1271, POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC721, POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC1155, STRATEGY_NOT_IMPLEMENTED, TRANSFER_MANAGER_APPROVAL_REVOKED_BY_OWNER_FOR_EXCHANGE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import { + ERC20_APPROVAL_INFERIOR_TO_PRICE, + ERC721_ITEM_ID_NOT_IN_BALANCE, + ERC721_NO_APPROVAL_FOR_ALL_OR_ITEM_ID, + ERC1155_BALANCE_OF_DOES_NOT_EXIST, + ERC1155_BALANCE_OF_ITEM_ID_INFERIOR_TO_AMOUNT, + ERC1155_IS_APPROVED_FOR_ALL_DOES_NOT_EXIST, + ERC1155_NO_APPROVAL_FOR_ALL, + MAKER_ORDER_INVALID_STANDARD_SALE, + MISSING_IS_VALID_SIGNATURE_FUNCTION_EIP1271, + POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC721, + POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC1155, + STRATEGY_NOT_IMPLEMENTED, + TRANSFER_MANAGER_APPROVAL_REVOKED_BY_OWNER_FOR_EXCHANGE +} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Utils -import { TestParameters } from "./utils/TestParameters.sol"; +import {TestParameters} from "./utils/TestParameters.sol"; // Mocks -import { MockRoyaltyFeeRegistry } from "../../mock/MockRoyaltyFeeRegistry.sol"; -import { MockERC721 } from "../../mock/MockERC721.sol"; -import { MockERC1155 } from "../../mock/MockERC1155.sol"; -import { MockERC1155WithoutBalanceOfBatch } from "../../mock/MockERC1155WithoutBalanceOfBatch.sol"; -import { MockERC1155WithoutAnyBalanceOf } from "../../mock/MockERC1155WithoutAnyBalanceOf.sol"; -import { MockERC1155WithoutIsApprovedForAll } from "../../mock/MockERC1155WithoutIsApprovedForAll.sol"; -import { MockERC721SupportsNoInterface } from "../../mock/MockERC721SupportsNoInterface.sol"; -import { MockERC1155SupportsNoInterface } from "../../mock/MockERC1155SupportsNoInterface.sol"; -import { MockERC20 } from "../../mock/MockERC20.sol"; +import {MockRoyaltyFeeRegistry} from "../../mock/MockRoyaltyFeeRegistry.sol"; +import {MockERC721} from "../../mock/MockERC721.sol"; +import {MockERC1155} from "../../mock/MockERC1155.sol"; +import {MockERC1155WithoutBalanceOfBatch} from "../../mock/MockERC1155WithoutBalanceOfBatch.sol"; +import {MockERC1155WithoutAnyBalanceOf} from "../../mock/MockERC1155WithoutAnyBalanceOf.sol"; +import {MockERC1155WithoutIsApprovedForAll} from "../../mock/MockERC1155WithoutIsApprovedForAll.sol"; +import {MockERC721SupportsNoInterface} from "../../mock/MockERC721SupportsNoInterface.sol"; +import {MockERC1155SupportsNoInterface} from "../../mock/MockERC1155SupportsNoInterface.sol"; +import {MockERC20} from "../../mock/MockERC20.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; /** * @dev Not everything is tested in this file. Most tests live in other files @@ -73,18 +87,15 @@ contract OrderValidatorV2ATest is TestParameters { ); assertEq(address(orderValidator.creatorFeeManager()), address(creatorFeeManager)); - assertEq(orderValidator.maxCreatorFeeBp(), 1_000); + assertEq(orderValidator.maxCreatorFeeBp(), 1000); } function testMakerAskStrategyNotImplemented() public { OrderStructs.Maker memory makerAsk; makerAsk.quoteType = QuoteType.Ask; makerAsk.strategyId = 1; - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerAsk, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerAsk, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[0], STRATEGY_NOT_IMPLEMENTED); } @@ -95,11 +106,8 @@ contract OrderValidatorV2ATest is TestParameters { looksRareProtocol.updateCurrencyStatus(currency, true); makerBid.currency = currency; makerBid.strategyId = 1; - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerBid, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerBid, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[0], STRATEGY_NOT_IMPLEMENTED); } @@ -120,11 +128,8 @@ contract OrderValidatorV2ATest is TestParameters { transferManager.removeOperator(operators[0]); - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerAsk, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerAsk, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[7], TRANSFER_MANAGER_APPROVAL_REVOKED_BY_OWNER_FOR_EXCHANGE); } @@ -133,11 +138,8 @@ contract OrderValidatorV2ATest is TestParameters { makerAsk.quoteType = QuoteType.Ask; makerAsk.collectionType = CollectionType.ERC721; makerAsk.collection = address(new MockERC721SupportsNoInterface()); - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerAsk, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerAsk, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[6], POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC721); } @@ -146,11 +148,8 @@ contract OrderValidatorV2ATest is TestParameters { makerBid.quoteType = QuoteType.Bid; makerBid.collectionType = CollectionType.ERC721; makerBid.collection = address(new MockERC721SupportsNoInterface()); - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerBid, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerBid, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[6], POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC721); } @@ -173,11 +172,8 @@ contract OrderValidatorV2ATest is TestParameters { uint256[] memory amounts = new uint256[](1); amounts[0] = amount; makerBid.amounts = amounts; - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerBid, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerBid, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[1], MAKER_ORDER_INVALID_STANDARD_SALE); } @@ -188,11 +184,8 @@ contract OrderValidatorV2ATest is TestParameters { makerBid.signer = address(this); makerBid.collectionType = CollectionType.ERC721; makerBid.collection = address(new MockERC721()); - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerBid, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerBid, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[3], MISSING_IS_VALID_SIGNATURE_FUNCTION_EIP1271); } @@ -200,11 +193,8 @@ contract OrderValidatorV2ATest is TestParameters { OrderStructs.Maker memory makerAsk; makerAsk.collectionType = CollectionType.ERC1155; makerAsk.collection = address(new MockERC1155SupportsNoInterface()); - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerAsk, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerAsk, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[6], POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC1155); } @@ -213,11 +203,8 @@ contract OrderValidatorV2ATest is TestParameters { makerBid.quoteType = QuoteType.Bid; makerBid.collectionType = CollectionType.ERC1155; makerBid.collection = address(new MockERC1155SupportsNoInterface()); - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerBid, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerBid, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[6], POTENTIAL_INVALID_COLLECTION_TYPE_SHOULD_BE_ERC1155); } @@ -238,11 +225,8 @@ contract OrderValidatorV2ATest is TestParameters { mockERC20.approve(address(orderValidator.looksRareProtocol()), makerBid.price - 1 wei); vm.stopPrank(); - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerBid, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerBid, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[5], ERC20_APPROVAL_INFERIOR_TO_PRICE); } @@ -272,11 +256,8 @@ contract OrderValidatorV2ATest is TestParameters { amounts[1] = 1; makerAsk.amounts = amounts; - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerAsk, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerAsk, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[5], ERC721_NO_APPROVAL_FOR_ALL_OR_ITEM_ID); } @@ -292,11 +273,8 @@ contract OrderValidatorV2ATest is TestParameters { uint256[] memory itemIds = new uint256[](1); makerAsk.itemIds = itemIds; - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerAsk, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerAsk, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[5], ERC721_ITEM_ID_NOT_IN_BALANCE); } @@ -331,11 +309,8 @@ contract OrderValidatorV2ATest is TestParameters { amounts[0] = 1; makerAsk.amounts = amounts; - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerAsk, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerAsk, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[5], ERC1155_BALANCE_OF_ITEM_ID_INFERIOR_TO_AMOUNT); } @@ -354,17 +329,14 @@ contract OrderValidatorV2ATest is TestParameters { amounts[0] = 1; makerAsk.amounts = amounts; - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerAsk, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerAsk, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[5], ERC1155_BALANCE_OF_DOES_NOT_EXIST); } function testMakerAskERC1155IsApprovedForAllDoesNotExist() public { MockERC1155WithoutIsApprovedForAll mockERC1155 = new MockERC1155WithoutIsApprovedForAll(); - mockERC1155.mint({ to: makerUser, tokenId: 0, amount: 1 }); + mockERC1155.mint({to: makerUser, tokenId: 0, amount: 1}); OrderStructs.Maker memory makerAsk; makerAsk.quoteType = QuoteType.Ask; @@ -378,17 +350,14 @@ contract OrderValidatorV2ATest is TestParameters { amounts[0] = 1; makerAsk.amounts = amounts; - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerAsk, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerAsk, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[5], ERC1155_IS_APPROVED_FOR_ALL_DOES_NOT_EXIST); } function testMakerAskERC1155IsApprovedForAllReturnsFalse() public { MockERC1155 mockERC1155 = new MockERC1155(); - mockERC1155.mint({ to: makerUser, tokenId: 0, amount: 1 }); + mockERC1155.mint({to: makerUser, tokenId: 0, amount: 1}); OrderStructs.Maker memory makerAsk; makerAsk.quoteType = QuoteType.Ask; @@ -402,11 +371,8 @@ contract OrderValidatorV2ATest is TestParameters { amounts[0] = 1; makerAsk.amounts = amounts; - uint256[9] memory validationCodes = orderValidator.checkMakerOrderValidity( - makerAsk, - new bytes(65), - _EMPTY_MERKLE_TREE - ); + uint256[9] memory validationCodes = + orderValidator.checkMakerOrderValidity(makerAsk, new bytes(65), _EMPTY_MERKLE_TREE); assertEq(validationCodes[5], ERC1155_NO_APPROVAL_FOR_ALL); } } diff --git a/contracts/test/foundry/marketplace/ProtocolBase.t.sol b/contracts/test/foundry/marketplace/ProtocolBase.t.sol index 92b090fd..8c3cee4b 100644 --- a/contracts/test/foundry/marketplace/ProtocolBase.t.sol +++ b/contracts/test/foundry/marketplace/ProtocolBase.t.sol @@ -2,28 +2,28 @@ pragma solidity >=0.8.7; // WETH -import { WETH } from "solmate/src/tokens/WETH.sol"; +import {WETH} from "solmate/src/tokens/WETH.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Core contracts -import { LooksRareProtocol, ILooksRareProtocol } from "@hypercerts/marketplace/LooksRareProtocol.sol"; -import { TransferManager } from "@hypercerts/marketplace/TransferManager.sol"; -import { ProtocolFeeRecipient } from "@hypercerts/marketplace/ProtocolFeeRecipient.sol"; +import {LooksRareProtocol, ILooksRareProtocol} from "@hypercerts/marketplace/LooksRareProtocol.sol"; +import {TransferManager} from "@hypercerts/marketplace/TransferManager.sol"; +import {ProtocolFeeRecipient} from "@hypercerts/marketplace/ProtocolFeeRecipient.sol"; // Other contracts -import { OrderValidatorV2A } from "@hypercerts/marketplace/helpers/OrderValidatorV2A.sol"; +import {OrderValidatorV2A} from "@hypercerts/marketplace/helpers/OrderValidatorV2A.sol"; // Mock files -import { MockERC20 } from "../../mock/MockERC20.sol"; -import { MockERC721 } from "../../mock/MockERC721.sol"; -import { MockERC721WithRoyalties } from "../../mock/MockERC721WithRoyalties.sol"; -import { MockERC1155 } from "../../mock/MockERC1155.sol"; -import { MockRoyaltyFeeRegistry } from "../../mock/MockRoyaltyFeeRegistry.sol"; +import {MockERC20} from "../../mock/MockERC20.sol"; +import {MockERC721} from "../../mock/MockERC721.sol"; +import {MockERC721WithRoyalties} from "../../mock/MockERC721WithRoyalties.sol"; +import {MockERC1155} from "../../mock/MockERC1155.sol"; +import {MockRoyaltyFeeRegistry} from "../../mock/MockRoyaltyFeeRegistry.sol"; // Utils -import { MockOrderGenerator } from "./utils/MockOrderGenerator.sol"; +import {MockOrderGenerator} from "./utils/MockOrderGenerator.sol"; contract ProtocolBase is MockOrderGenerator, ILooksRareProtocol { address[] public operators; @@ -73,11 +73,8 @@ contract ProtocolBase is MockOrderGenerator, ILooksRareProtocol { OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](1); merkleTrees[0] = merkleTree; - uint256[9][] memory validationCodes = orderValidator.checkMultipleMakerOrderValidities( - makerOrders, - signatures, - merkleTrees - ); + uint256[9][] memory validationCodes = + orderValidator.checkMultipleMakerOrderValidities(makerOrders, signatures, merkleTrees); uint256 index = expectedValidationCode / 100; assertEq(validationCodes[0][index - 1], expectedValidationCode); @@ -109,11 +106,8 @@ contract ProtocolBase is MockOrderGenerator, ILooksRareProtocol { OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](1); merkleTrees[0] = merkleTree; - uint256[9][] memory validationCodes = orderValidator.checkMultipleMakerOrderValidities( - makerOrders, - signatures, - merkleTrees - ); + uint256[9][] memory validationCodes = + orderValidator.checkMultipleMakerOrderValidities(makerOrders, signatures, merkleTrees); _assertValidationCodesAllZeroes(validationCodes); } @@ -138,7 +132,7 @@ contract ProtocolBase is MockOrderGenerator, ILooksRareProtocol { // Receive ETH and WETH vm.deal(user, _initialETHBalanceUser + _initialWETHBalanceUser); - weth.deposit{ value: _initialWETHBalanceUser }(); + weth.deposit{value: _initialWETHBalanceUser}(); } function _setUpUsers() internal { @@ -149,10 +143,7 @@ contract ProtocolBase is MockOrderGenerator, ILooksRareProtocol { function _setupRegistryRoyalties(address collection, uint256 standardRoyaltyFee) internal { vm.prank(royaltyFeeRegistry.owner()); royaltyFeeRegistry.updateRoyaltyInfoForCollection( - collection, - _royaltyRecipient, - _royaltyRecipient, - standardRoyaltyFee + collection, _royaltyRecipient, _royaltyRecipient, standardRoyaltyFee ); } @@ -188,13 +179,13 @@ contract ProtocolBase is MockOrderGenerator, ILooksRareProtocol { // Distribute ETH and WETH to protocol owner vm.deal(_owner, _initialETHBalanceOwner + _initialWETHBalanceOwner); - weth.deposit{ value: _initialWETHBalanceOwner }(); + weth.deposit{value: _initialWETHBalanceOwner}(); vm.stopPrank(); // Distribute ETH and WETH to royalty recipient vm.deal(_royaltyRecipient, _initialETHBalanceRoyaltyRecipient + _initialWETHBalanceRoyaltyRecipient); vm.startPrank(_royaltyRecipient); - weth.deposit{ value: _initialWETHBalanceRoyaltyRecipient }(); + weth.deposit{value: _initialWETHBalanceRoyaltyRecipient}(); vm.stopPrank(); } @@ -204,12 +195,7 @@ contract ProtocolBase is MockOrderGenerator, ILooksRareProtocol { function _addStrategy(address strategy, bytes4 selector, bool isMakerBid) internal { looksRareProtocol.addStrategy( - _standardProtocolFeeBp, - _minTotalFeeBp, - _maxProtocolFeeBp, - selector, - isMakerBid, - strategy + _standardProtocolFeeBp, _minTotalFeeBp, _maxProtocolFeeBp, selector, isMakerBid, strategy ); } @@ -251,16 +237,14 @@ contract ProtocolBase is MockOrderGenerator, ILooksRareProtocol { OrderStructs.Taker calldata takerAsk, OrderStructs.Maker calldata makerBid, bytes calldata makerSignature, - OrderStructs.MerkleTree calldata merkleTree, - address affiliate + OrderStructs.MerkleTree calldata merkleTree ) external {} function executeTakerBid( OrderStructs.Taker calldata takerBid, OrderStructs.Maker calldata makerAsk, bytes calldata makerSignature, - OrderStructs.MerkleTree calldata merkleTree, - address affiliate + OrderStructs.MerkleTree calldata merkleTree ) external payable {} function executeMultipleTakerBids( @@ -268,7 +252,6 @@ contract ProtocolBase is MockOrderGenerator, ILooksRareProtocol { OrderStructs.Maker[] calldata makerAsks, bytes[] calldata makerSignatures, OrderStructs.MerkleTree[] calldata merkleTrees, - address affiliate, bool isAtomic ) external payable {} } diff --git a/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol b/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol index 36f370df..a161feaf 100644 --- a/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol +++ b/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol @@ -2,15 +2,15 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IERC20 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC20.sol"; -import { IWETH } from "@looksrare/contracts-libs/contracts/interfaces/generic/IWETH.sol"; +import {IERC20} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC20.sol"; +import {IWETH} from "@looksrare/contracts-libs/contracts/interfaces/generic/IWETH.sol"; // Core contracts -import { ProtocolFeeRecipient } from "@hypercerts/marketplace/ProtocolFeeRecipient.sol"; +import {ProtocolFeeRecipient} from "@hypercerts/marketplace/ProtocolFeeRecipient.sol"; // Other mocks and utils -import { MockERC20 } from "../../mock/MockERC20.sol"; -import { TestParameters } from "./utils/TestParameters.sol"; +import {MockERC20} from "../../mock/MockERC20.sol"; +import {TestParameters} from "./utils/TestParameters.sol"; contract ProtocolFeeRecipientTest is TestParameters { ProtocolFeeRecipient private protocolFeeRecipient; @@ -47,8 +47,7 @@ contract ProtocolFeeRecipientTest is TestParameters { assertEq(address(protocolFeeRecipient).balance, 0); assertEq(IERC20(WETH_MAINNET).balanceOf(address(protocolFeeRecipient)), 0); assertEq( - IERC20(WETH_MAINNET).balanceOf(FEE_SHARING_SETTER), - feeSharingSetterInitialWETHBalance + 1 ether + DUST + IERC20(WETH_MAINNET).balanceOf(FEE_SHARING_SETTER), feeSharingSetterInitialWETHBalance + 1 ether + DUST ); } @@ -98,13 +97,13 @@ contract ProtocolFeeRecipientTest is TestParameters { } function _sendETHToProtocolFeeRecipient() private { - (bool success, ) = address(protocolFeeRecipient).call{ value: 1 ether }(""); + (bool success,) = address(protocolFeeRecipient).call{value: 1 ether}(""); assertTrue(success); assertEq(address(protocolFeeRecipient).balance, 1 ether); } function _sendWETHToProtocolFeeRecipient() private { - IWETH(WETH_MAINNET).deposit{ value: DUST }(); + IWETH(WETH_MAINNET).deposit{value: DUST}(); IERC20(WETH_MAINNET).transfer(address(protocolFeeRecipient), DUST); assertEq(IERC20(WETH_MAINNET).balanceOf(address(protocolFeeRecipient)), DUST); } diff --git a/contracts/test/foundry/marketplace/Sandbox.t.sol b/contracts/test/foundry/marketplace/Sandbox.t.sol index 6e2a3e36..9a349fd5 100644 --- a/contracts/test/foundry/marketplace/Sandbox.t.sol +++ b/contracts/test/foundry/marketplace/Sandbox.t.sol @@ -2,18 +2,18 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IERC721 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC721.sol"; -import { IERC1155 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC1155.sol"; +import {IERC721} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC721.sol"; +import {IERC1155} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC1155.sol"; // Libraries and interfaces -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract SandboxTest is ProtocolBase { error ERC721TransferFromFail(); @@ -25,12 +25,12 @@ contract SandboxTest is ProtocolBase { address private constant SANDBOX = 0xa342f5D851E866E18ff98F351f2c6637f4478dB5; // Forked block number to run the tests - uint256 private constant FORKED_BLOCK_NUMBER = 16268000; + uint256 private constant FORKED_BLOCK_NUMBER = 16_268_000; function _transferItemIdToUser(address user) private returns (uint256 itemId) { // @dev This user had 23 of the itemId at the forked block number address ownerOfItemId = 0x7A9fe22691c811ea339D9B73150e6911a5343DcA; - itemId = 55464657044963196816950587289035428064568320970692304673817341489688428423171; + itemId = 55_464_657_044_963_196_816_950_587_289_035_428_064_568_320_970_692_304_673_817_341_489_688_428_423_171; vm.prank(ownerOfItemId); IERC1155(SANDBOX).safeTransferFrom(ownerOfItemId, user, itemId, 23, ""); } @@ -79,7 +79,7 @@ contract SandboxTest is ProtocolBase { // It should fail with collectionType = 0 vm.expectRevert(abi.encodeWithSelector(ERC721TransferFromFail.selector)); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // Adjust the collection type and sign order again makerBid.collectionType = CollectionType.ERC1155; @@ -87,7 +87,7 @@ contract SandboxTest is ProtocolBase { // It shouldn't fail with collectionType = 0 vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // Maker user has received the Sandbox asset assertEq(IERC1155(SANDBOX).balanceOf(makerUser, itemId), makerBid.amounts[0]); @@ -126,13 +126,7 @@ contract SandboxTest is ProtocolBase { // It should fail with collectionType = 0 vm.expectRevert(abi.encodeWithSelector(ERC721TransferFromFail.selector)); vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // Adjust the collection type and sign order again makerAsk.collectionType = CollectionType.ERC1155; @@ -140,13 +134,7 @@ contract SandboxTest is ProtocolBase { // It shouldn't fail with collectionType = 0 vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // Taker user has received the Sandbox asset assertEq(IERC1155(SANDBOX).balanceOf(takerUser, itemId), makerAsk.amounts[0]); diff --git a/contracts/test/foundry/marketplace/SignaturesEIP2098.t.sol b/contracts/test/foundry/marketplace/SignaturesEIP2098.t.sol index 9a480b0f..ea02561a 100644 --- a/contracts/test/foundry/marketplace/SignaturesEIP2098.t.sol +++ b/contracts/test/foundry/marketplace/SignaturesEIP2098.t.sol @@ -3,17 +3,17 @@ pragma solidity 0.8.17; // Libraries, interfaces, errors import "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract SignaturesEIP2098Test is ProtocolBase { function setUp() public { @@ -26,7 +26,7 @@ contract SignaturesEIP2098Test is ProtocolBase { _setUpUsers(); _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); - (OrderStructs.Maker memory makerAsk, ) = _createMockMakerAskAndTakerBid(address(mockERC721)); + (OrderStructs.Maker memory makerAsk,) = _createMockMakerAskAndTakerBid(address(mockERC721)); makerAsk.price = price; makerAsk.itemIds[0] = itemId; @@ -48,7 +48,7 @@ contract SignaturesEIP2098Test is ProtocolBase { _setUpUsers(); _setupRegistryRoyalties(address(mockERC721), _standardRoyaltyFee); - (OrderStructs.Maker memory makerBid, ) = _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); + (OrderStructs.Maker memory makerBid,) = _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); makerBid.price = price; makerBid.itemIds[0] = itemId; diff --git a/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC1155.t.sol b/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC1155.t.sol index 60ef310b..2a96743c 100644 --- a/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC1155.t.sol +++ b/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC1155.t.sol @@ -2,27 +2,31 @@ pragma solidity 0.8.17; // Libraries and interfaces -import { IReentrancyGuard } from "@looksrare/contracts-libs/contracts/interfaces/IReentrancyGuard.sol"; -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {IReentrancyGuard} from "@looksrare/contracts-libs/contracts/interfaces/IReentrancyGuard.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Mocks and other utils -import { ERC1271Wallet } from "./utils/ERC1271Wallet.sol"; -import { MaliciousERC1271Wallet } from "./utils/MaliciousERC1271Wallet.sol"; -import { MaliciousOnERC1155ReceivedERC1271Wallet } from "./utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol"; -import { MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet } from "./utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol"; -import { MaliciousIsValidSignatureERC1271Wallet } from "./utils/MaliciousIsValidSignatureERC1271Wallet.sol"; +import {ERC1271Wallet} from "./utils/ERC1271Wallet.sol"; +import {MaliciousERC1271Wallet} from "./utils/MaliciousERC1271Wallet.sol"; +import {MaliciousOnERC1155ReceivedERC1271Wallet} from "./utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol"; +import {MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet} from + "./utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol"; +import {MaliciousIsValidSignatureERC1271Wallet} from "./utils/MaliciousIsValidSignatureERC1271Wallet.sol"; // Errors -import { SignatureERC1271Invalid } from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; -import { ERC1155SafeTransferFromFail, ERC1155SafeBatchTransferFromFail } from "@looksrare/contracts-libs/contracts/errors/LowLevelErrors.sol"; -import { SIGNATURE_INVALID_EIP1271 } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import {SignatureERC1271Invalid} from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; +import { + ERC1155SafeTransferFromFail, + ERC1155SafeBatchTransferFromFail +} from "@looksrare/contracts-libs/contracts/errors/LowLevelErrors.sol"; +import {SIGNATURE_INVALID_EIP1271} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; /** * @dev ERC1271Wallet recovers a signature's signer using ECDSA. If it matches the mock wallet's @@ -53,13 +57,7 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { _assertValidMakerOrder(makerAsk, signature); vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); assertEq(mockERC1155.balanceOf(takerUser, itemId), 1); } @@ -80,13 +78,7 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { vm.expectRevert(SignatureERC1271Invalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testTakerBidIsInvalidSignatureReentrancy() public { @@ -96,19 +88,12 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { _setUpUser(address(maliciousERC1271Wallet)); maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerBid); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _takerBidSetup( - address(maliciousERC1271Wallet) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _takerBidSetup(address(maliciousERC1271Wallet)); vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - _EMPTY_SIGNATURE, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE); } function testTakerAsk() public { @@ -125,7 +110,7 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { _assertValidMakerOrder(makerBid, signature); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); assertEq(mockERC1155.balanceOf(address(wallet), itemId), 1); } @@ -146,7 +131,7 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { vm.expectRevert(SignatureERC1271Invalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testTakerAskIsValidSignatureReentrancy() public { @@ -156,13 +141,12 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { _setUpUser(address(maliciousERC1271Wallet)); maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerAsk); - (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _takerAskSetup( - address(maliciousERC1271Wallet) - ); + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = + _takerAskSetup(address(maliciousERC1271Wallet)); vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE); } function testTakerAskOnERC1155ReceivedReentrancy() public { @@ -171,15 +155,14 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { ); _setUpUser(address(maliciousERC1271Wallet)); - (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _takerAskSetup( - address(maliciousERC1271Wallet) - ); + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = + _takerAskSetup(address(maliciousERC1271Wallet)); maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerAsk); vm.expectRevert(ERC1155SafeTransferFromFail.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE); } function testBatchTakerAsk() public { @@ -194,7 +177,7 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { weth.approve(address(looksRareProtocol), price); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); for (uint256 i; i < 10; i++) { assertEq(mockERC1155.balanceOf(address(wallet), i), 1); @@ -207,9 +190,8 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { ); _setUpUser(address(maliciousERC1271Wallet)); - (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _batchTakerAskSetup( - address(maliciousERC1271Wallet) - ); + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = + _batchTakerAskSetup(address(maliciousERC1271Wallet)); bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -222,7 +204,7 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { vm.expectRevert(ERC1155SafeBatchTransferFromFail.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } uint256 private constant numberOfPurchases = 3; @@ -243,13 +225,8 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { vm.stopPrank(); vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberOfPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberOfPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); for (uint256 i; i < numberOfPurchases; i++) { @@ -279,13 +256,8 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { vm.expectRevert(SignatureERC1271Invalid.selector); vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberOfPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberOfPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); } @@ -305,13 +277,8 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberOfPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberOfPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); for (uint256 i; i < numberOfPurchases - 1; i++) { @@ -320,7 +287,8 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { } function testExecuteMultipleTakerBidsOnERC1155ReceivedReentrancyOnlyInTheLastCall() public { - MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet maliciousERC1271Wallet = new MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet( + MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet maliciousERC1271Wallet = + new MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet( takerUser ); _setUpUser(makerUser); @@ -339,13 +307,8 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { } vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberOfPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberOfPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); // First 2 purchases should go through, but the last one fails silently @@ -355,9 +318,10 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { assertEq(mockERC1155.balanceOf(address(maliciousERC1271Wallet), numberOfPurchases - 1), 0); } - function _takerBidSetup( - address signer - ) private returns (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) { + function _takerBidSetup(address signer) + private + returns (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) + { // Mint asset mockERC1155.mint(signer, itemId, 1); @@ -379,9 +343,10 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { takerBid = _genericTakerOrder(); } - function _takerAskSetup( - address signer - ) private returns (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) { + function _takerAskSetup(address signer) + private + returns (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) + { makerBid = _createSingleItemMakerOrder({ quoteType: QuoteType.Bid, globalNonce: 0, @@ -403,9 +368,10 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { takerAsk = _genericTakerOrder(); } - function _batchTakerAskSetup( - address signer - ) private returns (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) { + function _batchTakerAskSetup(address signer) + private + returns (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) + { uint256[] memory itemIds = new uint256[](10); uint256[] memory amounts = new uint256[](10); @@ -437,9 +403,7 @@ contract SignaturesERC1271WalletForERC1155Test is ProtocolBase { takerAsk = _genericTakerOrder(); } - function _multipleTakerBidsSetup( - address signer - ) + function _multipleTakerBidsSetup(address signer) private returns ( OrderStructs.Maker[] memory makerAsks, diff --git a/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC721.t.sol b/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC721.t.sol index 61df2186..638c416e 100644 --- a/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC721.t.sol +++ b/contracts/test/foundry/marketplace/SignaturesERC1271WalletForERC721.t.sol @@ -2,24 +2,24 @@ pragma solidity 0.8.17; // Libraries and interfaces -import { IReentrancyGuard } from "@looksrare/contracts-libs/contracts/interfaces/IReentrancyGuard.sol"; -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {IReentrancyGuard} from "@looksrare/contracts-libs/contracts/interfaces/IReentrancyGuard.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Mocks and other utils -import { ERC1271Wallet } from "./utils/ERC1271Wallet.sol"; -import { MaliciousERC1271Wallet } from "./utils/MaliciousERC1271Wallet.sol"; -import { MaliciousIsValidSignatureERC1271Wallet } from "./utils/MaliciousIsValidSignatureERC1271Wallet.sol"; +import {ERC1271Wallet} from "./utils/ERC1271Wallet.sol"; +import {MaliciousERC1271Wallet} from "./utils/MaliciousERC1271Wallet.sol"; +import {MaliciousIsValidSignatureERC1271Wallet} from "./utils/MaliciousIsValidSignatureERC1271Wallet.sol"; // Errors -import { SignatureERC1271Invalid } from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; -import { SIGNATURE_INVALID_EIP1271 } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import {SignatureERC1271Invalid} from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; +import {SIGNATURE_INVALID_EIP1271} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; /** * @dev ERC1271Wallet recovers a signature's signer using ECDSA. If it matches the mock wallet's @@ -49,13 +49,7 @@ contract SignaturesERC1271WalletForERC721Test is ProtocolBase { _assertValidMakerOrder(makerAsk, signature); vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); assertEq(mockERC721.ownerOf(makerAsk.itemIds[0]), takerUser); } @@ -76,13 +70,7 @@ contract SignaturesERC1271WalletForERC721Test is ProtocolBase { vm.expectRevert(SignatureERC1271Invalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testTakerBidReentrancy() public { @@ -92,19 +80,12 @@ contract SignaturesERC1271WalletForERC721Test is ProtocolBase { _setUpUser(address(maliciousERC1271Wallet)); maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerBid); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _takerBidSetup( - address(maliciousERC1271Wallet) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _takerBidSetup(address(maliciousERC1271Wallet)); vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - _EMPTY_SIGNATURE, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE); } function testTakerAsk() public { @@ -121,7 +102,7 @@ contract SignaturesERC1271WalletForERC721Test is ProtocolBase { _assertValidMakerOrder(makerBid, signature); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); assertEq(mockERC721.ownerOf(makerBid.itemIds[0]), address(wallet)); } @@ -142,7 +123,7 @@ contract SignaturesERC1271WalletForERC721Test is ProtocolBase { vm.expectRevert(SignatureERC1271Invalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testTakerAskReentrancy() public { @@ -152,13 +133,12 @@ contract SignaturesERC1271WalletForERC721Test is ProtocolBase { _setUpUser(address(maliciousERC1271Wallet)); maliciousERC1271Wallet.setFunctionToReenter(MaliciousERC1271Wallet.FunctionToReenter.ExecuteTakerAsk); - (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = _takerAskSetup( - address(maliciousERC1271Wallet) - ); + (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) = + _takerAskSetup(address(maliciousERC1271Wallet)); vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, _EMPTY_SIGNATURE, _EMPTY_MERKLE_TREE); } uint256 private constant numberPurchases = 3; @@ -179,13 +159,8 @@ contract SignaturesERC1271WalletForERC721Test is ProtocolBase { vm.stopPrank(); vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); for (uint256 i; i < numberPurchases; i++) { @@ -215,13 +190,8 @@ contract SignaturesERC1271WalletForERC721Test is ProtocolBase { vm.expectRevert(SignatureERC1271Invalid.selector); vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); } @@ -241,37 +211,32 @@ contract SignaturesERC1271WalletForERC721Test is ProtocolBase { vm.expectRevert(IReentrancyGuard.ReentrancyFail.selector); vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); } - function _takerBidSetup( - address signer - ) private returns (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) { + function _takerBidSetup(address signer) + private + returns (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) + { (makerAsk, takerBid) = _createMockMakerAskAndTakerBid(address(mockERC721)); makerAsk.signer = signer; // Mint asset mockERC721.mint(signer, makerAsk.itemIds[0]); } - function _takerAskSetup( - address signer - ) private returns (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) { + function _takerAskSetup(address signer) + private + returns (OrderStructs.Taker memory takerAsk, OrderStructs.Maker memory makerBid) + { (makerBid, takerAsk) = _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); makerBid.signer = signer; // Mint asset mockERC721.mint(takerUser, makerBid.itemIds[0]); } - function _multipleTakerBidsSetup( - address signer - ) + function _multipleTakerBidsSetup(address signer) private returns ( OrderStructs.Maker[] memory makerAsks, diff --git a/contracts/test/foundry/marketplace/SignaturesRevertions.t.sol b/contracts/test/foundry/marketplace/SignaturesRevertions.t.sol index 1861c480..c5f1ef18 100644 --- a/contracts/test/foundry/marketplace/SignaturesRevertions.t.sol +++ b/contracts/test/foundry/marketplace/SignaturesRevertions.t.sol @@ -2,23 +2,35 @@ pragma solidity 0.8.17; // Libraries, interfaces, errors -import { SignatureParameterVInvalid, SignatureParameterSInvalid, SignatureEOAInvalid, NullSignerAddress, SignatureLengthInvalid } from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import { + SignatureParameterVInvalid, + SignatureParameterSInvalid, + SignatureEOAInvalid, + NullSignerAddress, + SignatureLengthInvalid +} from "@looksrare/contracts-libs/contracts/errors/SignatureCheckerErrors.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; -import { INVALID_S_PARAMETER_EOA, INVALID_V_PARAMETER_EOA, NULL_SIGNER_EOA, INVALID_SIGNATURE_LENGTH, INVALID_SIGNER_EOA } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import { + INVALID_S_PARAMETER_EOA, + INVALID_V_PARAMETER_EOA, + NULL_SIGNER_EOA, + INVALID_SIGNATURE_LENGTH, + INVALID_SIGNER_EOA +} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract SignaturesRevertionsTest is ProtocolBase { uint256 internal constant _MAX_PRIVATE_KEY = - 115792089237316195423570985008687907852837564279074904382605163141518161494337; + 115_792_089_237_316_195_423_570_985_008_687_907_852_837_564_279_074_904_382_605_163_141_518_161_494_337; function setUp() public { _setUp(); @@ -49,13 +61,7 @@ contract SignaturesRevertionsTest is ProtocolBase { vm.expectRevert(SignatureEOAInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid( - _genericTakerOrder(), - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid(_genericTakerOrder(), makerAsk, signature, _EMPTY_MERKLE_TREE); } function testRevertIfInvalidVParameter(uint256 itemId, uint256 price, uint8 v) public { @@ -77,23 +83,15 @@ contract SignaturesRevertionsTest is ProtocolBase { // Sign but replace v by the fuzzed v bytes32 orderHash = _computeOrderHash(makerAsk); - (, bytes32 r, bytes32 s) = vm.sign( - makerUserPK, - keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash)) - ); + (, bytes32 r, bytes32 s) = + vm.sign(makerUserPK, keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash))); bytes memory signature = abi.encodePacked(r, s, v); _assertMakerOrderReturnValidationCode(makerAsk, signature, INVALID_V_PARAMETER_EOA); vm.expectRevert(abi.encodeWithSelector(SignatureParameterVInvalid.selector, v)); vm.prank(takerUser); - looksRareProtocol.executeTakerBid( - _genericTakerOrder(), - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid(_genericTakerOrder(), makerAsk, signature, _EMPTY_MERKLE_TREE); } function testRevertIfInvalidSParameter(uint256 itemId, uint256 price, bytes32 s) public { @@ -115,23 +113,15 @@ contract SignaturesRevertionsTest is ProtocolBase { // Sign but replace s by the fuzzed s bytes32 orderHash = _computeOrderHash(makerAsk); - (uint8 v, bytes32 r, ) = vm.sign( - makerUserPK, - keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash)) - ); + (uint8 v, bytes32 r,) = + vm.sign(makerUserPK, keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash))); bytes memory signature = abi.encodePacked(r, s, v); _assertMakerOrderReturnValidationCode(makerAsk, signature, INVALID_S_PARAMETER_EOA); vm.expectRevert(abi.encodeWithSelector(SignatureParameterSInvalid.selector)); vm.prank(takerUser); - looksRareProtocol.executeTakerBid( - _genericTakerOrder(), - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid(_genericTakerOrder(), makerAsk, signature, _EMPTY_MERKLE_TREE); } function testRevertIfRecoveredSignerIsNullAddress(uint256 itemId, uint256 price) public { @@ -151,10 +141,8 @@ contract SignaturesRevertionsTest is ProtocolBase { // Sign but replace r by empty bytes32 bytes32 orderHash = _computeOrderHash(makerAsk); - (uint8 v, , bytes32 s) = vm.sign( - makerUserPK, - keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash)) - ); + (uint8 v,, bytes32 s) = + vm.sign(makerUserPK, keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash))); bytes32 r; bytes memory signature = abi.encodePacked(r, s, v); @@ -163,22 +151,15 @@ contract SignaturesRevertionsTest is ProtocolBase { vm.expectRevert(abi.encodeWithSelector(NullSignerAddress.selector)); vm.prank(takerUser); - looksRareProtocol.executeTakerBid( - _genericTakerOrder(), - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid(_genericTakerOrder(), makerAsk, signature, _EMPTY_MERKLE_TREE); } function testRevertIfInvalidSignatureLength(uint256 itemId, uint256 price, uint256 length) public { // @dev Getting OutOfGas starting from 16,776,985, probably due to memory cost vm.assume(length != 64 && length != 65 && length < 16_776_985); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); makerAsk.itemIds[0] = itemId; makerAsk.price = price; @@ -187,6 +168,6 @@ contract SignaturesRevertionsTest is ProtocolBase { vm.expectRevert(abi.encodeWithSelector(SignatureLengthInvalid.selector, length)); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } } diff --git a/contracts/test/foundry/marketplace/StandardTransactions.t.sol b/contracts/test/foundry/marketplace/StandardTransactions.t.sol index 3bc01b8e..6d5d8b38 100644 --- a/contracts/test/foundry/marketplace/StandardTransactions.t.sol +++ b/contracts/test/foundry/marketplace/StandardTransactions.t.sol @@ -2,20 +2,20 @@ pragma solidity 0.8.17; // Libraries, interfaces, errors -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { LengthsInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {LengthsInvalid} from "@hypercerts/marketplace/errors/SharedErrors.sol"; -import { CreatorFeeManagerWithRoyalties } from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; +import {CreatorFeeManagerWithRoyalties} from "@hypercerts/marketplace/CreatorFeeManagerWithRoyalties.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract StandardTransactionsTest is ProtocolBase { error ERC721TransferFromFail(); @@ -40,9 +40,8 @@ contract StandardTransactionsTest is ProtocolBase { _setUpUsers(); _setupRegistryRoyalties(address(mockERC721), NEW_ROYALTY_FEE); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); makerAsk.price = price; bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); @@ -54,7 +53,7 @@ contract StandardTransactionsTest is ProtocolBase { _assertValidMakerOrder(makerAsk, signature); // Arrays for events - uint256[3] memory expectedFees = _calculateExpectedFees({ price: price, royaltyFeeBp: NEW_ROYALTY_FEE }); + uint256[3] memory expectedFees = _calculateExpectedFees({price: price, royaltyFeeBp: NEW_ROYALTY_FEE}); address[2] memory expectedRecipients; expectedRecipients[0] = makerUser; @@ -81,13 +80,7 @@ contract StandardTransactionsTest is ProtocolBase { expectedFees ); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); _assertSuccessfulExecutionThroughETH(takerUser, makerUser, price, expectedFees); @@ -104,9 +97,8 @@ contract StandardTransactionsTest is ProtocolBase { vm.assume(price <= 2 ether); _setUpUsers(); - (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMockMakerAskAndTakerBid( - address(mockERC721) - ); + (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = + _createMockMakerAskAndTakerBid(address(mockERC721)); makerAsk.price = price; bytes memory signature = _signMakerOrder(makerAsk, makerUserPK); @@ -121,7 +113,7 @@ contract StandardTransactionsTest is ProtocolBase { _assertValidMakerOrder(makerAsk, signature); // Arrays for events - uint256[3] memory expectedFees = _calculateExpectedFees({ price: price, royaltyFeeBp: 0 }); + uint256[3] memory expectedFees = _calculateExpectedFees({price: price, royaltyFeeBp: 0}); address[2] memory expectedRecipients; expectedRecipients[0] = makerUser; @@ -148,13 +140,7 @@ contract StandardTransactionsTest is ProtocolBase { expectedFees ); - looksRareProtocol.executeTakerBid{ value: price }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: price}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); _assertSuccessfulExecutionThroughETH(takerUser, makerUser, price, expectedFees); } @@ -168,10 +154,8 @@ contract StandardTransactionsTest is ProtocolBase { _setUpUsers(); _setupRegistryRoyalties(address(mockERC721), NEW_ROYALTY_FEE); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); makerBid.price = price; bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -183,7 +167,7 @@ contract StandardTransactionsTest is ProtocolBase { mockERC721.mint(takerUser, makerBid.itemIds[0]); // Arrays for events - uint256[3] memory expectedFees = _calculateExpectedFees({ price: price, royaltyFeeBp: NEW_ROYALTY_FEE }); + uint256[3] memory expectedFees = _calculateExpectedFees({price: price, royaltyFeeBp: NEW_ROYALTY_FEE}); address[2] memory expectedRecipients; expectedRecipients[0] = takerUser; @@ -211,7 +195,7 @@ contract StandardTransactionsTest is ProtocolBase { expectedFees ); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); _assertSuccessfulExecutionThroughWETH(makerUser, takerUser, price, expectedFees); // Verify the nonce is marked as executed @@ -219,16 +203,15 @@ contract StandardTransactionsTest is ProtocolBase { } /** - * One ERC721 is sold through a taker ask using WETH. Address zero is specified as the recipient in the taker struct. + * One ERC721 is sold through a taker ask using WETH. Address zero is specified as the recipient in the taker + * struct. */ function testTakerAskERC721WithAddressZeroSpecifiedAsRecipient(uint256 price) public { vm.assume(price <= 2 ether); _setUpUsers(); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); makerBid.price = price; bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -243,7 +226,7 @@ contract StandardTransactionsTest is ProtocolBase { mockERC721.mint(takerUser, makerBid.itemIds[0]); // Arrays for events - uint256[3] memory expectedFees = _calculateExpectedFees({ price: price, royaltyFeeBp: 0 }); + uint256[3] memory expectedFees = _calculateExpectedFees({price: price, royaltyFeeBp: 0}); address[2] memory expectedRecipients; expectedRecipients[0] = takerUser; @@ -270,7 +253,7 @@ contract StandardTransactionsTest is ProtocolBase { expectedFees ); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); _assertSuccessfulExecutionThroughWETH(makerUser, takerUser, price, expectedFees); } @@ -317,13 +300,8 @@ contract StandardTransactionsTest is ProtocolBase { // Execute taker bid transaction vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); for (uint256 i; i < numberPurchases; i++) { @@ -338,9 +316,8 @@ contract StandardTransactionsTest is ProtocolBase { // Maker ask user receives 99.5% of the whole price (0.5% protocol) assertEq( address(makerUser).balance, - _initialETHBalanceUser + - ((price * _sellerProceedBpWithStandardProtocolFeeBp) * numberPurchases) / - ONE_HUNDRED_PERCENT_IN_BP + _initialETHBalanceUser + + ((price * _sellerProceedBpWithStandardProtocolFeeBp) * numberPurchases) / ONE_HUNDRED_PERCENT_IN_BP ); // No leftover in the balance of the contract assertEq(address(looksRareProtocol).balance, 0); @@ -397,13 +374,8 @@ contract StandardTransactionsTest is ProtocolBase { vm.expectRevert(abi.encodeWithSelector(ERC721TransferFromFail.selector)); vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: 1.4 ether * numberPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - true + looksRareProtocol.executeMultipleTakerBids{value: 1.4 ether * numberPurchases}( + takerBids, makerAsks, signatures, merkleTrees, true ); } @@ -416,13 +388,8 @@ contract StandardTransactionsTest is ProtocolBase { vm.prank(takerUser); // Execute taker bid transaction - looksRareProtocol.executeMultipleTakerBids{ value: 1.4 ether * numberPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: 1.4 ether * numberPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); } @@ -442,9 +409,9 @@ contract StandardTransactionsTest is ProtocolBase { // Maker ask user receives 99.5% of the whole price (0.5% protocol) assertEq( address(makerUser).balance, - _initialETHBalanceUser + - ((1.4 ether * _sellerProceedBpWithStandardProtocolFeeBp) * (numberPurchases - 1)) / - ONE_HUNDRED_PERCENT_IN_BP + _initialETHBalanceUser + + ((1.4 ether * _sellerProceedBpWithStandardProtocolFeeBp) * (numberPurchases - 1)) + / ONE_HUNDRED_PERCENT_IN_BP ); // 1 wei left in the balance of the contract assertEq(address(looksRareProtocol).balance, 1); @@ -465,13 +432,8 @@ contract StandardTransactionsTest is ProtocolBase { vm.expectRevert(LengthsInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); // 2. Invalid signatures length @@ -480,13 +442,8 @@ contract StandardTransactionsTest is ProtocolBase { vm.expectRevert(LengthsInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); // 3. Invalid merkle trees length @@ -495,20 +452,16 @@ contract StandardTransactionsTest is ProtocolBase { vm.expectRevert(LengthsInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeMultipleTakerBids{ value: price * numberPurchases }( - takerBids, - makerAsks, - signatures, - merkleTrees, - _EMPTY_AFFILIATE, - false + looksRareProtocol.executeMultipleTakerBids{value: price * numberPurchases}( + takerBids, makerAsks, signatures, merkleTrees, false ); } - function _calculateExpectedFees( - uint256 price, - uint256 royaltyFeeBp - ) private pure returns (uint256[3] memory expectedFees) { + function _calculateExpectedFees(uint256 price, uint256 royaltyFeeBp) + private + pure + returns (uint256[3] memory expectedFees) + { expectedFees[2] = (price * _standardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; expectedFees[1] = (price * royaltyFeeBp) / ONE_HUNDRED_PERCENT_IN_BP; if (expectedFees[2] + expectedFees[1] < ((price * _minTotalFeeBp) / ONE_HUNDRED_PERCENT_IN_BP)) { diff --git a/contracts/test/foundry/marketplace/StrategyManager.t.sol b/contracts/test/foundry/marketplace/StrategyManager.t.sol index 4d18eba3..e59128f2 100644 --- a/contracts/test/foundry/marketplace/StrategyManager.t.sol +++ b/contracts/test/foundry/marketplace/StrategyManager.t.sol @@ -2,29 +2,31 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; +import {IOwnableTwoSteps} from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Interfaces -import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; -import { IStrategy } from "@hypercerts/marketplace/interfaces/IStrategy.sol"; +import {IStrategyManager} from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; +import {IStrategy} from "@hypercerts/marketplace/interfaces/IStrategy.sol"; // Random strategy -import { StrategyCollectionOffer } from "@hypercerts/marketplace/executionStrategies/StrategyCollectionOffer.sol"; +import {StrategyCollectionOffer} from "@hypercerts/marketplace/executionStrategies/StrategyCollectionOffer.sol"; // Base test -import { ProtocolBase } from "./ProtocolBase.t.sol"; +import {ProtocolBase} from "./ProtocolBase.t.sol"; contract FalseBaseStrategy is IStrategy { /** * @inheritdoc IStrategy */ - function isMakerOrderValid( - OrderStructs.Maker calldata, - bytes4 - ) external view override returns (bool isValid, bytes4 errorSelector) { + function isMakerOrderValid(OrderStructs.Maker calldata, bytes4) + external + view + override + returns (bool isValid, bytes4 errorSelector) + { // } @@ -83,13 +85,7 @@ contract StrategyManagerTest is ProtocolBase, IStrategyManager { vm.expectEmit(true, false, false, true); emit NewStrategy( - strategyId, - _standardProtocolFeeBp, - _minTotalFeeBp, - _maxProtocolFeeBp, - selector, - isMakerBid, - implementation + strategyId, _standardProtocolFeeBp, _minTotalFeeBp, _maxProtocolFeeBp, selector, isMakerBid, implementation ); _addStrategy(implementation, selector, isMakerBid); @@ -131,15 +127,8 @@ contract StrategyManagerTest is ProtocolBase, IStrategyManager { * Owner functions for strategy updates revert as expected under multiple revertion scenarios */ function testOwnerRevertionsForInvalidParametersUpdateStrategy() public asPrankedUser(_owner) { - ( - , - uint16 currentStandardProtocolFee, - uint16 currentMinTotalFee, - uint16 maxProtocolFeeBp, - , - , - - ) = looksRareProtocol.strategyInfo(0); + (, uint16 currentStandardProtocolFee, uint16 currentMinTotalFee, uint16 maxProtocolFeeBp,,,) = + looksRareProtocol.strategyInfo(0); // 1. newStandardProtocolFee is higher than maxProtocolFeeBp uint16 newStandardProtocolFee = maxProtocolFeeBp + 1; @@ -171,36 +160,21 @@ contract StrategyManagerTest is ProtocolBase, IStrategyManager { maxProtocolFeeBp = standardProtocolFeeBp - 1; vm.expectRevert(abi.encodeWithSelector(IStrategyManager.StrategyProtocolFeeTooHigh.selector)); looksRareProtocol.addStrategy( - standardProtocolFeeBp, - minTotalFeeBp, - maxProtocolFeeBp, - _EMPTY_BYTES4, - true, - implementation + standardProtocolFeeBp, minTotalFeeBp, maxProtocolFeeBp, _EMPTY_BYTES4, true, implementation ); // 2. minTotalFeeBp is higher than maxProtocolFeeBp maxProtocolFeeBp = minTotalFeeBp - 1; vm.expectRevert(abi.encodeWithSelector(IStrategyManager.StrategyProtocolFeeTooHigh.selector)); looksRareProtocol.addStrategy( - standardProtocolFeeBp, - minTotalFeeBp, - maxProtocolFeeBp, - _EMPTY_BYTES4, - true, - implementation + standardProtocolFeeBp, minTotalFeeBp, maxProtocolFeeBp, _EMPTY_BYTES4, true, implementation ); // 3. maxProtocolFeeBp is higher than _MAX_PROTOCOL_FEE maxProtocolFeeBp = 500 + 1; vm.expectRevert(abi.encodeWithSelector(IStrategyManager.StrategyProtocolFeeTooHigh.selector)); looksRareProtocol.addStrategy( - standardProtocolFeeBp, - minTotalFeeBp, - maxProtocolFeeBp, - _EMPTY_BYTES4, - true, - implementation + standardProtocolFeeBp, minTotalFeeBp, maxProtocolFeeBp, _EMPTY_BYTES4, true, implementation ); } diff --git a/contracts/test/foundry/marketplace/TransferManager.t.sol b/contracts/test/foundry/marketplace/TransferManager.t.sol index 6d7f4643..d223cc59 100644 --- a/contracts/test/foundry/marketplace/TransferManager.t.sol +++ b/contracts/test/foundry/marketplace/TransferManager.t.sol @@ -2,24 +2,24 @@ pragma solidity 0.8.17; // LooksRare unopinionated libraries -import { IOwnableTwoSteps } from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; +import {IOwnableTwoSteps} from "@looksrare/contracts-libs/contracts/interfaces/IOwnableTwoSteps.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Core contracts -import { LooksRareProtocol } from "@hypercerts/marketplace/LooksRareProtocol.sol"; -import { ITransferManager, TransferManager } from "@hypercerts/marketplace/TransferManager.sol"; -import { AmountInvalid, LengthsInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import {LooksRareProtocol} from "@hypercerts/marketplace/LooksRareProtocol.sol"; +import {ITransferManager, TransferManager} from "@hypercerts/marketplace/TransferManager.sol"; +import {AmountInvalid, LengthsInvalid} from "@hypercerts/marketplace/errors/SharedErrors.sol"; // Mocks and other utils -import { MockERC721 } from "../../mock/MockERC721.sol"; -import { MockERC1155 } from "../../mock/MockERC1155.sol"; -import { TestHelpers } from "./utils/TestHelpers.sol"; -import { TestParameters } from "./utils/TestParameters.sol"; +import {MockERC721} from "../../mock/MockERC721.sol"; +import {MockERC1155} from "../../mock/MockERC1155.sol"; +import {TestHelpers} from "./utils/TestHelpers.sol"; +import {TestParameters} from "./utils/TestParameters.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; contract TransferManagerTest is ITransferManager, TestHelpers, TestParameters { address[] public operators; @@ -398,21 +398,13 @@ contract TransferManagerTest is ITransferManager, TestHelpers, TestParameters { // 1. ERC721 vm.expectRevert(LengthsInvalid.selector); transferManager.transferItemsERC721( - address(mockERC721), - _sender, - _recipient, - emptyArrayUint256, - emptyArrayUint256 + address(mockERC721), _sender, _recipient, emptyArrayUint256, emptyArrayUint256 ); // 2. ERC1155 length is 0 vm.expectRevert(LengthsInvalid.selector); transferManager.transferItemsERC1155( - address(mockERC1155), - _sender, - _recipient, - emptyArrayUint256, - emptyArrayUint256 + address(mockERC1155), _sender, _recipient, emptyArrayUint256, emptyArrayUint256 ); } diff --git a/contracts/test/foundry/marketplace/assembly/VerifyOrderTimestampValidityEquivalence.t.sol b/contracts/test/foundry/marketplace/assembly/VerifyOrderTimestampValidityEquivalence.t.sol index 9a124211..504f0049 100644 --- a/contracts/test/foundry/marketplace/assembly/VerifyOrderTimestampValidityEquivalence.t.sol +++ b/contracts/test/foundry/marketplace/assembly/VerifyOrderTimestampValidityEquivalence.t.sol @@ -1,10 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { Test } from "forge-std/Test.sol"; +import {Test} from "forge-std/Test.sol"; // Assembly -import { OutsideOfTimeRange_error_selector, OutsideOfTimeRange_error_length, Error_selector_offset } from "@hypercerts/marketplace/constants/AssemblyConstants.sol"; +import { + OutsideOfTimeRange_error_selector, + OutsideOfTimeRange_error_length, + Error_selector_offset +} from "@hypercerts/marketplace/constants/AssemblyConstants.sol"; contract NonAssemblyCode { error OutsideOfTimeRange(); diff --git a/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol b/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol index df930c71..066df8a6 100644 --- a/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol +++ b/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol @@ -2,26 +2,38 @@ pragma solidity 0.8.17; // Libraries and interfaces -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; -import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {IExecutionManager} from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import {IStrategyManager} from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; // Errors and constants -import { AmountInvalid, BidTooLow, OrderInvalid, CurrencyInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; -import { ChainlinkPriceInvalid, PriceNotRecentEnough } from "@hypercerts/marketplace/errors/ChainlinkErrors.sol"; -import { MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE, MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE, STRATEGY_NOT_ACTIVE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import { + AmountInvalid, + BidTooLow, + OrderInvalid, + CurrencyInvalid, + FunctionSelectorInvalid, + QuoteTypeInvalid +} from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import {ChainlinkPriceInvalid, PriceNotRecentEnough} from "@hypercerts/marketplace/errors/ChainlinkErrors.sol"; +import { + MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE, + MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE, + STRATEGY_NOT_ACTIVE +} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Strategies -import { StrategyChainlinkUSDDynamicAsk } from "@hypercerts/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol"; +import {StrategyChainlinkUSDDynamicAsk} from + "@hypercerts/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.sol"; // Mocks and other tests -import { MockChainlinkAggregator } from "../../../../mock/MockChainlinkAggregator.sol"; -import { MockERC20 } from "../../../../mock/MockERC20.sol"; -import { ProtocolBase } from "../../ProtocolBase.t.sol"; +import {MockChainlinkAggregator} from "../../../../mock/MockChainlinkAggregator.sol"; +import {MockERC20} from "../../../../mock/MockERC20.sol"; +import {ProtocolBase} from "../../ProtocolBase.t.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { StrategyChainlinkUSDDynamicAsk public strategyUSDDynamicAsk; @@ -33,10 +45,10 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { // startedAt uint256 : 1665680123 // updatedAt uint256 : 1665680123 // answeredInRound uint80 : 92233720368547793259 - uint256 private constant CHAINLINK_PRICE_UPDATED_AT = 1665680123; - uint256 private constant FORKED_BLOCK_NUMBER = 15740567; - uint256 private constant LATEST_CHAINLINK_ANSWER_IN_WAD = 126533075631 * 1e10; - uint256 private constant MAXIMUM_LATENCY = 3_600 seconds; + uint256 private constant CHAINLINK_PRICE_UPDATED_AT = 1_665_680_123; + uint256 private constant FORKED_BLOCK_NUMBER = 15_740_567; + uint256 private constant LATEST_CHAINLINK_ANSWER_IN_WAD = 126_533_075_631 * 1e10; + uint256 private constant MAXIMUM_LATENCY = 3600 seconds; function setUp() public { vm.createSelectFork(vm.rpcUrl("mainnet"), FORKED_BLOCK_NUMBER); @@ -54,13 +66,12 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { _addStrategy(address(strategyUSDDynamicAsk), selector, false); } - function _createMakerAskAndTakerBid( - uint256 numberOfItems, - uint256 numberOfAmounts, - uint256 desiredSalePriceInUSD - ) private returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) { + function _createMakerAskAndTakerBid(uint256 numberOfItems, uint256 numberOfAmounts, uint256 desiredSalePriceInUSD) + private + returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) + { uint256[] memory itemIds = new uint256[](numberOfItems); - for (uint256 i; i < numberOfItems; ) { + for (uint256 i; i < numberOfItems;) { mockERC721.mint(makerUser, i + 1); itemIds[i] = i + 1; unchecked { @@ -69,7 +80,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { } uint256[] memory amounts = new uint256[](numberOfAmounts); - for (uint256 i; i < numberOfAmounts; ) { + for (uint256 i; i < numberOfAmounts;) { amounts[i] = 1; unchecked { ++i; @@ -102,7 +113,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { } function testMaxLatency() public { - assertEq(strategyUSDDynamicAsk.maxLatency(), 3_600); + assertEq(strategyUSDDynamicAsk.maxLatency(), 3600); } function testUSDDynamicAskChainlinkPriceInvalid() public { @@ -124,7 +135,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); MockChainlinkAggregator(CHAINLINK_ETH_USD_PRICE_FEED).setAnswer(0); (isValid, errorSelector) = strategyUSDDynamicAsk.isMakerOrderValid(makerAsk, selector); @@ -133,7 +144,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testUSDDynamicAskUSDValueGreaterThanOrEqualToMinAcceptedEthValue() public { @@ -151,7 +162,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { // Execute taker bid transaction vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // Taker user has received the asset assertEq(mockERC721.ownerOf(1), takerUser); @@ -176,7 +187,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { // Execute taker bid transaction vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // Taker user has received the asset assertEq(mockERC721.ownerOf(1), takerUser); @@ -205,7 +216,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { // Execute taker bid transaction vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // Taker user has received the asset assertEq(mockERC721.ownerOf(1), takerUser); @@ -239,13 +250,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { // Execute taker bid transaction vm.prank(takerUser); - looksRareProtocol.executeTakerBid{ value: maxPrice }( - takerBid, - makerAsk, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerBid{value: maxPrice}(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // Taker user has received the asset assertEq(mockERC721.ownerOf(1), takerUser); @@ -277,7 +282,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testCannotExecuteIfNotWETHOrETH() public { @@ -302,7 +307,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testZeroItemIdsLength() public { @@ -320,7 +325,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testItemIdsAndAmountsLengthMismatch() public { @@ -338,7 +343,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testWrongQuoteType() public { @@ -382,7 +387,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { vm.prank(takerUser); vm.expectRevert(AmountInvalid.selector); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testAmountGreaterThanOneForERC721() public { @@ -404,7 +409,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { vm.prank(takerUser); vm.expectRevert(AmountInvalid.selector); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testTakerBidTooLow() public { @@ -425,7 +430,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(BidTooLow.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testInactiveStrategy() public { @@ -446,7 +451,7 @@ contract USDDynamicAskOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(abi.encodeWithSelector(IExecutionManager.StrategyNotAvailable.selector, 1)); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testInvalidSelector() public { diff --git a/contracts/test/foundry/marketplace/executionStrategies/CollectionOffers.t.sol b/contracts/test/foundry/marketplace/executionStrategies/CollectionOffers.t.sol index 429bee91..9f9efa3f 100644 --- a/contracts/test/foundry/marketplace/executionStrategies/CollectionOffers.t.sol +++ b/contracts/test/foundry/marketplace/executionStrategies/CollectionOffers.t.sol @@ -2,27 +2,34 @@ pragma solidity 0.8.17; // Murky (third-party) library is used to compute Merkle trees in Solidity -import { Merkle } from "murky/Merkle.sol"; +import {Merkle} from "murky/Merkle.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Shared errors -import { AmountInvalid, OrderInvalid, FunctionSelectorInvalid, MerkleProofInvalid, QuoteTypeInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; -import { MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import { + AmountInvalid, + OrderInvalid, + FunctionSelectorInvalid, + MerkleProofInvalid, + QuoteTypeInvalid +} from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import {MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE} from + "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Strategies -import { StrategyCollectionOffer } from "@hypercerts/marketplace/executionStrategies/StrategyCollectionOffer.sol"; +import {StrategyCollectionOffer} from "@hypercerts/marketplace/executionStrategies/StrategyCollectionOffer.sol"; // Base test -import { ProtocolBase } from "../ProtocolBase.t.sol"; +import {ProtocolBase} from "../ProtocolBase.t.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract CollectionOrdersTest is ProtocolBase { StrategyCollectionOffer public strategyCollectionOffer; @@ -68,10 +75,8 @@ contract CollectionOrdersTest is ProtocolBase { function testMakerBidAmountsLengthNotOne() public { _setUpUsers(); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); // Adjust strategy for collection order and sign order // Change array to make it bigger than expected @@ -86,7 +91,7 @@ contract CollectionOrdersTest is ProtocolBase { _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); vm.expectRevert(OrderInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // With proof makerBid.strategyId = 2; @@ -97,16 +102,14 @@ contract CollectionOrdersTest is ProtocolBase { _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); vm.expectRevert(OrderInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testZeroAmount() public { _setUpUsers(); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMockMakerBidAndTakerAsk( - address(mockERC721), - address(weth) - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMockMakerBidAndTakerAsk(address(mockERC721), address(weth)); uint256[] memory amounts = new uint256[](1); amounts[0] = 0; @@ -121,7 +124,7 @@ contract CollectionOrdersTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(AmountInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } /** @@ -159,7 +162,7 @@ contract CollectionOrdersTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); _assertSuccessfulTakerAsk(makerBid, tokenId); } @@ -205,7 +208,7 @@ contract CollectionOrdersTest is ProtocolBase { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); _assertSuccessfulTakerAsk(makerBid, itemIdInMerkleTree); } @@ -249,7 +252,7 @@ contract CollectionOrdersTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(MerkleProofInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testInvalidAmounts() public { @@ -280,7 +283,7 @@ contract CollectionOrdersTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(AmountInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // 2. Amount is too high for ERC721 (without merkle proof) makerBid.amounts[0] = 2; @@ -290,7 +293,7 @@ contract CollectionOrdersTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(AmountInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // 3. Amount is 0 (with merkle proof) makerBid.strategyId = 2; @@ -312,7 +315,7 @@ contract CollectionOrdersTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(AmountInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // 4. Amount is too high for ERC721 (with merkle proof) makerBid.amounts[0] = 2; @@ -322,7 +325,7 @@ contract CollectionOrdersTest is ProtocolBase { vm.prank(takerUser); vm.expectRevert(AmountInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testMerkleRootLengthIsNot32() public { @@ -346,14 +349,9 @@ contract CollectionOrdersTest is ProtocolBase { _assertMakerOrderReturnValidationCode(makerBid, signature, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE); vm.prank(takerUser); - vm.expectRevert(); // It should revert without data (since the root cannot be extracted since the additionalParameters length is 0) - looksRareProtocol.executeTakerAsk( - _genericTakerOrder(), - makerBid, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + vm.expectRevert(); // It should revert without data (since the root cannot be extracted since the + // additionalParameters length is 0) + looksRareProtocol.executeTakerAsk(_genericTakerOrder(), makerBid, signature, _EMPTY_MERKLE_TREE); } function testInvalidSelector() public { @@ -391,29 +389,22 @@ contract CollectionOrdersTest is ProtocolBase { itemId: 0 }); - (bool orderIsValid, bytes4 errorSelector) = strategyCollectionOffer.isMakerOrderValid( - makerAsk, - selectorNoProof - ); + (bool orderIsValid, bytes4 errorSelector) = strategyCollectionOffer.isMakerOrderValid(makerAsk, selectorNoProof); assertFalse(orderIsValid); assertEq(errorSelector, QuoteTypeInvalid.selector); } function _assertOrderIsValid(OrderStructs.Maker memory makerBid, bool withProof) private { - (bool orderIsValid, bytes4 errorSelector) = strategyCollectionOffer.isMakerOrderValid( - makerBid, - withProof ? selectorWithProof : selectorNoProof - ); + (bool orderIsValid, bytes4 errorSelector) = + strategyCollectionOffer.isMakerOrderValid(makerBid, withProof ? selectorWithProof : selectorNoProof); assertTrue(orderIsValid); assertEq(errorSelector, _EMPTY_BYTES4); } function _assertOrderIsInvalid(OrderStructs.Maker memory makerBid, bool withProof) private { - (bool orderIsValid, bytes4 errorSelector) = strategyCollectionOffer.isMakerOrderValid( - makerBid, - withProof ? selectorWithProof : selectorNoProof - ); + (bool orderIsValid, bytes4 errorSelector) = + strategyCollectionOffer.isMakerOrderValid(makerBid, withProof ? selectorWithProof : selectorNoProof); assertFalse(orderIsValid); assertEq(errorSelector, OrderInvalid.selector); diff --git a/contracts/test/foundry/marketplace/executionStrategies/DutchAuctionOrders.t.sol b/contracts/test/foundry/marketplace/executionStrategies/DutchAuctionOrders.t.sol index dd8b05c6..4370cb3d 100644 --- a/contracts/test/foundry/marketplace/executionStrategies/DutchAuctionOrders.t.sol +++ b/contracts/test/foundry/marketplace/executionStrategies/DutchAuctionOrders.t.sol @@ -2,26 +2,36 @@ pragma solidity 0.8.17; // Libraries and interfaces -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; -import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {IExecutionManager} from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import {IStrategyManager} from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; // Shared errors -import { AmountInvalid, BidTooLow, OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; -import { STRATEGY_NOT_ACTIVE, MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import { + AmountInvalid, + BidTooLow, + OrderInvalid, + FunctionSelectorInvalid, + QuoteTypeInvalid +} from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { + STRATEGY_NOT_ACTIVE, + MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE, + MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE +} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Strategies -import { StrategyDutchAuction } from "@hypercerts/marketplace/executionStrategies/StrategyDutchAuction.sol"; +import {StrategyDutchAuction} from "@hypercerts/marketplace/executionStrategies/StrategyDutchAuction.sol"; // Other tests -import { ProtocolBase } from "../ProtocolBase.t.sol"; +import {ProtocolBase} from "../ProtocolBase.t.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { StrategyDutchAuction public strategyDutchAuction; @@ -44,7 +54,7 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { uint256 endTime ) private returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) { uint256[] memory itemIds = new uint256[](numberOfItems); - for (uint256 i; i < numberOfItems; ) { + for (uint256 i; i < numberOfItems;) { mockERC721.mint(makerUser, i + 1); itemIds[i] = i + 1; unchecked { @@ -53,7 +63,7 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { } uint256[] memory amounts = new uint256[](numberOfAmounts); - for (uint256 i; i < numberOfAmounts; ) { + for (uint256 i; i < numberOfAmounts;) { amounts[i] = 1; unchecked { ++i; @@ -89,12 +99,10 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { _assertStrategyAttributes(address(strategyDutchAuction), selector, false); } - function _fuzzAssumptions( - uint256 _startPrice, - uint256 _duration, - uint256 _decayPerSecond, - uint256 _elapsedTime - ) private returns (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) { + function _fuzzAssumptions(uint256 _startPrice, uint256 _duration, uint256 _decayPerSecond, uint256 _elapsedTime) + private + returns (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) + { // Bound instead of assume to handle too many rejections // These limits should be realistically way more than enough // vm.assume(duration > 0 && duration <= 31_536_000); @@ -111,38 +119,25 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { elapsedTime = _elapsedTime; } - function _calculatePrices( - uint256 startPrice, - uint256 duration, - uint256 decayPerSecond, - uint256 elapsedTime - ) private pure returns (uint256 endPrice, uint256 executionPrice) { + function _calculatePrices(uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) + private + pure + returns (uint256 endPrice, uint256 executionPrice) + { endPrice = startPrice - decayPerSecond * duration; uint256 discount = decayPerSecond * elapsedTime; executionPrice = startPrice - discount; } - function testDutchAuction( - uint256 _startPrice, - uint256 _duration, - uint256 _decayPerSecond, - uint256 _elapsedTime - ) public { - (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) = _fuzzAssumptions( - _startPrice, - _duration, - _decayPerSecond, - _elapsedTime - ); + function testDutchAuction(uint256 _startPrice, uint256 _duration, uint256 _decayPerSecond, uint256 _elapsedTime) + public + { + (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) = + _fuzzAssumptions(_startPrice, _duration, _decayPerSecond, _elapsedTime); _setUpUsers(); _setUpNewStrategy(); - (uint256 endPrice, uint256 executionPrice) = _calculatePrices( - startPrice, - duration, - decayPerSecond, - elapsedTime - ); + (uint256 endPrice, uint256 executionPrice) = _calculatePrices(startPrice, duration, decayPerSecond, elapsedTime); deal(address(weth), takerUser, executionPrice); @@ -164,7 +159,7 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { // Execute taker bid transaction vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // Taker user has received the asset assertEq(mockERC721.ownerOf(1), takerUser); @@ -180,27 +175,15 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { ); } - function testStartPriceTooLow( - uint256 _startPrice, - uint256 _duration, - uint256 _decayPerSecond, - uint256 _elapsedTime - ) public { - (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) = _fuzzAssumptions( - _startPrice, - _duration, - _decayPerSecond, - _elapsedTime - ); + function testStartPriceTooLow(uint256 _startPrice, uint256 _duration, uint256 _decayPerSecond, uint256 _elapsedTime) + public + { + (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) = + _fuzzAssumptions(_startPrice, _duration, _decayPerSecond, _elapsedTime); _setUpUsers(); _setUpNewStrategy(); - (uint256 endPrice, uint256 executionPrice) = _calculatePrices( - startPrice, - duration, - decayPerSecond, - elapsedTime - ); + (uint256 endPrice, uint256 executionPrice) = _calculatePrices(startPrice, duration, decayPerSecond, elapsedTime); deal(address(weth), takerUser, executionPrice); (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ @@ -221,30 +204,18 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } - function testTakerBidTooLow( - uint256 _startPrice, - uint256 _duration, - uint256 _decayPerSecond, - uint256 _elapsedTime - ) public { - (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) = _fuzzAssumptions( - _startPrice, - _duration, - _decayPerSecond, - _elapsedTime - ); + function testTakerBidTooLow(uint256 _startPrice, uint256 _duration, uint256 _decayPerSecond, uint256 _elapsedTime) + public + { + (uint256 startPrice, uint256 duration, uint256 decayPerSecond, uint256 elapsedTime) = + _fuzzAssumptions(_startPrice, _duration, _decayPerSecond, _elapsedTime); _setUpUsers(); _setUpNewStrategy(); - (uint256 endPrice, uint256 executionPrice) = _calculatePrices( - startPrice, - duration, - decayPerSecond, - elapsedTime - ); + (uint256 endPrice, uint256 executionPrice) = _calculatePrices(startPrice, duration, decayPerSecond, elapsedTime); deal(address(weth), takerUser, executionPrice); (OrderStructs.Maker memory makerAsk, OrderStructs.Taker memory takerBid) = _createMakerAskAndTakerBid({ @@ -266,7 +237,7 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(BidTooLow.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testInactiveStrategy() public { @@ -291,7 +262,7 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { vm.prank(takerUser); vm.expectRevert(abi.encodeWithSelector(IExecutionManager.StrategyNotAvailable.selector, 1)); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testZeroItemIdsLength() public { @@ -313,7 +284,7 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testItemIdsAndAmountsLengthMismatch() public { @@ -335,7 +306,7 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testInvalidAmounts() public { @@ -361,7 +332,7 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(AmountInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); // 2. ERC721 amount > 1 makerAsk.amounts[0] = 2; @@ -372,7 +343,7 @@ contract DutchAuctionOrdersTest is ProtocolBase, IStrategyManager { vm.prank(takerUser); vm.expectRevert(AmountInvalid.selector); - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, _EMPTY_MERKLE_TREE); } function testWrongQuoteType() public { diff --git a/contracts/test/foundry/marketplace/executionStrategies/ItemIdsRangeOrders.t.sol b/contracts/test/foundry/marketplace/executionStrategies/ItemIdsRangeOrders.t.sol index 714595d8..07199143 100644 --- a/contracts/test/foundry/marketplace/executionStrategies/ItemIdsRangeOrders.t.sol +++ b/contracts/test/foundry/marketplace/executionStrategies/ItemIdsRangeOrders.t.sol @@ -2,23 +2,29 @@ pragma solidity 0.8.17; // Libraries and interfaces -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; -import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; -import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {IExecutionManager} from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import {IStrategyManager} from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; // Shared errors -import { OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; -import { STRATEGY_NOT_ACTIVE, MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE, MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE } from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; +import { + OrderInvalid, FunctionSelectorInvalid, QuoteTypeInvalid +} from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import { + STRATEGY_NOT_ACTIVE, + MAKER_ORDER_TEMPORARILY_INVALID_NON_STANDARD_SALE, + MAKER_ORDER_PERMANENTLY_INVALID_NON_STANDARD_SALE +} from "@hypercerts/marketplace/constants/ValidationCodeConstants.sol"; // Strategies -import { StrategyItemIdsRange } from "@hypercerts/marketplace/executionStrategies/StrategyItemIdsRange.sol"; +import {StrategyItemIdsRange} from "@hypercerts/marketplace/executionStrategies/StrategyItemIdsRange.sol"; // Base test -import { ProtocolBase } from "../ProtocolBase.t.sol"; +import {ProtocolBase} from "../ProtocolBase.t.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { StrategyItemIdsRange public strategyItemIdsRange; @@ -40,10 +46,10 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { } } - function _createMakerBidAndTakerAsk( - uint256 lowerBound, - uint256 upperBound - ) private returns (OrderStructs.Maker memory newMakerBid, OrderStructs.Taker memory newTakerAsk) { + function _createMakerBidAndTakerAsk(uint256 lowerBound, uint256 upperBound) + private + returns (OrderStructs.Maker memory newMakerBid, OrderStructs.Taker memory newTakerAsk) + { uint256 mid = (lowerBound + upperBound) / 2; newMakerBid = _createMultiItemMakerOrder({ @@ -82,7 +88,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { newTakerAsk = OrderStructs.Taker({ recipient: takerUser, - additionalParameters: abi.encode(takerAskItemIds, _offeredAmounts({ length: 3, amount: 1 })) + additionalParameters: abi.encode(takerAskItemIds, _offeredAmounts({length: 3, amount: 1})) }); } @@ -98,10 +104,8 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { _setUpUsers(); _setUpNewStrategy(); - (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = _createMakerBidAndTakerAsk( - lowerBound, - upperBound - ); + (OrderStructs.Maker memory makerBid, OrderStructs.Taker memory takerAsk) = + _createMakerBidAndTakerAsk(lowerBound, upperBound); // Sign order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -111,7 +115,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // Maker user has received the asset assertEq(mockERC721.ownerOf(lowerBound), makerUser); @@ -160,7 +164,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { OrderStructs.Taker memory takerAsk = OrderStructs.Taker({ recipient: takerUser, - additionalParameters: abi.encode(takerAskItemIds, _offeredAmounts({ length: 3, amount: 2 })) + additionalParameters: abi.encode(takerAskItemIds, _offeredAmounts({length: 3, amount: 2})) }); // Sign order @@ -171,7 +175,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { // Execute taker ask transaction vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // Maker user has received the asset assertEq(mockERC1155.balanceOf(makerUser, lowerBound), 2); @@ -201,7 +205,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(); // EVM revert vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testZeroDesiredAmount() public { @@ -218,12 +222,12 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testWrongQuoteType() public { _setUpNewStrategy(); - (OrderStructs.Maker memory makerBid, ) = _createMakerBidAndTakerAsk(5, 10); + (OrderStructs.Maker memory makerBid,) = _createMakerBidAndTakerAsk(5, 10); makerBid.quoteType = QuoteType.Ask; (bool isValid, bytes4 errorSelector) = strategyItemIdsRange.isMakerOrderValid(makerBid, selector); @@ -246,11 +250,11 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { takerAskItemIds[0] = 5; takerAskItemIds[1] = 7; takerAskItemIds[2] = 10; - takerAsk.additionalParameters = abi.encode(takerAskItemIds, _offeredAmounts({ length: 4, amount: 1 })); + takerAsk.additionalParameters = abi.encode(takerAskItemIds, _offeredAmounts({length: 4, amount: 1})); vm.prank(takerUser); vm.expectRevert(OrderInvalid.selector); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testTakerAskRevertIfAmountIsZeroOrGreaterThanOneERC721() public { @@ -280,7 +284,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { // It fails at 2nd item in the array (greater than 1) vm.expectRevert(OrderInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // Re-adjust the amounts invalidAmounts[0] = 0; @@ -292,7 +296,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { // It now fails at 1st item in the array (equal to 0) vm.expectRevert(OrderInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testMakerBidItemIdsLowerBandHigherThanOrEqualToUpperBand() public { @@ -311,7 +315,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(errorSelector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // lower band == upper band makerBid.additionalParameters = abi.encode(5, 5, 1); @@ -321,7 +325,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(OrderInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testTakerAskDuplicatedItemIds() public { @@ -334,7 +338,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { invalidItemIds[1] = 7; invalidItemIds[2] = 7; - takerAsk.additionalParameters = abi.encode(invalidItemIds, _offeredAmounts({ length: 3, amount: 1 })); + takerAsk.additionalParameters = abi.encode(invalidItemIds, _offeredAmounts({length: 3, amount: 1})); // Sign order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -345,7 +349,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(OrderInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testTakerAskUnsortedItemIds() public { @@ -358,7 +362,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { invalidItemIds[1] = 10; invalidItemIds[2] = 7; - takerAsk.additionalParameters = abi.encode(invalidItemIds, _offeredAmounts({ length: 3, amount: 1 })); + takerAsk.additionalParameters = abi.encode(invalidItemIds, _offeredAmounts({length: 3, amount: 1})); // Sign order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -369,7 +373,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(OrderInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testTakerAskOfferedAmountNotEqualToDesiredAmount() public { @@ -381,7 +385,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { itemIds[0] = 5; itemIds[1] = 10; - takerAsk.additionalParameters = abi.encode(itemIds, _offeredAmounts({ length: 2, amount: 1 })); + takerAsk.additionalParameters = abi.encode(itemIds, _offeredAmounts({length: 2, amount: 1})); // Sign order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -392,7 +396,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(OrderInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testTakerAskOfferedItemIdTooLow() public { @@ -411,7 +415,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { itemIds[0] = itemIdOne; itemIds[1] = itemIdTwo; - takerAsk.additionalParameters = abi.encode(itemIds, _offeredAmounts({ length: 2, amount: 1 })); + takerAsk.additionalParameters = abi.encode(itemIds, _offeredAmounts({length: 2, amount: 1})); // Sign order bytes memory signature = _signMakerOrder(makerBid, makerUserPK); @@ -421,7 +425,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(OrderInvalid.selector); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testInactiveStrategy() public { @@ -442,7 +446,7 @@ contract ItemIdsRangeOrdersTest is ProtocolBase, IStrategyManager { vm.expectRevert(abi.encodeWithSelector(IExecutionManager.StrategyNotAvailable.selector, 1)); vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); } function testInvalidSelector() public { diff --git a/contracts/test/foundry/marketplace/executionStrategies/MultiFillCollectionOrders.t.sol b/contracts/test/foundry/marketplace/executionStrategies/MultiFillCollectionOrders.t.sol index 4e8f9f37..5fd15bda 100644 --- a/contracts/test/foundry/marketplace/executionStrategies/MultiFillCollectionOrders.t.sol +++ b/contracts/test/foundry/marketplace/executionStrategies/MultiFillCollectionOrders.t.sol @@ -2,22 +2,22 @@ pragma solidity >=0.8.7; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Interfaces -import { IExecutionManager } from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; -import { IStrategyManager } from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; +import {IExecutionManager} from "@hypercerts/marketplace/interfaces/IExecutionManager.sol"; +import {IStrategyManager} from "@hypercerts/marketplace/interfaces/IStrategyManager.sol"; // Mock files and other tests -import { StrategyTestMultiFillCollectionOrder } from "../utils/StrategyTestMultiFillCollectionOrder.sol"; -import { ProtocolBase } from "../ProtocolBase.t.sol"; +import {StrategyTestMultiFillCollectionOrder} from "../utils/StrategyTestMultiFillCollectionOrder.sol"; +import {ProtocolBase} from "../ProtocolBase.t.sol"; // Constants -import { ONE_HUNDRED_PERCENT_IN_BP } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {ONE_HUNDRED_PERCENT_IN_BP} from "@hypercerts/marketplace/constants/NumericConstants.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract MultiFillCollectionOrdersTest is ProtocolBase, IStrategyManager { uint256 private constant price = 1 ether; // Fixed price of sale @@ -85,7 +85,7 @@ contract MultiFillCollectionOrdersTest is ProtocolBase, IStrategyManager { // Execute the first taker ask transaction by the first taker user vm.prank(takerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // Taker user has received the asset assertEq(mockERC721.ownerOf(0), makerUser); @@ -120,7 +120,7 @@ contract MultiFillCollectionOrdersTest is ProtocolBase, IStrategyManager { // Execute a second taker ask transaction from the second taker user vm.prank(secondTakerUser); - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE, _EMPTY_AFFILIATE); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, _EMPTY_MERKLE_TREE); // Taker user has received the 3 assets assertEq(mockERC721.ownerOf(1), makerUser); @@ -132,9 +132,8 @@ contract MultiFillCollectionOrdersTest is ProtocolBase, IStrategyManager { // Taker ask user receives 99.5% of the whole price (0.5% protocol) assertEq( weth.balanceOf(secondTakerUser), - _initialWETHBalanceUser + - 3 * - ((price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP) + _initialWETHBalanceUser + + 3 * ((price * _sellerProceedBpWithStandardProtocolFeeBp) / ONE_HUNDRED_PERCENT_IN_BP) ); // Verify the nonce is now marked as executed assertEq(looksRareProtocol.userOrderNonce(makerUser, makerBid.orderNonce), MAGIC_VALUE_ORDER_NONCE_EXECUTED); @@ -182,13 +181,7 @@ contract MultiFillCollectionOrdersTest is ProtocolBase, IStrategyManager { // It should revert if strategy is not available vm.prank(takerUser); vm.expectRevert(abi.encodeWithSelector(IExecutionManager.StrategyNotAvailable.selector, 1)); - looksRareProtocol.executeTakerAsk( - _genericTakerOrder(), - makerBid, - signature, - _EMPTY_MERKLE_TREE, - _EMPTY_AFFILIATE - ); + looksRareProtocol.executeTakerAsk(_genericTakerOrder(), makerBid, signature, _EMPTY_MERKLE_TREE); } } } diff --git a/contracts/test/foundry/marketplace/utils/BytesLib.sol b/contracts/test/foundry/marketplace/utils/BytesLib.sol index d4140def..7d0a3ffa 100644 --- a/contracts/test/foundry/marketplace/utils/BytesLib.sol +++ b/contracts/test/foundry/marketplace/utils/BytesLib.sol @@ -47,9 +47,7 @@ library BytesLib { } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) - } { - mstore(mc, mload(cc)) - } + } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) diff --git a/contracts/test/foundry/marketplace/utils/EIP712MerkleTree.sol b/contracts/test/foundry/marketplace/utils/EIP712MerkleTree.sol index a17c3275..00e89a30 100644 --- a/contracts/test/foundry/marketplace/utils/EIP712MerkleTree.sol +++ b/contracts/test/foundry/marketplace/utils/EIP712MerkleTree.sol @@ -2,20 +2,20 @@ pragma solidity 0.8.17; // Forge test -import { Test } from "forge-std/Test.sol"; +import {Test} from "forge-std/Test.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Core contracts -import { LooksRareProtocol } from "@hypercerts/marketplace/LooksRareProtocol.sol"; +import {LooksRareProtocol} from "@hypercerts/marketplace/LooksRareProtocol.sol"; // Utils -import { MerkleWithPosition } from "./MerkleWithPosition.sol"; -import { MathLib } from "./MathLib.sol"; +import {MerkleWithPosition} from "./MerkleWithPosition.sol"; +import {MathLib} from "./MathLib.sol"; // Constants -import { MAX_CALLDATA_PROOF_LENGTH } from "@hypercerts/marketplace/constants/NumericConstants.sol"; +import {MAX_CALLDATA_PROOF_LENGTH} from "@hypercerts/marketplace/constants/NumericConstants.sol"; contract EIP712MerkleTree is Test { using OrderStructs for OrderStructs.Maker; @@ -26,11 +26,10 @@ contract EIP712MerkleTree is Test { looksRareProtocol = _looksRareProtocol; } - function sign( - uint256 privateKey, - OrderStructs.Maker[] memory makerOrders, - uint256 makerOrderIndex - ) external returns (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) { + function sign(uint256 privateKey, OrderStructs.Maker[] memory makerOrders, uint256 makerOrderIndex) + external + returns (bytes memory signature, OrderStructs.MerkleTree memory merkleTree) + { uint256 bidCount = makerOrders.length; uint256 treeHeight = MathLib.log2(bidCount); if (2 ** treeHeight != bidCount || treeHeight == 0) { @@ -43,9 +42,7 @@ contract EIP712MerkleTree is Test { for (uint256 i; i < bidCount; i++) { leaves[i] = OrderStructs.MerkleTreeNode({ value: makerOrders[i].hash(), - position: i % 2 == 0 - ? OrderStructs.MerkleTreeNodePosition.Left - : OrderStructs.MerkleTreeNodePosition.Right + position: i % 2 == 0 ? OrderStructs.MerkleTreeNodePosition.Left : OrderStructs.MerkleTreeNodePosition.Right }); } @@ -53,9 +50,7 @@ contract EIP712MerkleTree is Test { for (uint256 i = bidCount; i < leafCount; i++) { leaves[i] = OrderStructs.MerkleTreeNode({ value: emptyMakerOrderHash, - position: i % 2 == 0 - ? OrderStructs.MerkleTreeNodePosition.Left - : OrderStructs.MerkleTreeNodePosition.Right + position: i % 2 == 0 ? OrderStructs.MerkleTreeNodePosition.Left : OrderStructs.MerkleTreeNodePosition.Right }); } @@ -64,7 +59,7 @@ contract EIP712MerkleTree is Test { bytes32 root = merkle.getRoot(leaves); signature = _sign(privateKey, batchOrderTypehash, root); - merkleTree = OrderStructs.MerkleTree({ root: root, proof: proof }); + merkleTree = OrderStructs.MerkleTree({root: root, proof: proof}); } function _emptyMakerOrderHash() private pure returns (bytes32 makerOrderHash) { @@ -72,19 +67,17 @@ contract EIP712MerkleTree is Test { makerOrderHash = makerOrder.hash(); } - function _sign( - uint256 privateKey, - bytes32 batchOrderTypehash, - bytes32 root - ) private view returns (bytes memory signature) { + function _sign(uint256 privateKey, bytes32 batchOrderTypehash, bytes32 root) + private + view + returns (bytes memory signature) + { bytes32 digest = keccak256(abi.encode(batchOrderTypehash, root)); bytes32 domainSeparator = looksRareProtocol.domainSeparator(); - (uint8 v, bytes32 r, bytes32 s) = vm.sign( - privateKey, - keccak256(abi.encodePacked("\x19\x01", domainSeparator, digest)) - ); + (uint8 v, bytes32 r, bytes32 s) = + vm.sign(privateKey, keccak256(abi.encodePacked("\x19\x01", domainSeparator, digest))); signature = abi.encodePacked(r, s, v); } diff --git a/contracts/test/foundry/marketplace/utils/ERC1271Wallet.sol b/contracts/test/foundry/marketplace/utils/ERC1271Wallet.sol index ee76287f..f6eaf418 100644 --- a/contracts/test/foundry/marketplace/utils/ERC1271Wallet.sol +++ b/contracts/test/foundry/marketplace/utils/ERC1271Wallet.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { ERC1271WalletMock } from "openzeppelin-contracts/contracts/mocks/ERC1271WalletMock.sol"; +import {ERC1271WalletMock} from "openzeppelin-contracts/contracts/mocks/ERC1271WalletMock.sol"; contract ERC1271Wallet is ERC1271WalletMock { constructor(address originalOwner) ERC1271WalletMock(originalOwner) {} @@ -10,13 +10,11 @@ contract ERC1271Wallet is ERC1271WalletMock { return this.onERC1155Received.selector; } - function onERC1155BatchReceived( - address, - address, - uint256[] calldata, - uint256[] calldata, - bytes calldata - ) external pure returns (bytes4) { + function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) + external + pure + returns (bytes4) + { return this.onERC1155BatchReceived.selector; } } diff --git a/contracts/test/foundry/marketplace/utils/MaliciousERC1271Wallet.sol b/contracts/test/foundry/marketplace/utils/MaliciousERC1271Wallet.sol index 965149b3..c13ff909 100644 --- a/contracts/test/foundry/marketplace/utils/MaliciousERC1271Wallet.sol +++ b/contracts/test/foundry/marketplace/utils/MaliciousERC1271Wallet.sol @@ -1,8 +1,8 @@ /// SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { ILooksRareProtocol } from "@hypercerts/marketplace/interfaces/ILooksRareProtocol.sol"; -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {ILooksRareProtocol} from "@hypercerts/marketplace/interfaces/ILooksRareProtocol.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; abstract contract MaliciousERC1271Wallet { enum FunctionToReenter { @@ -31,13 +31,11 @@ abstract contract MaliciousERC1271Wallet { return this.onERC1155Received.selector; } - function onERC1155BatchReceived( - address, - address, - uint256[] calldata, - uint256[] calldata, - bytes calldata - ) external virtual returns (bytes4) { + function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) + external + virtual + returns (bytes4) + { return this.onERC1155BatchReceived.selector; } @@ -46,7 +44,7 @@ abstract contract MaliciousERC1271Wallet { OrderStructs.Maker memory makerBid; OrderStructs.MerkleTree memory merkleTree; - looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, merkleTree, address(this)); + looksRareProtocol.executeTakerAsk(takerAsk, makerBid, signature, merkleTree); } function _executeTakerBid(bytes memory signature) internal { @@ -54,7 +52,7 @@ abstract contract MaliciousERC1271Wallet { OrderStructs.Maker memory makerAsk; OrderStructs.MerkleTree memory merkleTree; - looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, merkleTree, address(this)); + looksRareProtocol.executeTakerBid(takerBid, makerAsk, signature, merkleTree); } function _executeMultipleTakerBids() internal { @@ -63,6 +61,6 @@ abstract contract MaliciousERC1271Wallet { bytes[] memory signatures = new bytes[](2); OrderStructs.MerkleTree[] memory merkleTrees = new OrderStructs.MerkleTree[](2); - looksRareProtocol.executeMultipleTakerBids(takerBids, makerAsks, signatures, merkleTrees, address(this), false); + looksRareProtocol.executeMultipleTakerBids(takerBids, makerAsks, signatures, merkleTrees, false); } } diff --git a/contracts/test/foundry/marketplace/utils/MaliciousIsValidSignatureERC1271Wallet.sol b/contracts/test/foundry/marketplace/utils/MaliciousIsValidSignatureERC1271Wallet.sol index d8c557ff..c8aaf1ef 100644 --- a/contracts/test/foundry/marketplace/utils/MaliciousIsValidSignatureERC1271Wallet.sol +++ b/contracts/test/foundry/marketplace/utils/MaliciousIsValidSignatureERC1271Wallet.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { MaliciousERC1271Wallet } from "./MaliciousERC1271Wallet.sol"; +import {MaliciousERC1271Wallet} from "./MaliciousERC1271Wallet.sol"; contract MaliciousIsValidSignatureERC1271Wallet is MaliciousERC1271Wallet { constructor(address _looksRareProtocol) MaliciousERC1271Wallet(_looksRareProtocol) {} diff --git a/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol b/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol index 4881535a..cc790326 100644 --- a/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol +++ b/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedERC1271Wallet.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { MaliciousERC1271Wallet } from "./MaliciousERC1271Wallet.sol"; +import {MaliciousERC1271Wallet} from "./MaliciousERC1271Wallet.sol"; contract MaliciousOnERC1155ReceivedERC1271Wallet is MaliciousERC1271Wallet { constructor(address _looksRareProtocol) MaliciousERC1271Wallet(_looksRareProtocol) {} @@ -18,13 +18,11 @@ contract MaliciousOnERC1155ReceivedERC1271Wallet is MaliciousERC1271Wallet { return this.onERC1155Received.selector; } - function onERC1155BatchReceived( - address, - address, - uint256[] calldata, - uint256[] calldata, - bytes calldata - ) external override returns (bytes4) { + function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) + external + override + returns (bytes4) + { if (functionToReenter == FunctionToReenter.ExecuteTakerAsk) { _executeTakerAsk(new bytes(0)); } else if (functionToReenter == FunctionToReenter.ExecuteTakerBid) { diff --git a/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol b/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol index 544aeb28..95ba4347 100644 --- a/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol +++ b/contracts/test/foundry/marketplace/utils/MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { MaliciousERC1271Wallet } from "./MaliciousERC1271Wallet.sol"; +import {MaliciousERC1271Wallet} from "./MaliciousERC1271Wallet.sol"; contract MaliciousOnERC1155ReceivedTheThirdTimeERC1271Wallet is MaliciousERC1271Wallet { uint256 private isValidSignatureEnterCount; diff --git a/contracts/test/foundry/marketplace/utils/MerkleWithPosition.sol b/contracts/test/foundry/marketplace/utils/MerkleWithPosition.sol index 3b7cf871..43857193 100644 --- a/contracts/test/foundry/marketplace/utils/MerkleWithPosition.sol +++ b/contracts/test/foundry/marketplace/utils/MerkleWithPosition.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; /** * @dev Modified from MurkyBase to add each node's position after hashing. @@ -22,10 +22,11 @@ contract MerkleWithPosition { return data[0].value; } - function getProof( - OrderStructs.MerkleTreeNode[] memory data, - uint256 node - ) public pure returns (OrderStructs.MerkleTreeNode[] memory result) { + function getProof(OrderStructs.MerkleTreeNode[] memory data, uint256 node) + public + pure + returns (OrderStructs.MerkleTreeNode[] memory result) + { require(data.length > 1, "won't generate proof for single leaf"); // The size of the proof is equal to the ceiling of log2(numLeaves) result = new OrderStructs.MerkleTreeNode[](log2ceilBitMagic(data.length)); @@ -56,9 +57,11 @@ contract MerkleWithPosition { } ///@dev function is private to prevent unsafe data from being passed - function hashLevel( - OrderStructs.MerkleTreeNode[] memory data - ) private pure returns (OrderStructs.MerkleTreeNode[] memory result) { + function hashLevel(OrderStructs.MerkleTreeNode[] memory data) + private + pure + returns (OrderStructs.MerkleTreeNode[] memory result) + { // Function is private, and all internal callers check that data.length >=2. // Underflow is not possible as lowest possible value for data/result index is 1 // overflow should be safe as length is / 2 always. @@ -67,10 +70,8 @@ contract MerkleWithPosition { if (length & 0x1 == 1) { result = new OrderStructs.MerkleTreeNode[](length / 2 + 1); bytes32 hashed = hashLeafPairs(data[length - 1].value, bytes32(0)); - result[result.length - 1] = OrderStructs.MerkleTreeNode({ - value: hashed, - position: OrderStructs.MerkleTreeNodePosition.Left - }); + result[result.length - 1] = + OrderStructs.MerkleTreeNode({value: hashed, position: OrderStructs.MerkleTreeNodePosition.Left}); } else { result = new OrderStructs.MerkleTreeNode[](length / 2); } diff --git a/contracts/test/foundry/marketplace/utils/MockOrderGenerator.sol b/contracts/test/foundry/marketplace/utils/MockOrderGenerator.sol index 7f6fd135..d6e695f5 100644 --- a/contracts/test/foundry/marketplace/utils/MockOrderGenerator.sol +++ b/contracts/test/foundry/marketplace/utils/MockOrderGenerator.sol @@ -2,22 +2,24 @@ pragma solidity 0.8.17; // Generic interfaces -import { IERC165 } from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC165.sol"; +import {IERC165} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC165.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Other helpers -import { ProtocolHelpers } from "../utils/ProtocolHelpers.sol"; +import {ProtocolHelpers} from "../utils/ProtocolHelpers.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract MockOrderGenerator is ProtocolHelpers { - function _createMockMakerAskAndTakerBid( - address collection - ) internal view returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) { + function _createMockMakerAskAndTakerBid(address collection) + internal + view + returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) + { CollectionType collectionType = _getCollectionType(collection); newMakerAsk = _createSingleItemMakerOrder({ @@ -37,10 +39,11 @@ contract MockOrderGenerator is ProtocolHelpers { newTakerBid = OrderStructs.Taker(takerUser, abi.encode()); } - function _createMockMakerBidAndTakerAsk( - address collection, - address currency - ) internal view returns (OrderStructs.Maker memory newMakerBid, OrderStructs.Taker memory newTakerAsk) { + function _createMockMakerBidAndTakerAsk(address collection, address currency) + internal + view + returns (OrderStructs.Maker memory newMakerBid, OrderStructs.Taker memory newTakerAsk) + { CollectionType collectionType = _getCollectionType(collection); newMakerBid = _createSingleItemMakerOrder({ @@ -60,16 +63,14 @@ contract MockOrderGenerator is ProtocolHelpers { newTakerAsk = OrderStructs.Taker(takerUser, abi.encode()); } - function _createMockMakerAskAndTakerBidWithBundle( - address collection, - uint256 numberTokens - ) internal view returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) { + function _createMockMakerAskAndTakerBidWithBundle(address collection, uint256 numberTokens) + internal + view + returns (OrderStructs.Maker memory newMakerAsk, OrderStructs.Taker memory newTakerBid) + { CollectionType collectionType = _getCollectionType(collection); - (uint256[] memory itemIds, uint256[] memory amounts) = _setBundleItemIdsAndAmounts( - collectionType, - numberTokens - ); + (uint256[] memory itemIds, uint256[] memory amounts) = _setBundleItemIdsAndAmounts(collectionType, numberTokens); newMakerAsk = _createMultiItemMakerOrder({ quoteType: QuoteType.Ask, @@ -89,17 +90,14 @@ contract MockOrderGenerator is ProtocolHelpers { newTakerBid = OrderStructs.Taker(takerUser, abi.encode()); } - function _createMockMakerBidAndTakerAskWithBundle( - address collection, - address currency, - uint256 numberTokens - ) internal view returns (OrderStructs.Maker memory newMakerBid, OrderStructs.Taker memory newTakerAsk) { + function _createMockMakerBidAndTakerAskWithBundle(address collection, address currency, uint256 numberTokens) + internal + view + returns (OrderStructs.Maker memory newMakerBid, OrderStructs.Taker memory newTakerAsk) + { CollectionType collectionType = _getCollectionType(collection); - (uint256[] memory itemIds, uint256[] memory amounts) = _setBundleItemIdsAndAmounts( - collectionType, - numberTokens - ); + (uint256[] memory itemIds, uint256[] memory amounts) = _setBundleItemIdsAndAmounts(collectionType, numberTokens); newMakerBid = _createMultiItemMakerOrder({ quoteType: QuoteType.Bid, @@ -128,10 +126,11 @@ contract MockOrderGenerator is ProtocolHelpers { } } - function _setBundleItemIdsAndAmounts( - CollectionType collectionType, - uint256 numberTokens - ) private pure returns (uint256[] memory itemIds, uint256[] memory amounts) { + function _setBundleItemIdsAndAmounts(CollectionType collectionType, uint256 numberTokens) + private + pure + returns (uint256[] memory itemIds, uint256[] memory amounts) + { itemIds = new uint256[](numberTokens); amounts = new uint256[](numberTokens); diff --git a/contracts/test/foundry/marketplace/utils/ProtocolHelpers.sol b/contracts/test/foundry/marketplace/utils/ProtocolHelpers.sol index 066bf9b3..a8c092b6 100644 --- a/contracts/test/foundry/marketplace/utils/ProtocolHelpers.sol +++ b/contracts/test/foundry/marketplace/utils/ProtocolHelpers.sol @@ -2,18 +2,18 @@ pragma solidity 0.8.17; // Dependencies -import { BatchOrderTypehashRegistry } from "@hypercerts/marketplace/BatchOrderTypehashRegistry.sol"; +import {BatchOrderTypehashRegistry} from "@hypercerts/marketplace/BatchOrderTypehashRegistry.sol"; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Other tests -import { TestHelpers } from "./TestHelpers.sol"; -import { TestParameters } from "./TestParameters.sol"; +import {TestHelpers} from "./TestHelpers.sol"; +import {TestParameters} from "./TestParameters.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; -import { QuoteType } from "@hypercerts/marketplace/enums/QuoteType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {QuoteType} from "@hypercerts/marketplace/enums/QuoteType.sol"; contract ProtocolHelpers is TestHelpers, TestParameters { using OrderStructs for OrderStructs.Maker; @@ -95,10 +95,8 @@ contract ProtocolHelpers is TestHelpers, TestParameters { function _signMakerOrder(OrderStructs.Maker memory maker, uint256 signerKey) internal view returns (bytes memory) { bytes32 orderHash = _computeOrderHash(maker); - (uint8 v, bytes32 r, bytes32 s) = vm.sign( - signerKey, - keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash)) - ); + (uint8 v, bytes32 r, bytes32 s) = + vm.sign(signerKey, keccak256(abi.encodePacked("\x19\x01", _domainSeparator, orderHash))); return abi.encodePacked(r, s, v); } diff --git a/contracts/test/foundry/marketplace/utils/StrategyTestMultiFillCollectionOrder.sol b/contracts/test/foundry/marketplace/utils/StrategyTestMultiFillCollectionOrder.sol index ea76b14c..80323455 100644 --- a/contracts/test/foundry/marketplace/utils/StrategyTestMultiFillCollectionOrder.sol +++ b/contracts/test/foundry/marketplace/utils/StrategyTestMultiFillCollectionOrder.sol @@ -2,16 +2,16 @@ pragma solidity 0.8.17; // Libraries -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; // Custom errors -import { OrderInvalid } from "@hypercerts/marketplace/errors/SharedErrors.sol"; +import {OrderInvalid} from "@hypercerts/marketplace/errors/SharedErrors.sol"; // Base strategy contracts -import { BaseStrategy, IStrategy } from "@hypercerts/marketplace/executionStrategies/BaseStrategy.sol"; +import {BaseStrategy, IStrategy} from "@hypercerts/marketplace/executionStrategies/BaseStrategy.sol"; // Enums -import { CollectionType } from "@hypercerts/marketplace/enums/CollectionType.sol"; +import {CollectionType} from "@hypercerts/marketplace/enums/CollectionType.sol"; contract StrategyTestMultiFillCollectionOrder is BaseStrategy { using OrderStructs for OrderStructs.Maker; @@ -35,10 +35,10 @@ contract StrategyTestMultiFillCollectionOrder is BaseStrategy { * @param takerAsk Taker ask struct (taker ask-specific parameters for the execution) * @param makerBid Maker bid struct (maker bid-specific parameters for the execution) */ - function executeStrategyWithTakerAsk( - OrderStructs.Taker calldata takerAsk, - OrderStructs.Maker calldata makerBid - ) external returns (uint256 price, uint256[] memory itemIds, uint256[] memory amounts, bool isNonceInvalidated) { + function executeStrategyWithTakerAsk(OrderStructs.Taker calldata takerAsk, OrderStructs.Maker calldata makerBid) + external + returns (uint256 price, uint256[] memory itemIds, uint256[] memory amounts, bool isNonceInvalidated) + { if (msg.sender != LOOKSRARE_PROTOCOL) revert OrderInvalid(); // Only available for ERC721 if (makerBid.collectionType != CollectionType.ERC721) revert OrderInvalid(); @@ -52,10 +52,8 @@ contract StrategyTestMultiFillCollectionOrder is BaseStrategy { uint256 countItemsToFill = amounts.length; if ( - countItemsToFill == 0 || - makerBid.amounts.length != 1 || - itemIds.length != countItemsToFill || - countItemsFillable < countItemsToFill + countItemsFilled + countItemsToFill == 0 || makerBid.amounts.length != 1 || itemIds.length != countItemsToFill + || countItemsFillable < countItemsToFill + countItemsFilled ) revert OrderInvalid(); price *= countItemsToFill; @@ -68,10 +66,12 @@ contract StrategyTestMultiFillCollectionOrder is BaseStrategy { } } - function isMakerOrderValid( - OrderStructs.Maker calldata, - bytes4 - ) external view override returns (bool isValid, bytes4 errorSelector) { + function isMakerOrderValid(OrderStructs.Maker calldata, bytes4) + external + view + override + returns (bool isValid, bytes4 errorSelector) + { // } } diff --git a/contracts/test/foundry/marketplace/utils/TestHelpers.sol b/contracts/test/foundry/marketplace/utils/TestHelpers.sol index 32f9b9b6..66270688 100644 --- a/contracts/test/foundry/marketplace/utils/TestHelpers.sol +++ b/contracts/test/foundry/marketplace/utils/TestHelpers.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { Test } from "forge-std/Test.sol"; -import { BytesLib } from "./BytesLib.sol"; +import {Test} from "forge-std/Test.sol"; +import {BytesLib} from "./BytesLib.sol"; abstract contract TestHelpers is Test { using BytesLib for bytes; diff --git a/contracts/test/foundry/marketplace/utils/TestParameters.sol b/contracts/test/foundry/marketplace/utils/TestParameters.sol index cb073095..44d29cf9 100644 --- a/contracts/test/foundry/marketplace/utils/TestParameters.sol +++ b/contracts/test/foundry/marketplace/utils/TestParameters.sol @@ -1,14 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import { Test } from "forge-std/Test.sol"; -import { OrderStructs } from "@hypercerts/marketplace/libraries/OrderStructs.sol"; +import {Test} from "forge-std/Test.sol"; +import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; abstract contract TestParameters is Test { // Empty constants OrderStructs.MerkleTree internal _EMPTY_MERKLE_TREE; bytes4 internal constant _EMPTY_BYTES4 = bytes4(0); - address internal constant _EMPTY_AFFILIATE = address(0); bytes32 public constant MAGIC_VALUE_ORDER_NONCE_EXECUTED = keccak256("ORDER_NONCE_EXECUTED"); // Addresses @@ -17,7 +16,6 @@ abstract contract TestParameters is Test { address internal constant _recipient = address(90); address internal constant _transferrer = address(100); address internal constant _royaltyRecipient = address(22); - address internal constant _affiliate = address(2); // Currencies address internal constant ETH = address(0); @@ -29,7 +27,7 @@ abstract contract TestParameters is Test { uint16 internal constant _maxProtocolFeeBp = uint16(200); uint16 internal constant _standardRoyaltyFee = uint16(0); - uint256 internal constant _sellerProceedBpWithStandardProtocolFeeBp = 9_950; + uint256 internal constant _sellerProceedBpWithStandardProtocolFeeBp = 9950; // Public/Private keys for maker/taker user uint256 internal constant makerUserPK = 1; @@ -40,15 +38,14 @@ abstract contract TestParameters is Test { address internal constant takerUser = 0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF; // Initial balances - // @dev The balances are on purpose different across users to make sure the tests are properly checking the assertion + // @dev The balances are on purpose different across users to make sure the tests are properly checking the + // assertion uint256 internal constant _initialETHBalanceUser = 100 ether; uint256 internal constant _initialWETHBalanceUser = 10 ether; uint256 internal constant _initialETHBalanceRoyaltyRecipient = 10 ether; uint256 internal constant _initialWETHBalanceRoyaltyRecipient = 25 ether; uint256 internal constant _initialETHBalanceOwner = 50 ether; uint256 internal constant _initialWETHBalanceOwner = 15 ether; - uint256 internal constant _initialETHBalanceAffiliate = 30 ether; - uint256 internal constant _initialWETHBalanceAffiliate = 12 ether; // Chainlink ETH/USD price feed (Ethereum mainnet) address internal constant CHAINLINK_ETH_USD_PRICE_FEED = 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419; diff --git a/contracts/test/foundry/protocol/AllowlistMinter.t.sol b/contracts/test/foundry/protocol/AllowlistMinter.t.sol index 8aecd6e7..a16c343c 100644 --- a/contracts/test/foundry/protocol/AllowlistMinter.t.sol +++ b/contracts/test/foundry/protocol/AllowlistMinter.t.sol @@ -1,20 +1,21 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; -import { AllowlistMinter } from "@hypercerts/protocol/AllowlistMinter.sol"; -import { Errors } from "@hypercerts/protocol/libs/Errors.sol"; +import {AllowlistMinter} from "@hypercerts/protocol/AllowlistMinter.sol"; +import {Errors} from "@hypercerts/protocol/libs/Errors.sol"; -import { Merkle } from "murky/Merkle.sol"; +import {Merkle} from "murky/Merkle.sol"; contract MerkleHelper is AllowlistMinter, Merkle { - function generateCustomData( - address[] calldata addresses, - uint256[] calldata units - ) public pure returns (bytes32[] memory data) { + function generateCustomData(address[] calldata addresses, uint256[] calldata units) + public + pure + returns (bytes32[] memory data) + { data = new bytes32[](addresses.length); for (uint256 i = 0; i < addresses.length; i++) { data[i] = _calculateLeaf(addresses[i], units[i]); @@ -39,7 +40,7 @@ contract MerkleHelper is AllowlistMinter, Merkle { function _getSum(uint256[] memory array) public pure returns (uint256 sum) { uint256 len = array.length; - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { sum += array[i]; unchecked { ++i; @@ -159,7 +160,7 @@ contract AllowlistTest is PRBTest, StdCheats, StdUtils { } function testBasicAllowlistFuzz(uint256 size) public { - size = bound(size, 4, 5_000); + size = bound(size, 4, 5000); uint256 units = 10_000; bytes32[] memory data = merkle.generateData(size, 10_000); bytes32 root = merkle.getRoot(data); @@ -173,7 +174,7 @@ contract AllowlistTest is PRBTest, StdCheats, StdUtils { } function testProcessClaimFuzz(uint256 size) public { - size = bound(size, 4, 5_000); + size = bound(size, 4, 5000); uint256 value = 10_000; bytes32[] memory data = merkle.generateData(size, value); bytes32 root = merkle.getRoot(data); diff --git a/contracts/test/foundry/protocol/Bitshifting.t.sol b/contracts/test/foundry/protocol/Bitshifting.t.sol index 68bc2cc8..6c4d9fe2 100644 --- a/contracts/test/foundry/protocol/Bitshifting.t.sol +++ b/contracts/test/foundry/protocol/Bitshifting.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; contract Bitshifter { /// @dev Bitmask used to expose only upper 128 bits of uint256 @@ -47,21 +47,24 @@ contract BitshiftingTest is PRBTest, StdCheats, StdUtils, Bitshifter { function testTypeMask() public { // 128 1s, 128 0s - assertEq(TYPE_MASK, 115792089237316195423570985008687907852929702298719625575994209400481361428480); + assertEq( + TYPE_MASK, + 115_792_089_237_316_195_423_570_985_008_687_907_852_929_702_298_719_625_575_994_209_400_481_361_428_480 + ); // 128 0s, 128 1s - assertEq(NF_INDEX_MASK, 340282366920938463463374607431768211455); + assertEq(NF_INDEX_MASK, 340_282_366_920_938_463_463_374_607_431_768_211_455); } function testBaseType() public { uint256 baseID = 1 << 128; uint256 baseType = getBaseType(baseID); assertEq(baseID, baseType); - assertEq(baseID, 340282366920938463463374607431768211456); + assertEq(baseID, 340_282_366_920_938_463_463_374_607_431_768_211_456); assertTrue(isBaseType(baseID)); assertEq(getItemIndex(baseID), 0); - assertEq(getBaseType(baseID), 340282366920938463463374607431768211456); + assertEq(getBaseType(baseID), 340_282_366_920_938_463_463_374_607_431_768_211_456); assertFalse(isTypedItem(baseID)); } diff --git a/contracts/test/foundry/protocol/HypercertMinter.batchminting.t.sol b/contracts/test/foundry/protocol/HypercertMinter.batchminting.t.sol index d58f0276..3f8502d6 100644 --- a/contracts/test/foundry/protocol/HypercertMinter.batchminting.t.sol +++ b/contracts/test/foundry/protocol/HypercertMinter.batchminting.t.sol @@ -1,14 +1,15 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {HypercertMinter} from "@hypercerts/protocol/HypercertMinter.sol"; //solhint-disable-next-line max-line-length -import { ERC1155HolderUpgradeable } from "openzeppelin-contracts-upgradeable/contracts/token/ERC1155/utils/ERC1155HolderUpgradeable.sol"; -import { Merkle } from "murky/Merkle.sol"; -import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; +import {ERC1155HolderUpgradeable} from + "openzeppelin-contracts-upgradeable/contracts/token/ERC1155/utils/ERC1155HolderUpgradeable.sol"; +import {Merkle} from "murky/Merkle.sol"; +import {IHypercertToken} from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; contract BatchMintingHelper is Merkle, ERC1155HolderUpgradeable { event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values); @@ -20,10 +21,11 @@ contract BatchMintingHelper is Merkle, ERC1155HolderUpgradeable { bytes32 root; } - function generateCustomData( - address[] memory addresses, - uint256[] memory units - ) public pure returns (bytes32[] memory data) { + function generateCustomData(address[] memory addresses, uint256[] memory units) + public + pure + returns (bytes32[] memory data) + { data = new bytes32[](addresses.length); for (uint256 i = 0; i < addresses.length; i++) { data[i] = _calculateLeaf(addresses[i], units[i]); @@ -62,7 +64,7 @@ contract BatchMintingHelper is Merkle, ERC1155HolderUpgradeable { function _getSum(uint256[] memory array) public pure returns (uint256 sum) { uint256 len = array.length; - for (uint256 i; i < len; ) { + for (uint256 i; i < len;) { sum += array[i]; unchecked { ++i; @@ -107,7 +109,7 @@ contract HypercertBatchMintingTest is PRBTest, StdCheats, StdUtils, BatchMinting proofs[i] = getProof(dataset.data, index); ids[i] = (i + 1) << 128; units[i] = dataset.units[index]; - minter.createAllowlist(user, 10000, dataset.root, _uri, IHypercertToken.TransferRestrictions.AllowAll); + minter.createAllowlist(user, 10_000, dataset.root, _uri, IHypercertToken.TransferRestrictions.AllowAll); } units[3] = 0; @@ -151,8 +153,8 @@ contract HypercertBatchMintingTest is PRBTest, StdCheats, StdUtils, BatchMinting uint256[] memory zeroes = new uint256[](2); - minter.createAllowlist(user, 10000, one.root, _uri, IHypercertToken.TransferRestrictions.AllowAll); - minter.createAllowlist(user, 10000, two.root, _uri, IHypercertToken.TransferRestrictions.AllowAll); + minter.createAllowlist(user, 10_000, one.root, _uri, IHypercertToken.TransferRestrictions.AllowAll); + minter.createAllowlist(user, 10_000, two.root, _uri, IHypercertToken.TransferRestrictions.AllowAll); startHoax(user, 10 ether); @@ -179,7 +181,7 @@ contract HypercertBatchMintingTest is PRBTest, StdCheats, StdUtils, BatchMinting ids[i] = (i + 1) << 128; tokenIDs[i] = ids[i] + 1; units[i] = dataset.units[index]; - minter.createAllowlist(user, 10000, dataset.root, _uri, IHypercertToken.TransferRestrictions.AllowAll); + minter.createAllowlist(user, 10_000, dataset.root, _uri, IHypercertToken.TransferRestrictions.AllowAll); } startHoax(user, 10 ether); @@ -215,11 +217,7 @@ contract HypercertBatchMintingTest is PRBTest, StdCheats, StdUtils, BatchMinting tokenIDs[i] = ids[i] + 1; units[i] = dataset.units[index]; minter.createAllowlist( - user, - _getSum(units), - dataset.root, - _uri, - IHypercertToken.TransferRestrictions.AllowAll + user, _getSum(units), dataset.root, _uri, IHypercertToken.TransferRestrictions.AllowAll ); } @@ -254,7 +252,7 @@ contract HypercertBatchMintingTest is PRBTest, StdCheats, StdUtils, BatchMinting ids[i] = (i + 1) << 128; tokenIDs[i] = ids[i] + 1; units[i] = dataset.units[index]; - minter.createAllowlist(user, 10000, dataset.root, _uri, IHypercertToken.TransferRestrictions.DisallowAll); + minter.createAllowlist(user, 10_000, dataset.root, _uri, IHypercertToken.TransferRestrictions.DisallowAll); } startHoax(user, 10 ether); @@ -289,11 +287,7 @@ contract HypercertBatchMintingTest is PRBTest, StdCheats, StdUtils, BatchMinting tokenIDs[i] = ids[i] + 1; units[i] = dataset.units[index]; minter.createAllowlist( - user, - 10000, - dataset.root, - _uri, - IHypercertToken.TransferRestrictions.FromCreatorOnly + user, 10_000, dataset.root, _uri, IHypercertToken.TransferRestrictions.FromCreatorOnly ); } diff --git a/contracts/test/foundry/protocol/HypercertMinter.pausable.t.sol b/contracts/test/foundry/protocol/HypercertMinter.pausable.t.sol index ae849161..a4b63061 100644 --- a/contracts/test/foundry/protocol/HypercertMinter.pausable.t.sol +++ b/contracts/test/foundry/protocol/HypercertMinter.pausable.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; -import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {HypercertMinter} from "@hypercerts/protocol/HypercertMinter.sol"; +import {IHypercertToken} from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; contract PausableTestHelper { /** @@ -86,13 +86,7 @@ contract HypercertMinterPausableTest is PRBTest, StdCheats, StdUtils, PausableTe hypercertMinter.mintClaim(owner, 1, _uri, IHypercertToken.TransferRestrictions.AllowAll); vm.expectRevert("Pausable: paused"); - hypercertMinter.mintClaimWithFractions( - owner, - 1, - fractions, - _uri, - IHypercertToken.TransferRestrictions.AllowAll - ); + hypercertMinter.mintClaimWithFractions(owner, 1, fractions, _uri, IHypercertToken.TransferRestrictions.AllowAll); vm.expectRevert("Pausable: paused"); hypercertMinter.mintClaimFromAllowlist(owner, proofs, 2, 1000); diff --git a/contracts/test/foundry/protocol/HypercertMinter.t.sol b/contracts/test/foundry/protocol/HypercertMinter.t.sol index 86364b56..86bbe1d5 100644 --- a/contracts/test/foundry/protocol/HypercertMinter.t.sol +++ b/contracts/test/foundry/protocol/HypercertMinter.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { Merkle } from "murky/Merkle.sol"; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; -import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {Merkle} from "murky/Merkle.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {HypercertMinter} from "@hypercerts/protocol/HypercertMinter.sol"; +import {IHypercertToken} from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; contract MinterTestHelper { event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits); @@ -78,7 +78,7 @@ contract HypercertMinterTest is PRBTest, StdCheats, StdUtils, MinterTestHelper { } function testClaimSingleFraction() public { - uint256 units = 10000; + uint256 units = 10_000; vm.expectEmit(true, true, true, true); emit ClaimStored(1 << 128, _uri, units); @@ -91,11 +91,7 @@ contract HypercertMinterTest is PRBTest, StdCheats, StdUtils, MinterTestHelper { vm.expectEmit(true, true, true, true); emit ClaimStored(1 << 128, _uri, totalUnits); hypercertMinter.mintClaimWithFractions( - alice, - totalUnits, - fractions, - _uri, - IHypercertToken.TransferRestrictions.AllowAll + alice, totalUnits, fractions, _uri, IHypercertToken.TransferRestrictions.AllowAll ); } @@ -106,11 +102,7 @@ contract HypercertMinterTest is PRBTest, StdCheats, StdUtils, MinterTestHelper { vm.expectEmit(true, true, true, true); emit ClaimStored(1 << 128, _uri, totalUnits); hypercertMinter.mintClaimWithFractions( - alice, - totalUnits, - fractions, - _uri, - IHypercertToken.TransferRestrictions.AllowAll + alice, totalUnits, fractions, _uri, IHypercertToken.TransferRestrictions.AllowAll ); } @@ -120,11 +112,7 @@ contract HypercertMinterTest is PRBTest, StdCheats, StdUtils, MinterTestHelper { vm.expectEmit(true, true, true, true); emit ClaimStored(1 << 128, _uri, totalUnits); hypercertMinter.mintClaimWithFractions( - alice, - totalUnits, - fractions, - _uri, - IHypercertToken.TransferRestrictions.DisallowAll + alice, totalUnits, fractions, _uri, IHypercertToken.TransferRestrictions.DisallowAll ); } @@ -134,11 +122,7 @@ contract HypercertMinterTest is PRBTest, StdCheats, StdUtils, MinterTestHelper { vm.expectEmit(true, true, true, true); emit ClaimStored(1 << 128, _uri, totalUnits); hypercertMinter.mintClaimWithFractions( - alice, - totalUnits, - fractions, - _uri, - IHypercertToken.TransferRestrictions.FromCreatorOnly + alice, totalUnits, fractions, _uri, IHypercertToken.TransferRestrictions.FromCreatorOnly ); } } diff --git a/contracts/test/foundry/protocol/HypercertMinter.transfers.t.sol b/contracts/test/foundry/protocol/HypercertMinter.transfers.t.sol index f4b3ff9b..cd2f1773 100644 --- a/contracts/test/foundry/protocol/HypercertMinter.transfers.t.sol +++ b/contracts/test/foundry/protocol/HypercertMinter.transfers.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { Errors } from "@hypercerts/protocol/libs/Errors.sol"; -import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; -import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {Errors} from "@hypercerts/protocol/libs/Errors.sol"; +import {HypercertMinter} from "@hypercerts/protocol/HypercertMinter.sol"; +import {IHypercertToken} from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; /// @dev Testing transfer restrictions on hypercerts contract HypercertMinterTransferTest is PRBTest, StdCheats, StdUtils { @@ -22,7 +22,7 @@ contract HypercertMinterTransferTest is PRBTest, StdCheats, StdUtils { function setUp() public { hypercertMinter = new HypercertMinter(); _uri = "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi"; - _units = 10000; + _units = 10_000; baseID = 1 << 128; tokenIndex = 1; tokenID = baseID + tokenIndex; diff --git a/contracts/test/foundry/protocol/PerformanceTesting.t.sol b/contracts/test/foundry/protocol/PerformanceTesting.t.sol index 7b2a71d3..956fd3bb 100644 --- a/contracts/test/foundry/protocol/PerformanceTesting.t.sol +++ b/contracts/test/foundry/protocol/PerformanceTesting.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { HypercertMinter } from "@hypercerts/protocol/HypercertMinter.sol"; -import { Merkle } from "murky/Merkle.sol"; -import { IHypercertToken } from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {HypercertMinter} from "@hypercerts/protocol/HypercertMinter.sol"; +import {Merkle} from "murky/Merkle.sol"; +import {IHypercertToken} from "@hypercerts/protocol/interfaces/IHypercertToken.sol"; // forge test -vv --match-path test/foundry/PerformanceTesting.t.sol @@ -78,10 +78,11 @@ contract PerformanceTestHelper is Merkle { leaf = keccak256(bytes.concat(keccak256(abi.encode(account, amount)))); } - function generateCustomData( - address[] memory addresses, - uint256[] memory units - ) public pure returns (bytes32[] memory data) { + function generateCustomData(address[] memory addresses, uint256[] memory units) + public + pure + returns (bytes32[] memory data) + { data = new bytes32[](addresses.length); for (uint256 i = 0; i < addresses.length; i++) { data[i] = _calculateLeaf(addresses[i], units[i]); @@ -129,7 +130,7 @@ contract PerformanceTesting is PRBTest, StdCheats, StdUtils, PerformanceTestHelp function setUp() public { alice = address(1); hypercertMinter = new HypercertMinter(); - bytes32[] memory data = generateData(12, 10000); + bytes32[] memory data = generateData(12, 10_000); rootHash = getRoot(data); proof = getProof(data, 6); @@ -149,11 +150,7 @@ contract PerformanceTesting is PRBTest, StdCheats, StdUtils, PerformanceTestHelp ids[i] = (i + 1) << 128; units[i] = dataset.units[index]; hypercertMinter.createAllowlist( - alice, - dataset.units[index], - dataset.root, - _uri, - IHypercertToken.TransferRestrictions.AllowAll + alice, dataset.units[index], dataset.root, _uri, IHypercertToken.TransferRestrictions.AllowAll ); } } @@ -170,7 +167,7 @@ contract PerformanceTesting is PRBTest, StdCheats, StdUtils, PerformanceTestHelp // Mint Hypercert with 1 fraction function testClaimSingleFraction() public { - hypercertMinter.mintClaim(alice, 10000, _uri, IHypercertToken.TransferRestrictions.AllowAll); + hypercertMinter.mintClaim(alice, 10_000, _uri, IHypercertToken.TransferRestrictions.AllowAll); } function testClaimSingleFractionFuzz(address account, uint256 value) public { @@ -188,11 +185,7 @@ contract PerformanceTesting is PRBTest, StdCheats, StdUtils, PerformanceTestHelp uint256 totalUnits = getSum(fractions); hypercertMinter.mintClaimWithFractions( - alice, - totalUnits, - fractions, - _uri, - IHypercertToken.TransferRestrictions.AllowAll + alice, totalUnits, fractions, _uri, IHypercertToken.TransferRestrictions.AllowAll ); } @@ -201,11 +194,7 @@ contract PerformanceTesting is PRBTest, StdCheats, StdUtils, PerformanceTestHelp uint256 totalUnits = getSum(fractions); hypercertMinter.mintClaimWithFractions( - alice, - totalUnits, - fractions, - _uri, - IHypercertToken.TransferRestrictions.AllowAll + alice, totalUnits, fractions, _uri, IHypercertToken.TransferRestrictions.AllowAll ); } @@ -215,11 +204,7 @@ contract PerformanceTesting is PRBTest, StdCheats, StdUtils, PerformanceTestHelp uint256 totalUnits = getSum(fractions); hypercertMinter.mintClaimWithFractions( - alice, - totalUnits, - fractions, - "https://example.com/ipfsHash", - IHypercertToken.TransferRestrictions.AllowAll + alice, totalUnits, fractions, "https://example.com/ipfsHash", IHypercertToken.TransferRestrictions.AllowAll ); } diff --git a/contracts/test/foundry/protocol/SemiFungible1155.allowances.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.allowances.t.sol index 438b1893..efe78bef 100644 --- a/contracts/test/foundry/protocol/SemiFungible1155.allowances.t.sol +++ b/contracts/test/foundry/protocol/SemiFungible1155.allowances.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { SemiFungible1155Helper } from "./SemiFungibleHelper.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {SemiFungible1155Helper} from "./SemiFungibleHelper.sol"; /// @dev See the "Writing Tests" section in the Foundry Book if this is your first time with Forge. /// https://book.getfoundry.sh/forge/writing-tests diff --git a/contracts/test/foundry/protocol/SemiFungible1155.burning.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.burning.t.sol index a5db0bd6..1e3c21a4 100644 --- a/contracts/test/foundry/protocol/SemiFungible1155.burning.t.sol +++ b/contracts/test/foundry/protocol/SemiFungible1155.burning.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.16; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { SemiFungible1155Helper } from "./SemiFungibleHelper.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {SemiFungible1155Helper} from "./SemiFungibleHelper.sol"; /// @dev See the "Writing Tests" section in the Foundry Book if this is your first time with Forge. /// https://book.getfoundry.sh/forge/writing-tests diff --git a/contracts/test/foundry/protocol/SemiFungible1155.minting.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.minting.t.sol index ae7f78d6..9458a8cc 100644 --- a/contracts/test/foundry/protocol/SemiFungible1155.minting.t.sol +++ b/contracts/test/foundry/protocol/SemiFungible1155.minting.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { stdError } from "forge-std/StdError.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { SemiFungible1155Helper } from "./SemiFungibleHelper.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {stdError} from "forge-std/StdError.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {SemiFungible1155Helper} from "./SemiFungibleHelper.sol"; /// @dev See the "Writing Tests" section in the Foundry Book if this is your first time with Forge. /// https://book.getfoundry.sh/forge/writing-tests @@ -64,7 +64,7 @@ contract SemiFungible1155MintingTest is PRBTest, StdCheats, StdUtils, SemiFungib semiFungible.setMaxType(); vm.expectRevert(stdError.arithmeticError); - semiFungible.mintValue(alice, 10000, _uri); + semiFungible.mintValue(alice, 10_000, _uri); } // HAPPY MINTING @@ -81,17 +81,17 @@ contract SemiFungible1155MintingTest is PRBTest, StdCheats, StdUtils, SemiFungib // uint256 value vm.expectEmit(true, true, true, true); emit TransferSingle(alice, address(0), address(0), _baseID, 0); - uint256 baseID = semiFungible.mintValue(alice, 10000, _uri); + uint256 baseID = semiFungible.mintValue(alice, 10_000, _uri); assertEq(baseID, _baseID); assertEq(semiFungible.ownerOf(baseID), address(0)); assertEq(semiFungible.creator(baseID), alice); - assertEq(semiFungible.unitsOf(baseID), 10000); + assertEq(semiFungible.unitsOf(baseID), 10_000); - semiFungible.validateOwnerBalanceUnits(baseID + 1, alice, 1, 10000); + semiFungible.validateOwnerBalanceUnits(baseID + 1, alice, 1, 10_000); - assertEq(semiFungible.tokenValue(baseID), 10000); - assertEq(semiFungible.tokenValue(baseID + 1), 10000); + assertEq(semiFungible.tokenValue(baseID), 10_000); + assertEq(semiFungible.tokenValue(baseID + 1), 10_000); assertEq(semiFungible.tokenValue(baseID + 2), 0); } @@ -123,7 +123,7 @@ contract SemiFungible1155MintingTest is PRBTest, StdCheats, StdUtils, SemiFungib values[2] = 5000; uint256 baseID = semiFungible.mintValue(alice, values, _uri); - assertEq(semiFungible.unitsOf(baseID), 15000); + assertEq(semiFungible.unitsOf(baseID), 15_000); assertEq(semiFungible.ownerOf(baseID), address(0)); // Swap because of splitting logic diff --git a/contracts/test/foundry/protocol/SemiFungible1155.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.t.sol index 09918e69..ea5746c1 100644 --- a/contracts/test/foundry/protocol/SemiFungible1155.t.sol +++ b/contracts/test/foundry/protocol/SemiFungible1155.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { SemiFungible1155Helper } from "./SemiFungibleHelper.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {SemiFungible1155Helper} from "./SemiFungibleHelper.sol"; /// @dev See the "Writing Tests" section in the Foundry Book if this is your first time with Forge. /// https://book.getfoundry.sh/forge/writing-tests @@ -35,16 +35,16 @@ contract SemiFungible1155DefaultTest is PRBTest, StdCheats, StdUtils, SemiFungib startHoax(alice, 100 ether); - semiFungible.mintValue(alice, 10000, _uri); + semiFungible.mintValue(alice, 10_000, _uri); semiFungible.splitValue(alice, tokenID, values); - assertEq(semiFungible.unitsOf(baseID), 10000); + assertEq(semiFungible.unitsOf(baseID), 10_000); semiFungible.validateOwnerBalanceUnits(tokenID, alice, 1, values[0]); semiFungible.validateOwnerBalanceUnits(tokenID + 1, alice, 1, values[1]); // Units - assertEq(semiFungible.unitsOf(baseID), 10000); + assertEq(semiFungible.unitsOf(baseID), 10_000); assertEq(semiFungible.unitsOf(tokenID), 7000); assertEq(semiFungible.unitsOf(tokenID + 1), 3000); } diff --git a/contracts/test/foundry/protocol/SemiFungible1155.transfers.t.sol b/contracts/test/foundry/protocol/SemiFungible1155.transfers.t.sol index 5a910740..bcad3900 100644 --- a/contracts/test/foundry/protocol/SemiFungible1155.transfers.t.sol +++ b/contracts/test/foundry/protocol/SemiFungible1155.transfers.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { SemiFungible1155Helper } from "./SemiFungibleHelper.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {SemiFungible1155Helper} from "./SemiFungibleHelper.sol"; /// @dev See the "Writing Tests" section in the Foundry Book if this is your first time with Forge. /// https://book.getfoundry.sh/forge/writing-tests @@ -24,14 +24,14 @@ contract SemiFungible1155TransferTest is PRBTest, StdCheats, StdUtils { // UNHAPPY PATHS function testFailTransferTypeIDToken() public { - semiFungible.mintValue(alice, 10000, _uri); + semiFungible.mintValue(alice, 10_000, _uri); //NotApprovedOrOWner, since no owner semiFungible.safeTransferFrom(alice, bob, 1 << 128, 1, ""); } function testFailTransferNonExistingFractionToken() public { - semiFungible.mintValue(alice, 10000, _uri); + semiFungible.mintValue(alice, 10_000, _uri); //NotApprovedOrOWner, since no owner semiFungible.safeTransferFrom(alice, bob, 1 << (128 + 2), 1, ""); @@ -59,10 +59,10 @@ contract SemiFungible1155TransferTest is PRBTest, StdCheats, StdUtils { uint256 baseID = 1 << 128; uint128 tokenID = 1; - semiFungible.mintValue(alice, 10000, _uri); + semiFungible.mintValue(alice, 10_000, _uri); assertEq(semiFungible.balanceOf(alice, baseID), 0); - semiFungible.validateOwnerBalanceUnits(baseID + tokenID, alice, 1, 10000); + semiFungible.validateOwnerBalanceUnits(baseID + tokenID, alice, 1, 10_000); assertEq(semiFungible.balanceOf(bob, baseID), 0); semiFungible.validateNotOwnerNoBalanceNoUnits(baseID + tokenID, bob); @@ -78,7 +78,7 @@ contract SemiFungible1155TransferTest is PRBTest, StdCheats, StdUtils { semiFungible.validateNotOwnerNoBalanceNoUnits(baseID + tokenID, alice); // Updates token ownership - semiFungible.validateOwnerBalanceUnits(baseID + tokenID, bob, 1, 10000); + semiFungible.validateOwnerBalanceUnits(baseID + tokenID, bob, 1, 10_000); } function testFuzzTransferFullToken(address from, address to, uint256 units) public { diff --git a/contracts/test/foundry/protocol/SemiFungible1155.units.sol b/contracts/test/foundry/protocol/SemiFungible1155.units.sol index 654c1dbb..384bcdfb 100644 --- a/contracts/test/foundry/protocol/SemiFungible1155.units.sol +++ b/contracts/test/foundry/protocol/SemiFungible1155.units.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; -import { SemiFungible1155Helper } from "./SemiFungibleHelper.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {SemiFungible1155Helper} from "./SemiFungibleHelper.sol"; /// @dev See the "Writing Tests" section in the Foundry Book if this is your first time with Forge. /// https://book.getfoundry.sh/forge/writing-tests @@ -28,11 +28,11 @@ contract SemiFungible1155UnitsTest is PRBTest, StdCheats, StdUtils { uint256 baseID = 1 << 128; uint128 tokenID = 1; - semiFungible.mintValue(alice, 10000, _uri); + semiFungible.mintValue(alice, 10_000, _uri); assertEq(semiFungible.unitsOf(baseID), 10_000); - semiFungible.validateOwnerBalanceUnits(baseID + tokenID, alice, 1, 10000); + semiFungible.validateOwnerBalanceUnits(baseID + tokenID, alice, 1, 10_000); semiFungible.validateNotOwnerNoBalanceNoUnits(baseID + tokenID, bob); @@ -51,7 +51,7 @@ contract SemiFungible1155UnitsTest is PRBTest, StdCheats, StdUtils { semiFungible.validateNotOwnerNoBalanceNoUnits(baseID + tokenID, alice); assertEq(semiFungible.balanceOf(bob, baseID), 0); - semiFungible.validateOwnerBalanceUnits(baseID + tokenID, bob, 1, 10000); + semiFungible.validateOwnerBalanceUnits(baseID + tokenID, bob, 1, 10_000); } function testUnitsMultipleFractions() public { diff --git a/contracts/test/foundry/protocol/SemiFungibleHelper.sol b/contracts/test/foundry/protocol/SemiFungibleHelper.sol index 7555bc9d..82a1c264 100644 --- a/contracts/test/foundry/protocol/SemiFungibleHelper.sol +++ b/contracts/test/foundry/protocol/SemiFungibleHelper.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.16; -import { SemiFungible1155 } from "@hypercerts/protocol/SemiFungible1155.sol"; -import { PRBTest } from "prb-test/PRBTest.sol"; -import { StdCheats } from "forge-std/StdCheats.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; +import {SemiFungible1155} from "@hypercerts/protocol/SemiFungible1155.sol"; +import {PRBTest} from "prb-test/PRBTest.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; contract SemiFungible1155Helper is SemiFungible1155, PRBTest, StdCheats, StdUtils { error FractionalBurn(); diff --git a/docs/docs/developer/api/contracts/HypercertMinter.md b/docs/docs/developer/api/contracts/HypercertMinter.md index 012e3d60..518efa42 100644 --- a/docs/docs/developer/api/contracts/HypercertMinter.md +++ b/docs/docs/developer/api/contracts/HypercertMinter.md @@ -99,7 +99,7 @@ _Calls AllowlistMinter to verify `proofs`.Mints the `amount` of units for the hy ### burn ```solidity -function burn(address account, uint256 id, uint256 value) external nonpayable +function burn(address account, uint256 id, uint256) external nonpayable ``` Burn a claimtoken; override is needed to update units/values @@ -112,12 +112,12 @@ _see {ERC1155Burnable}_ | ------- | ------- | ----------- | | account | address | undefined | | id | uint256 | undefined | -| value | uint256 | undefined | +| \_2 | uint256 | undefined | ### burnBatch ```solidity -function burnBatch(address account, uint256[] ids, uint256[] values) external nonpayable +function burnBatch(address account, uint256[] ids, uint256[]) external nonpayable ``` Batch burn claimtokens; override is needed to update units/values @@ -130,7 +130,7 @@ _see {ERC1155Burnable}_ | ------- | --------- | ----------- | | account | address | undefined | | ids | uint256[] | undefined | -| values | uint256[] | undefined | +| \_2 | uint256[] | undefined | ### burnFraction diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 988958cc..a353eed7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -195,9 +195,6 @@ importers: solhint-plugin-prettier: specifier: ^0.0.5 version: 0.0.5(prettier-plugin-solidity@1.1.3)(prettier@2.8.8) - solidity-coverage: - specifier: ^0.8.2 - version: 0.8.5(hardhat@2.13.1) solmate: specifier: ^6.2.0 version: 6.2.0 From d48f2baba88f9e7f05e3f1fd3765583da9190bad Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Fri, 27 Oct 2023 23:34:21 +0200 Subject: [PATCH 16/49] chore(license): dual licensing contracts + repo (#1141) --- LICENSE | 203 +------------------------- LICENSE-APACHE | 13 ++ LICENSE-MIT | 21 +++ contracts/LICENSE | 4 + contracts/LICENSE-APACHE | 10 ++ contracts/{LICENSE.md => LICENSE-MIT} | 4 +- 6 files changed, 53 insertions(+), 202 deletions(-) create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 contracts/LICENSE create mode 100644 contracts/LICENSE-APACHE rename contracts/{LICENSE.md => LICENSE-MIT} (100%) diff --git a/LICENSE b/LICENSE index 261eeb9e..dba11665 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,4 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +This project is dual licensed under MIT and Apache-2.0. - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 \ No newline at end of file diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 00000000..103c2143 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,13 @@ +Copyright 2023 Hypercerts Foundation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 00000000..d67b8580 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright © 2023 Hypercerts Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/contracts/LICENSE b/contracts/LICENSE new file mode 100644 index 00000000..dba11665 --- /dev/null +++ b/contracts/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 \ No newline at end of file diff --git a/contracts/LICENSE-APACHE b/contracts/LICENSE-APACHE new file mode 100644 index 00000000..d4cc5a41 --- /dev/null +++ b/contracts/LICENSE-APACHE @@ -0,0 +1,10 @@ +Copyright 2023 Hypercerts Foundation + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific +language governing permissions and limitations under the License. diff --git a/contracts/LICENSE.md b/contracts/LICENSE-MIT similarity index 100% rename from contracts/LICENSE.md rename to contracts/LICENSE-MIT index 1234b4cf..4e9e555e 100644 --- a/contracts/LICENSE.md +++ b/contracts/LICENSE-MIT @@ -1,11 +1,11 @@ MIT License -Copyright (c) 2022 Paul Razvan Berg for inital template: /~https://github.com/paulrberg/foundry-template +Copyright (c) 2022 Hypercerts Foundation: Hypercerts protocol and marketplace. Copyright (c) 2022 LooksRare for portions of marketplace: /~https://github.com/LooksRare/contracts-exchange-v2 commit: 7fca565 -Copyright (c) 2022 Hypercerts Foundation: Hypercerts protocol and marketplace. +Copyright (c) 2022 Paul Razvan Berg for inital template: /~https://github.com/paulrberg/foundry-template Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the From 5971ab1aa1fded70ad05730f2adacf4cdcbede93 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 30 Oct 2023 23:38:41 +0100 Subject: [PATCH 17/49] feat(config): updated sdk init config --- sdk/src/client.ts | 62 ++-- sdk/src/constants.ts | 7 +- sdk/src/evaluations/eas.ts | 6 +- sdk/src/evaluations/index.ts | 10 +- sdk/src/index.ts | 12 +- sdk/src/indexer.ts | 4 +- sdk/src/storage.ts | 11 +- sdk/src/types/client.ts | 29 +- sdk/src/types/index.ts | 16 +- sdk/src/utils/config.ts | 334 ++++++++++++---------- sdk/src/utils/errors.ts | 2 +- sdk/src/utils/formatter.ts | 4 +- sdk/src/utils/resolvers.ts | 2 +- sdk/src/validator/index.ts | 4 +- sdk/test/client.test.ts | 14 +- sdk/test/client/allowlist.minting.test.ts | 28 +- sdk/test/client/burn.test.ts | 51 ++-- sdk/test/client/minting.test.ts | 11 +- sdk/test/client/split.merge.test.ts | 151 ++++++---- sdk/test/utils/config.test.ts | 56 ++-- sdk/tsconfig.json | 2 +- 21 files changed, 458 insertions(+), 358 deletions(-) diff --git a/sdk/src/client.ts b/sdk/src/client.ts index 6163bf03..350f01a4 100644 --- a/sdk/src/client.ts +++ b/sdk/src/client.ts @@ -2,10 +2,9 @@ import { HypercertMinter, HypercertMinterAbi } from "@hypercerts-org/contracts"; import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; import { BigNumber, BigNumberish, BytesLike, ContractTransaction, ethers, providers } from "ethers"; -import { DEFAULT_CHAIN_ID } from "./constants.js"; -import HypercertEvaluator from "./evaluations/index.js"; -import HypercertIndexer from "./indexer.js"; -import HypercertsStorage from "./storage.js"; +import HypercertEvaluator from "./evaluations"; +import HypercertIndexer from "./indexer"; +import HypercertsStorage from "./storage"; import { AllowlistEntry, ClientError, @@ -15,10 +14,11 @@ import { InvalidOrMissingError, MalformedDataError, TransferRestrictions, -} from "./types/index.js"; -import { getConfig } from "./utils/config.js"; -import logger from "./utils/logger.js"; -import { validateAllowlist, validateMetaData, verifyMerkleProof, verifyMerkleProofs } from "./validator/index.js"; + Operator, +} from "./types/index"; +import { getWritableConfig, getReadOnlyConfig } from "./utils/config"; +import logger from "./utils/logger"; +import { validateAllowlist, validateMetaData, verifyMerkleProof, verifyMerkleProofs } from "./validator"; /** * Hypercerts client factory @@ -28,12 +28,12 @@ import { validateAllowlist, validateMetaData, verifyMerkleProof, verifyMerklePro * @param storage - Hypercerts storage object */ export default class HypercertClient implements HypercertClientInterface { - readonly _config: HypercertClientConfig; + private _config: HypercertClientConfig; private _storage: HypercertsStorage; - private _evaluator: HypercertEvaluator; + // TODO better handling readonly. For now not needed since we don't use this class; + private _evaluator: HypercertEvaluator | undefined; private _indexer: HypercertIndexer; //TODO added the TypedDataSigner since that's needed for EAS signing. Will this work on front-end? - private _operator: ethers.providers.Provider | ethers.Signer; private _contract: HypercertMinter; readonly: boolean; @@ -41,31 +41,45 @@ export default class HypercertClient implements HypercertClientInterface { * Creates a new instance of the `HypercertClient` class. * @param config The configuration options for the client. */ - constructor(config = { chainId: DEFAULT_CHAIN_ID } as Partial) { - this._config = getConfig(config); - this._operator = this._config.operator; - - this._contract = ( - new ethers.Contract(this._config.contractAddress, HypercertMinterAbi, this._operator) - ); + constructor(config: Partial) { + this._config = getReadOnlyConfig(config); this._storage = new HypercertsStorage(this._config); this._indexer = new HypercertIndexer(this._config); - this._evaluator = new HypercertEvaluator(this._config); + this.readonly = this._config.readOnly || !this._config.contractAddress || this._storage.readonly; - this.readonly = - providers.Provider.isProvider(this._operator) || - !ethers.Signer.isSigner(this._operator) || - !this._config.contractAddress || - this._storage.readonly; + this._contract = new ethers.Contract(this._config.contractAddress, HypercertMinterAbi); if (this.readonly) { logger.warn("HypercertsClient is in readonly mode", "client"); } } + /** + * Connect the client to an operator. + * @param operator The operator to connect to. + */ + connect = async (operator: Operator) => { + this._config = await getWritableConfig({ ...this._config, operator: operator }); + + this._indexer = new HypercertIndexer(this._config); + + this._evaluator = new HypercertEvaluator(this._config); + + this._contract = this._contract?.connect(operator); + + this.readonly = this._config.readOnly || this._storage.readonly || !this._contract; + + if (this.readonly) { + logger.warn("HypercertsClient is in readonly mode", "client"); + logger.warn(this._config.readOnlyReason ?? "No reason provided", "client"); + } + + return this; + }; + /** * Gets the config for the client. * @returns The client config. diff --git a/sdk/src/constants.ts b/sdk/src/constants.ts index da4383b5..81ee5ff6 100644 --- a/sdk/src/constants.ts +++ b/sdk/src/constants.ts @@ -2,10 +2,7 @@ * Constants */ -import { Deployment, SupportedChainIds } from "./types/index.js"; - -// Goerli is default if nothing specified -const DEFAULT_CHAIN_ID = 5; +import { Deployment, SupportedChainIds } from "./types"; const DEFAULT_GRAPH_BASE_URL = "https://api.thegraph.com/subgraphs/name/hypercerts-admin"; @@ -52,4 +49,4 @@ const EAS_SCHEMAS = { }, } as const; -export { DEFAULT_CHAIN_ID, DEPLOYMENTS, EAS_SCHEMAS }; +export { DEPLOYMENTS, EAS_SCHEMAS }; diff --git a/sdk/src/evaluations/eas.ts b/sdk/src/evaluations/eas.ts index 3a7923b1..42d2cdc4 100644 --- a/sdk/src/evaluations/eas.ts +++ b/sdk/src/evaluations/eas.ts @@ -2,7 +2,7 @@ import { Offchain, SchemaEncoder, SignedOffchainAttestation } from "@ethereum-at import { TypedDataSigner } from "@ethersproject/abstract-signer"; import { ethers } from "ethers"; -import { EAS_SCHEMAS } from "../constants.js"; +import { EAS_SCHEMAS } from "../constants"; import { DuplicateEvaluation, EvaluationData, @@ -10,8 +10,8 @@ import { InvalidOrMissingError, MalformedDataError, SimpleTextEvaluation, -} from "../types/index.js"; -import { validateDuplicateEvaluationData, validateSimpleTextEvaluationData } from "../validator/index.js"; +} from "../types"; +import { validateDuplicateEvaluationData, validateSimpleTextEvaluationData } from "../validator"; /** * The EasEvaluator class provides methods for signing off-chain attestations of evaluations. diff --git a/sdk/src/evaluations/index.ts b/sdk/src/evaluations/index.ts index 9092b0b7..968b051f 100644 --- a/sdk/src/evaluations/index.ts +++ b/sdk/src/evaluations/index.ts @@ -1,18 +1,17 @@ import type { TypedDataSigner } from "@ethersproject/abstract-signer"; import { ethers } from "ethers"; -import { isAddress } from "ethers/lib/utils.js"; +import { isAddress } from "ethers/lib/utils"; import { CIDString } from "nft.storage"; -import { DEFAULT_CHAIN_ID } from "../constants.js"; -import HypercertsStorage from "../storage.js"; +import HypercertsStorage from "../storage"; import { EASEvaluation, EvaluationSource, HypercertClientConfig, HypercertEvaluationSchema, MalformedDataError, -} from "../types/index.js"; -import EasEvaluator from "./eas.js"; +} from "../types"; +import EasEvaluator from "./eas"; const EASContractAddress = "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"; // Sepolia v0.26 @@ -36,7 +35,6 @@ export default class HypercertEvaluator implements EvaluatorInterface { constructor( config = { - chainId: DEFAULT_CHAIN_ID, easContractAddress: EASContractAddress, operator: new ethers.VoidSigner(""), } as Partial, diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 4bbdfcd6..abe5436b 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -1,9 +1,9 @@ import type { HypercertMinter, IHypercertToken } from "@hypercerts-org/contracts"; import { execute } from "../.graphclient"; -import HypercertClient from "./client.js"; -import HypercertsStorage from "./storage.js"; -import { DEPLOYMENTS } from "./constants.js"; +import HypercertClient from "./client"; +import HypercertsStorage from "./storage"; +import { DEPLOYMENTS } from "./constants"; /** * Protocol @@ -24,17 +24,17 @@ export { HypercertsStorage }; /** * Types */ -export * from "./types/index.js"; +export * from "./types"; /** * Validators */ -export * from "./validator/index.js"; +export * from "./validator"; /** * Formatters */ -export * from "./utils/formatter.js"; +export * from "./utils/formatter"; /** * Graph diff --git a/sdk/src/indexer.ts b/sdk/src/indexer.ts index 793e77ab..5fea7ba7 100644 --- a/sdk/src/indexer.ts +++ b/sdk/src/indexer.ts @@ -1,6 +1,6 @@ import { getBuiltGraphSDK, Sdk as GraphClient } from "../.graphclient"; -import { defaultQueryParams } from "./indexer/utils.js"; -import { HypercertIndexerInterface, QueryParams } from "./types/index.js"; +import { defaultQueryParams } from "./indexer/utils"; +import { HypercertIndexerInterface, QueryParams } from "./types"; /** * A class that provides indexing functionality for Hypercerts. diff --git a/sdk/src/storage.ts b/sdk/src/storage.ts index 8dd23c2a..3b637026 100644 --- a/sdk/src/storage.ts +++ b/sdk/src/storage.ts @@ -2,16 +2,16 @@ import axios from "axios"; import { CIDString, NFTStorage } from "nft.storage"; import { Blob, File, Web3Storage } from "web3.storage"; -import { validateMetaData } from "./validator/index.js"; +import { validateMetaData } from "./validator"; import { HypercertStorageConfig, HypercertStorageInterface, HypercertMetadata, MalformedDataError, StorageError, -} from "./types/index.js"; -import logger from "./utils/logger.js"; -import { getConfig } from "./utils/config.js"; +} from "./types"; +import logger from "./utils/logger"; +import { getNftStorageToken, getWeb3StorageToken } from "./utils/config"; const getCid = (cidOrIpfsUri: string) => cidOrIpfsUri.replace("ipfs://", ""); @@ -31,7 +31,8 @@ export default class HypercertsStorage implements HypercertStorageInterface { * @param overrides The configuration overrides for the storage. */ constructor(overrides: Partial) { - const { nftStorageToken, web3StorageToken } = getConfig(overrides); + const nftStorageToken = getNftStorageToken(overrides); + const web3StorageToken = getWeb3StorageToken(overrides); if (!nftStorageToken || nftStorageToken === "") { logger.warn(`NFT Storage API key is missing or invalid: ${nftStorageToken}}`); diff --git a/sdk/src/types/client.ts b/sdk/src/types/client.ts index 7d803a0c..eafb63dd 100644 --- a/sdk/src/types/client.ts +++ b/sdk/src/types/client.ts @@ -3,11 +3,19 @@ import { HypercertMinter } from "@hypercerts-org/contracts"; import { BigNumberish, BytesLike, ContractTransaction, ethers } from "ethers"; import { CIDString } from "nft.storage"; -import HypercertIndexer from "../indexer.js"; -import { AllowlistEntry, TransferRestrictions } from "./hypercerts.js"; -import { HypercertMetadata } from "./metadata.js"; +import HypercertIndexer from "../indexer"; +import { AllowlistEntry, TransferRestrictions } from "./hypercerts"; +import { HypercertMetadata } from "./metadata"; +import HypercertClient from "src/client"; + +export enum SupportedChainIds { + CELO = 42220, + GOERLI = 5, + OPTIMISM = 10, + SEPOLIA = 11155111, +} -export type SupportedChainIds = 5 | 10 | 42220 | 11155111; +export type Environment = "test" | "production" | SupportedChainIds; /** * Represents a deployment of a contract on a specific network. @@ -23,16 +31,24 @@ export type Deployment = { graphUrl: string; }; +export type Operator = ethers.providers.Provider | ethers.Signer; + /** * Configuration options for the Hypercert client. */ export type HypercertClientConfig = Deployment & HypercertStorageConfig & HypercertEvaluatorConfig & { + /** The environment the SDK runs in */ + environment: Environment; /** The provider is inherently read-only */ - operator: ethers.providers.Provider | ethers.Signer; + operator: Operator; /** Force the use of overridden values */ unsafeForceOverrideConfig?: boolean; + /** Boolean to assert if the client is in readOnly mode */ + readOnly: boolean; + /** Reason for readOnly mode */ + readOnlyReason?: string; }; /** @@ -118,6 +134,9 @@ export interface HypercertClientState { * The methods for the Hypercert client. */ export interface HypercertClientMethods { + /** Connect to client to an operator */ + connect: (operator: Operator) => Promise; + /** * Mints a new claim. * @param metaData The metadata for the claim. diff --git a/sdk/src/types/index.ts b/sdk/src/types/index.ts index b3f7dfc7..39d19b46 100644 --- a/sdk/src/types/index.ts +++ b/sdk/src/types/index.ts @@ -1,8 +1,8 @@ -export type { HypercertClaimdata } from "./claimdata.js"; -export * from "./client.js"; -export * from "./errors.js"; -export * from "./hypercerts.js"; -export * from "./indexer.js"; +export type { HypercertClaimdata } from "./claimdata"; +export * from "./client"; +export * from "./errors"; +export * from "./hypercerts"; +export * from "./indexer"; export type { EvaluationData, EvaluationSource, @@ -12,6 +12,6 @@ export type { EASEvaluation, IPFSEvaluation, HypercertPointer, -} from "./evaluation.js"; -export type { ClaimByIdQuery, ClaimTokensByClaimQuery, Claim, ClaimToken } from "./global.js"; -export type { HypercertMetadata } from "./metadata.js"; +} from "./evaluation"; +export type { ClaimByIdQuery, ClaimTokensByClaimQuery, Claim, ClaimToken } from "./global"; +export type { HypercertMetadata } from "./metadata"; diff --git a/sdk/src/utils/config.ts b/sdk/src/utils/config.ts index a9dfb228..96c5ccca 100644 --- a/sdk/src/utils/config.ts +++ b/sdk/src/utils/config.ts @@ -1,16 +1,15 @@ import { ethers } from "ethers"; -import { isAddress } from "ethers/lib/utils.js"; -import { DEFAULT_CHAIN_ID, DEPLOYMENTS } from "../constants.js"; +import { DEPLOYMENTS } from "../constants"; import { ConfigurationError, - Deployment, HypercertClientConfig, InvalidOrMissingError, + Operator, SupportedChainIds, UnsupportedChainError, -} from "../types/index.js"; -import logger from "./logger.js"; +} from "../types"; +import logger from "./logger"; /** * Returns the configuration for the Hypercert client, based on the given overrides. @@ -18,210 +17,243 @@ import logger from "./logger.js"; * @returns The configuration for the Hypercert client. * @throws An `UnsupportedChainError` if the chain ID is not 5 or 10, or if the chain ID is missing or not found. */ -export const getConfig = (overrides: Partial) => { - // Get the chainId, first from overrides, then environment variables, then the constant - const { chainId } = getChainConfig(overrides); +export const getReadOnlyConfig = (config: Partial) => { + let deployment; + const readOnly = true; + const readOnlyReason = "No signer provided"; - let baseDeployment: Deployment & { unsafeForceOverrideConfig?: boolean }; + // Need to get an environment to initialize the SDK + if (!config.environment) { + throw new ConfigurationError( + "An environment must be specified. For example, 'test', 'production' or a supported chainId.", + ); + } - if (overrides.unsafeForceOverrideConfig) { - if (!overrides.chainName || !overrides.contractAddress || !overrides.graphUrl) { - throw new UnsupportedChainError( - `attempted to override with chainId=${chainId}, but requires chainName, graphUrl, and contractAddress to be set`, - { chainID: chainId?.toString() || "undefined" }, - ); - } - baseDeployment = { - chainId: chainId, - chainName: overrides.chainName, - contractAddress: overrides.contractAddress, - graphUrl: overrides.graphUrl, - unsafeForceOverrideConfig: overrides.unsafeForceOverrideConfig, - }; - } else { - if (!chainId || [5, 10, 42220, 11155111].indexOf(chainId) === -1) { - throw new UnsupportedChainError(`chainId=${chainId} is not yet supported`, { - chainID: chainId?.toString() || "undefined", - }); - } + // Configure for a specific chain based on chainID in environment or overrides (if provided) + if (config.environment !== "test" && config.environment !== "production") { + deployment = DEPLOYMENTS[config.environment as SupportedChainIds]; - baseDeployment = DEPLOYMENTS[chainId as SupportedChainIds]; - if (!baseDeployment) { - throw new UnsupportedChainError(`Default config for chainId=${chainId} is missing in SDK`, { - chainID: chainId, - }); + // If the config provided enables unsafeForceOverrideConfig, we can use that to get the deployment + if (config.unsafeForceOverrideConfig) { + if (!config.chainId || !config.chainName || !config.contractAddress || !config.graphUrl) { + throw new UnsupportedChainError( + `attempted to override with chainId=${config.chainId}, but requires chainName, graphUrl, and contractAddress to be set`, + { chainID: config.chainId?.toString() || "undefined" }, + ); + } + deployment = { + chainId: config.chainId, + chainName: config.chainName, + contractAddress: config.contractAddress, + graphUrl: config.graphUrl, + unsafeForceOverrideConfig: config.unsafeForceOverrideConfig, + }; } } - const config = { + const _config = { + ...config, // Start with the hardcoded values - ...baseDeployment, + ...deployment, // Let the user override from environment variables - ...getChainConfig(overrides), - ...getOperator(overrides), - ...getContractAddress(overrides), - ...getGraphUrl(overrides), - ...getNftStorageToken(overrides), - ...getWeb3StorageToken(overrides), - ...getEasContractAddress(overrides), + ...getGraphUrl(config), + nftStorageToken: getNftStorageToken(config), + web3StorageToken: getWeb3StorageToken(config), + easContractAddress: getEasContractAddress(config), + readOnly, + readOnlyReason, } as HypercertClientConfig; - for (const [key, value] of Object.entries(config)) { - if (!value) { - logger.warn(`Cannot get chain config. ${key} is possibly undefined`); - } - } + checkOnMissingValues(_config); - return config; + return _config; }; -const getChainConfig = (overrides: Partial) => { - const chainId = - overrides?.chainId ?? (process.env.DEFAULT_CHAIN_ID ? parseInt(process.env.DEFAULT_CHAIN_ID) : DEFAULT_CHAIN_ID); - let chainName: string; - - switch (chainId) { - case 5: - chainName = "goerli"; - break; - case 10: - chainName = "optimism-mainnet"; - break; - case 42220: - chainName = "celo"; - break; - case 11155111: - chainName = "sepolia"; - break; - default: - chainName = overrides?.chainName ?? ""; - if (!chainName) { - throw new UnsupportedChainError(`chainId=${chainId} is not yet supported`, { - chainID: chainId?.toString() || "undefined", - }); - } +/** + * Returns the configuration for the Hypercert client, based on the given overrides. + * @param overrides An object containing overrides for the default configuration. + * @returns The configuration for the Hypercert client. + * @throws An `UnsupportedChainError` if the chain ID is not 5 or 10, or if the chain ID is missing or not found. + */ +export const getWritableConfig = async (config: Partial) => { + let deployment; + let readOnly = true; + let readOnlyReason: string | undefined = "No signer provided"; + + // Need to get an environment to initialize the SDK + if (!config.environment) { + throw new ConfigurationError( + "An environment must be specified. For example, 'test', 'production' or a supported chainId.", + ); } - return { chainId, chainName }; -}; + // If we know the chainID from the operator or the config, we can use that to get the deployment + const chainId = await getChaindId(config?.operator); -const getContractAddress = (overrides: Partial) => { - if (overrides.contractAddress) { - if (!isAddress(overrides.contractAddress)) { - throw new InvalidOrMissingError("Invalid contract address.", { contractAddress: overrides.contractAddress }); - } - return { contractAddress: overrides.contractAddress }; + if (!chainId) { + readOnly = true; + readOnlyReason = "Could not get chainId from operator"; } - const contractAddress = process.env.CONTRACT_ADDRESS; - if (contractAddress && !isAddress(contractAddress)) { - throw new InvalidOrMissingError("Invalid contract address.", { contractAddress }); + + // If the chainId from environment and the operator are different, set to readOnly according to the environment chainID + if (chainId && chainId !== config.environment) { + deployment = DEPLOYMENTS[config.environment as SupportedChainIds]; + readOnly = true; + readOnlyReason = `ChainID mismatch between signer ${chainId} and configured environment ${config.environment}`; + } else if (chainId && chainId === config.environment) { + deployment = DEPLOYMENTS[chainId as SupportedChainIds]; + readOnly = false; + readOnlyReason = undefined; } - return contractAddress ? { contractAddress } : undefined; -}; -const getGraphUrl = (overrides: Partial) => { - let graphUrl; - if (overrides.unsafeForceOverrideConfig) { - if (!overrides.graphUrl) { - throw new ConfigurationError("A graphUrl must be specified when overriding configuration"); + // If the config provided enables unsafeForceOverrideConfig, we can use that to get the deployment + if (config.unsafeForceOverrideConfig) { + if (!config.chainId || !config.chainName || !config.contractAddress || !config.graphUrl) { + throw new UnsupportedChainError( + `attempted to override with chainId=${config.chainId}, but requires chainName, graphUrl, and contractAddress to be set`, + { chainID: config.chainId?.toString() || "undefined" }, + ); } - try { - new URL(overrides.graphUrl); - } catch (error) { - throw new ConfigurationError("Invalid graph URL", { graphUrl: overrides.graphUrl }); + deployment = { + chainId: config.chainId, + chainName: config.chainName, + contractAddress: config.contractAddress, + graphUrl: config.graphUrl, + unsafeForceOverrideConfig: config.unsafeForceOverrideConfig, + }; + } + + // TODO execute validations + // else { + // if (!Object.values(SupportedChainIds).includes(deployment?.chainId as SupportedChainIds)) { + // throw new UnsupportedChainError(`Default config for chainId=${deployment?.chainId} is missing in SDK`, { + // chainID: deployment?.chainId, + // }); + // } + // } + // + + const _config = { + ...config, + // Start with the hardcoded values + ...deployment, + // Let the user override from environment variables + ...getOperator(config), + ...getGraphUrl(config), + nftStorageToken: getNftStorageToken(config), + web3StorageToken: getWeb3StorageToken(config), + easContractAddress: getEasContractAddress(config) ?? "NOT_SET", + readOnly, + readOnlyReason, + } as HypercertClientConfig; + + checkOnMissingValues(_config); + + return _config; +}; + +const checkOnMissingValues = (config: Partial) => { + for (const [key, value] of Object.entries(config)) { + if (!value) { + logger.warn(`Missing value in client config. ${key} is possibly undefined`); } - graphUrl = overrides.graphUrl; - return { graphUrl }; } +}; - const { chainId } = getChainConfig(overrides); +const getChaindId = async (operator?: Operator) => { + let chainId; + if (!operator) { + return undefined; + } else if (ethers.providers.Provider.isProvider(operator)) { + chainId = await operator.getNetwork().then((network) => network.chainId); + } else { + chainId = await operator.getChainId().then((chainId) => chainId); + } - graphUrl = DEPLOYMENTS[chainId as keyof typeof DEPLOYMENTS].graphUrl ?? process.env.GRAPH_URL; - if (!graphUrl) { - throw new UnsupportedChainError(`chainId=${chainId} is not yet supported`, { - chainID: chainId?.toString() || "undefined", - }); + return chainId; +}; + +const getGraphUrl = (config: Partial) => { + // Overrides determine Graph URL so skip the magic bits + if (config.unsafeForceOverrideConfig) { + return; } - try { - new URL(graphUrl); - } catch (error) { - throw new ConfigurationError("Invalid graph URL", { graphUrl }); + + // If environment is "test" or "production" group the graph by environment + if (config.environment === "test") { + return { graphUrl: "test" }; } - return { graphUrl }; + if (config.environment === "production") { + return { graphUrl: "production" }; + } }; -const getOperator = (overrides: Partial) => { - let operator: ethers.Signer | ethers.providers.Provider; +const getOperator = (config: Partial) => { + let operator: Operator; + + // If no operator is provided, we don't do anything + if (!config.operator) { + return undefined; + } + // Throw an error if the provided operator is not a Provider or Signer if ( - overrides.operator && - !ethers.providers.Provider.isProvider(overrides.operator) && - !ethers.Signer.isSigner(overrides.operator) + config.operator && + !ethers.providers.Provider.isProvider(config.operator) && + !ethers.Signer.isSigner(config.operator) ) { - throw new InvalidOrMissingError("Invalid operator.", { operator: overrides.operator }); + throw new InvalidOrMissingError("Invalid operator.", { operator: config.operator }); } - if (ethers.Signer.isSigner(overrides.operator)) { - operator = overrides.operator; - } else if (ethers.providers.Provider.isProvider(overrides.operator)) { - operator = overrides.operator; - operator.on("network", (newNetwork, oldNetwork) => { - // When a Provider makes its initial connection, it emits a "network" - // event with a null oldNetwork along with the newNetwork. So, if the - // oldNetwork exists, it represents a changing network + // Listen to network changes on the operator + // When a Provider makes its initial connection, it emits a "network" event with a null oldNetwork along with the + // newNetwork. So, if the oldNetwork exists, it represents a changing network + if (ethers.Signer.isSigner(config.operator)) { + operator = config.operator; + operator?.provider?.on("network", (newNetwork, oldNetwork) => { + if (typeof window === "undefined") return; + if (oldNetwork && window.location) { + window.location.reload(); + } + }); + return { operator }; + } else if (ethers.providers.Provider.isProvider(config.operator)) { + operator = config.operator; + operator.on("network", (newNetwork, oldNetwork) => { if (typeof window === "undefined") return; if (oldNetwork && window.location) { window.location.reload(); } }); - } else if (process.env.PRIVATE_KEY) { - const provider = ethers.getDefaultProvider(DEFAULT_CHAIN_ID); - operator = new ethers.Wallet(process.env.PRIVATE_KEY, provider); - } else { - operator = ethers.getDefaultProvider(DEFAULT_CHAIN_ID); - } - return { operator }; + return { operator }; + } }; -const getNftStorageToken = (overrides: Partial) => { +export const getNftStorageToken = (overrides: Partial) => { if (overrides.nftStorageToken) { - return { nftStorageToken: overrides.nftStorageToken }; + return overrides.nftStorageToken; } if (process.env.NFT_STORAGE_TOKEN) { - return { nftStorageToken: process.env.NFT_STORAGE_TOKEN }; - } - - if (process.env.NEXT_PUBLIC_NFT_STORAGE_TOKEN) { - return { nftStorageToken: process.env.NEXT_PUBLIC_NFT_STORAGE_TOKEN }; + return process.env.NFT_STORAGE_TOKEN; } - - return {}; }; -const getWeb3StorageToken = (overrides: Partial) => { +export const getWeb3StorageToken = (overrides: Partial) => { if (overrides.web3StorageToken) { - return { web3StorageToken: overrides.web3StorageToken }; + return overrides.web3StorageToken; } if (process.env.WEB3_STORAGE_TOKEN) { - return { web3StorageToken: process.env.WEB3_STORAGE_TOKEN }; + return process.env.WEB3_STORAGE_TOKEN; } - - if (process.env.NEXT_PUBLIC_WEB3_STORAGE_TOKEN) { - return { web3StorageToken: process.env.NEXT_PUBLIC_WEB3_STORAGE_TOKEN }; - } - - return {}; }; const getEasContractAddress = (overrides: Partial) => { if (overrides.easContractAddress) { - return { easContractAddress: overrides.easContractAddress }; + return overrides.easContractAddress; } - - return { easContractAddress: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e" }; }; diff --git a/sdk/src/utils/errors.ts b/sdk/src/utils/errors.ts index 2b44580d..29bd9c12 100644 --- a/sdk/src/utils/errors.ts +++ b/sdk/src/utils/errors.ts @@ -8,7 +8,7 @@ import { StorageError, UnknownSchemaError, UnsupportedChainError, -} from "../types/errors.js"; +} from "../types/errors"; /** * diff --git a/sdk/src/utils/formatter.ts b/sdk/src/utils/formatter.ts index d966b6b4..fa413cd9 100644 --- a/sdk/src/utils/formatter.ts +++ b/sdk/src/utils/formatter.ts @@ -1,5 +1,5 @@ -import { HypercertClaimdata, HypercertMetadata } from "../types/index.js"; -import { validateClaimData, validateMetaData } from "../validator/index.js"; +import { HypercertClaimdata, HypercertMetadata } from "../types"; +import { validateClaimData, validateMetaData } from "../validator"; export const INDEFINITE_DATE_STRING = "indefinite"; const formatUnixTime = (seconds: number) => { diff --git a/sdk/src/utils/resolvers.ts b/sdk/src/utils/resolvers.ts index 566795d1..d22d832a 100644 --- a/sdk/src/utils/resolvers.ts +++ b/sdk/src/utils/resolvers.ts @@ -1,4 +1,4 @@ -import { Resolvers } from "../../.graphclient/index.js"; +import { Resolvers } from "../../.graphclient"; export const resolvers: Resolvers = { Claim: { diff --git a/sdk/src/validator/index.ts b/sdk/src/validator/index.ts index b24244ce..3d3db592 100644 --- a/sdk/src/validator/index.ts +++ b/sdk/src/validator/index.ts @@ -1,7 +1,7 @@ import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; import Ajv from "ajv"; import { BigNumber, BigNumberish } from "ethers"; -import { isAddress } from "ethers/lib/utils.js"; +import { isAddress } from "ethers/lib/utils"; import claimDataSchema from "../resources/schema/claimdata.json"; import evaluationSchema from "../resources/schema/evaluation.json"; @@ -13,7 +13,7 @@ import { HypercertMetadata, MintingError, SimpleTextEvaluation, -} from "../types/index.js"; +} from "../types"; const ajv = new Ajv({ allErrors: true }); // options can be passed, e.g. {allErrors: true} ajv.addSchema(metaDataSchema, "metaData"); diff --git a/sdk/test/client.test.ts b/sdk/test/client.test.ts index 8540404b..8f2ec57c 100644 --- a/sdk/test/client.test.ts +++ b/sdk/test/client.test.ts @@ -3,8 +3,8 @@ import { MockProvider } from "ethereum-waffle"; import { ethers } from "ethers"; import sinon from "sinon"; -import { HypercertClient, HypercertMetadata, TransferRestrictions } from "../src/index.js"; -import { AllowlistEntry, ClientError, UnsupportedChainError } from "../src/types/index.js"; +import { HypercertClient, HypercertMetadata, TransferRestrictions } from "../src"; +import { AllowlistEntry, ClientError, UnsupportedChainError } from "../src/types"; const provider = new MockProvider(); sinon.stub(provider, "on"); @@ -20,17 +20,17 @@ describe("HypercertClient setup tests", () => { sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: null }); sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN: null }); - const client = new HypercertClient({ operator: provider }); + const client = new HypercertClient({ environment: "test" }); expect(client).to.be.an.instanceOf(HypercertClient); expect(client.readonly).to.be.true; }); - it("should be able to create a new instance", () => { + it("should be able to create a new instance", async () => { const operator = ethers.Wallet.createRandom(); - const config = { chainId: 5, operator, nftStorageToken: "test", web3StorageToken: "test" }; - const client = new HypercertClient(config); + const config = { environment: 5, operator, nftStorageToken: "test", web3StorageToken: "test" }; + const client = await new HypercertClient(config).connect(operator); expect(client).to.be.an.instanceOf(HypercertClient); expect(client.readonly).to.be.false; }); @@ -54,7 +54,7 @@ describe("HypercertClient setup tests", () => { sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: null }); sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN: null }); - const client = new HypercertClient({ operator: provider }); + const client = new HypercertClient({ environment: "test" }); // mintClaim try { diff --git a/sdk/test/client/allowlist.minting.test.ts b/sdk/test/client/allowlist.minting.test.ts index b2b9eb3c..7c805790 100644 --- a/sdk/test/client/allowlist.minting.test.ts +++ b/sdk/test/client/allowlist.minting.test.ts @@ -3,10 +3,10 @@ import { BigNumber, ethers } from "ethers"; import sinon from "sinon"; import { expect } from "@jest/globals"; -import { HypercertClient } from "../../src/index.js"; -import HypercertsStorage from "../../src/storage.js"; -import { MalformedDataError, MintingError, TransferRestrictions } from "../../src/types/index.js"; -import { getAllowlist, getFormattedMetadata } from "../helpers.js"; +import { HypercertClient, deployments } from "../../src/index"; +import HypercertsStorage from "../../src/storage"; +import { MalformedDataError, MintingError, TransferRestrictions } from "../../src/types/index"; +import { getAllowlist, getFormattedMetadata } from "../helpers"; import { HypercertMinter, HypercertMinterAbi } from "@hypercerts-org/contracts"; const mockCorrectMetadataCid = "testCID1234fkreigdm2flneb4khd7eixodagst5nrndptgezrjux7gohxcngjn67x6u"; @@ -15,17 +15,23 @@ describe("Allows for minting claims from an allowlist", () => { const dataStub = sinon.stub(HypercertsStorage.prototype, "storeData").resolves(mockCorrectMetadataCid); const setUp = async () => { - const provider = new MockProvider(); + const provider = new MockProvider({ + ganacheOptions: { + chain: { chainId: 5 }, + }, + }); const [user, other, admin] = provider.getWallets(); const stub = sinon.stub(provider, "on"); - const minter = await deployMockContract(user, HypercertMinterAbi); - - const client = new HypercertClient({ - chainId: 5, - operator: user, + const minter = await deployMockContract(user, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, }); + const client = await new HypercertClient({ + environment: 5, + }).connect(user); + sinon.replaceGetter(client, "contract", () => minter as unknown as HypercertMinter); return { @@ -71,7 +77,7 @@ describe("Allows for minting claims from an allowlist", () => { sinon.assert.calledOnce(metaDataStub); sinon.assert.calledOnce(dataStub); - expect(res.chainId).toBe(1337); + expect(res.chainId).toBe(5); expect(_provider.callHistory.length).toBe(2); }); diff --git a/sdk/test/client/burn.test.ts b/sdk/test/client/burn.test.ts index c0d83887..85bc16fe 100644 --- a/sdk/test/client/burn.test.ts +++ b/sdk/test/client/burn.test.ts @@ -2,9 +2,11 @@ import { MockProvider, deployMockContract } from "ethereum-waffle"; import { BigNumber, Wallet } from "ethers"; import sinon from "sinon"; -import HypercertClient from "../../src/client.js"; -import { ClientError } from "../../src/types/errors.js"; +import HypercertClient from "../../src/client"; +import { ClientError } from "../../src/types/errors"; import { HypercertMinterAbi } from "@hypercerts-org/contracts"; +import { deployments } from "../../src"; + describe("burn fraction tokens in HypercertClient", () => { let stub: sinon.SinonStub; let provider: MockProvider; @@ -13,7 +15,11 @@ describe("burn fraction tokens in HypercertClient", () => { const fractionId = BigNumber.from("9868188640707215440437863615521278132232"); beforeAll(() => { - provider = new MockProvider(); + provider = new MockProvider({ + ganacheOptions: { + chain: { chainId: 5 }, + }, + }); [user, other] = provider.getWallets(); stub = sinon.stub(provider, "on"); @@ -28,15 +34,16 @@ describe("burn fraction tokens in HypercertClient", () => { it("allows for a hypercert fraction to be burned", async () => { const userAddress = await user.getAddress(); - const mockMinter = await deployMockContract(user, HypercertMinterAbi); + const mockMinter = await deployMockContract(user, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); await mockMinter.mock["burnFraction(address,uint256)"].withArgs(userAddress, fractionId).returns(); - const client = new HypercertClient({ - chainId: 5, - operator: user, - contractAddress: mockMinter.address, - }); + const client = await new HypercertClient({ + environment: 5, + }).connect(user); expect(client.readonly).toBe(false); @@ -48,14 +55,15 @@ describe("burn fraction tokens in HypercertClient", () => { it("throws on burning fraction not owned by signer", async () => { const otherUser = await other.getAddress(); - const mockMinter = await deployMockContract(user, HypercertMinterAbi); + const mockMinter = await deployMockContract(user, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); await mockMinter.mock.ownerOf.withArgs(fractionId).returns(otherUser); - const client = new HypercertClient({ - chainId: 5, - operator: user, - contractAddress: mockMinter.address, - }); + const client = await new HypercertClient({ + environment: 5, + }).connect(user); expect(client.readonly).toBe(false); @@ -77,15 +85,16 @@ describe("burn fraction tokens in HypercertClient", () => { it("allows for a hypercert fraction to be burned with override params", async () => { const userAddress = await user.getAddress(); - const mockMinter = await deployMockContract(user, HypercertMinterAbi); + const mockMinter = await deployMockContract(user, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); await mockMinter.mock["burnFraction(address,uint256)"].withArgs(userAddress, fractionId).returns(); - const client = new HypercertClient({ - chainId: 5, - operator: user, - contractAddress: mockMinter.address, - }); + const client = await new HypercertClient({ + environment: 5, + }).connect(user); expect(client.readonly).toBe(false); diff --git a/sdk/test/client/minting.test.ts b/sdk/test/client/minting.test.ts index 2d657062..3b491e4d 100644 --- a/sdk/test/client/minting.test.ts +++ b/sdk/test/client/minting.test.ts @@ -16,16 +16,19 @@ describe("mintClaim in HypercertClient", () => { const metaDataStub = sinon.stub(HypercertsStorage.prototype, "storeMetadata").resolves(mockCorrectMetadataCid); const setUp = async () => { - const provider = new MockProvider(); + const provider = new MockProvider({ + ganacheOptions: { + chain: { chainId: 5 }, + }, + }); const [user, other, admin] = provider.getWallets(); const stub = sinon.stub(provider, "on"); const minter = await deployMockContract(user, HypercertMinterAbi); - const client = new HypercertClient({ + const client = await new HypercertClient({ chainId: 5, - operator: user, - }); + }).connect(user); sinon.replaceGetter(client, "contract", () => minter as unknown as HypercertMinter); diff --git a/sdk/test/client/split.merge.test.ts b/sdk/test/client/split.merge.test.ts index fec89bf8..3ac67ab4 100644 --- a/sdk/test/client/split.merge.test.ts +++ b/sdk/test/client/split.merge.test.ts @@ -2,10 +2,11 @@ import { MockProvider, deployMockContract } from "ethereum-waffle"; import { BigNumber, Wallet } from "ethers"; import sinon from "sinon"; -import HypercertClient from "../../src/client.js"; -import { ClientError } from "../../src/types/errors.js"; +import HypercertClient from "../../src/client"; +import { ClientError } from "../../src/types/errors"; import { HypercertMinterAbi } from "@hypercerts-org/contracts"; +import { deployments } from "../../src"; describe("splitClaimUnits in HypercertClient", () => { let stub: sinon.SinonStub; @@ -14,7 +15,11 @@ describe("splitClaimUnits in HypercertClient", () => { const fractionId = BigNumber.from("9868188640707215440437863615521278132232"); beforeAll(() => { - provider = new MockProvider(); + provider = new MockProvider({ + ganacheOptions: { + chain: { chainId: 5 }, + }, + }); wallet = provider.getWallets()[0]; stub = sinon.stub(provider, "on"); @@ -29,7 +34,10 @@ describe("splitClaimUnits in HypercertClient", () => { it("allows for a hypercert fractions to be splitted over value", async () => { const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); + const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); await mockMinter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(300); await mockMinter.mock["splitFraction(address,uint256,uint256[])"] @@ -38,23 +46,25 @@ describe("splitClaimUnits in HypercertClient", () => { const signer = wallet.connect(provider); - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); + const client = await new HypercertClient({ + environment: 5, + }).connect(signer); expect(client.readonly).toBe(false); - await client.splitClaimUnits(fractionId, [100, 200]); + const tx = await client.splitClaimUnits(fractionId, [100, 200]); + expect((await tx.wait()).status).toBe(1); //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(7); + expect(provider.callHistory.length).toBe(6); }, 10000); it("allows for a hypercert fractions to be splitted over value with override params", async () => { const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); + const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); await mockMinter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(300); await mockMinter.mock["splitFraction(address,uint256,uint256[])"] @@ -63,11 +73,10 @@ describe("splitClaimUnits in HypercertClient", () => { const signer = wallet.connect(provider); - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); + const client = await new HypercertClient({ + environment: 5, + }).connect(signer); + expect(client.readonly).toBe(false); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -78,29 +87,33 @@ describe("splitClaimUnits in HypercertClient", () => { expect((e as Error).message).toMatch(/invalid BigNumber string/); } - await client.splitClaimUnits(fractionId, [100, 200], { gasLimit: "12300000" }); + const tx = await client.splitClaimUnits(fractionId, [100, 200], { gasLimit: "12300000" }); + expect((await tx.wait()).status).toBe(1); //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(9); + expect(provider.callHistory.length).toBe(8); }, 10000); it("throws on splitting with incorrect new total value", async () => { const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); + const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); await mockMinter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(42); const signer = wallet.connect(provider); - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); + const client = await new HypercertClient({ + environment: 5, + }).connect(signer); + expect(client.readonly).toBe(false); try { - await client.splitClaimUnits(fractionId, [100, 200]); + const tx = await client.splitClaimUnits(fractionId, [100, 200]); + expect((await tx.wait()).status).toBe(1); } catch (e) { expect(e instanceof ClientError).toBeTruthy(); @@ -111,26 +124,29 @@ describe("splitClaimUnits in HypercertClient", () => { //TODO determine underlying calls and mock those out. Some are provider simulation calls // Owner // UnitsOf - expect(provider.callHistory.length).toBe(5); + expect(provider.callHistory.length).toBe(4); expect.assertions(4); }); it("throws on splitting fractions not owned by signer", async () => { const otherUser = await provider.getWallets()[1].getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); + const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); await mockMinter.mock.ownerOf.withArgs(fractionId).returns(otherUser); const signer = wallet.connect(provider); - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); + const client = await new HypercertClient({ + environment: 5, + }).connect(signer); + expect(client.readonly).toBe(false); try { - await client.splitClaimUnits(fractionId, [100, 200]); + const tx = await client.splitClaimUnits(fractionId, [100, 200]); + expect((await tx.wait()).status).toBe(1); } catch (e) { expect(e instanceof ClientError).toBeTruthy(); @@ -140,7 +156,7 @@ describe("splitClaimUnits in HypercertClient", () => { //TODO determine underlying calls and mock those out. Some are provider simulation calls // Owner - expect(provider.callHistory.length).toBe(3); + expect(provider.callHistory.length).toBe(2); expect.assertions(4); }); }); @@ -152,10 +168,16 @@ describe("mergeClaimUnits in HypercertClient", () => { const fractionId = BigNumber.from("9868188640707215440437863615521278132232"); beforeAll(() => { - provider = new MockProvider(); + provider = new MockProvider({ + ganacheOptions: { + chain: { chainId: 5 }, + }, + }); + wallet = provider.getWallets()[0]; stub = sinon.stub(provider, "on"); }); + beforeEach(() => { provider.clearCallHistory(); }); @@ -166,7 +188,10 @@ describe("mergeClaimUnits in HypercertClient", () => { it("allows for hypercert fractions to merge value", async () => { const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); + const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); await mockMinter.mock.ownerOf.withArgs(fractionId.add(1)).returns(userAddress); await mockMinter.mock["mergeFractions(address,uint256[])"] @@ -175,22 +200,25 @@ describe("mergeClaimUnits in HypercertClient", () => { const signer = wallet.connect(provider); - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); + const client = await new HypercertClient({ + environment: 5, + }).connect(signer); + expect(client.readonly).toBe(false); - await client.mergeClaimUnits([fractionId, fractionId.add(1)]); + const tx = await client.mergeClaimUnits([fractionId, fractionId.add(1)]); + expect((await tx.wait()).status).toBe(1); //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(7); + expect(provider.callHistory.length).toBe(6); }, 10000); it("allows for hypercert fractions to merge value with override params", async () => { const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); + const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); await mockMinter.mock.ownerOf.withArgs(fractionId.add(1)).returns(userAddress); await mockMinter.mock["mergeFractions(address,uint256[])"] @@ -199,11 +227,10 @@ describe("mergeClaimUnits in HypercertClient", () => { const signer = wallet.connect(provider); - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); + const client = await new HypercertClient({ + environment: 5, + }).connect(signer); + expect(client.readonly).toBe(false); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -214,31 +241,35 @@ describe("mergeClaimUnits in HypercertClient", () => { expect((e as Error).message).toMatch(/invalid BigNumber string/); } - await client.mergeClaimUnits([fractionId, fractionId.add(1)], { gasLimit: "12300000" }); + const tx = await client.mergeClaimUnits([fractionId, fractionId.add(1)], { gasLimit: "12300000" }); + expect((await tx.wait()).status).toBe(1); //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(9); + expect(provider.callHistory.length).toBe(8); }, 10000); it("throws on splitting fractions not owned by signer", async () => { const userAddress = await wallet.getAddress(); const otherUser = await provider.getWallets()[1].getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); + const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); await mockMinter.mock.ownerOf.withArgs(fractionId.add(1)).returns(otherUser); const signer = wallet.connect(provider); - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); + const client = await new HypercertClient({ + environment: 5, + }).connect(signer); + expect(client.readonly).toBe(false); try { - await client.mergeClaimUnits([fractionId, fractionId.add(1)]); + const tx = await client.mergeClaimUnits([fractionId, fractionId.add(1)]); + expect((await tx.wait()).status).toBe(1); } catch (e) { expect(e instanceof ClientError).toBeTruthy(); @@ -247,6 +278,6 @@ describe("mergeClaimUnits in HypercertClient", () => { } //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(5); + expect(provider.callHistory.length).toBe(4); }); }); diff --git a/sdk/test/utils/config.test.ts b/sdk/test/utils/config.test.ts index 1290fa90..507cc4d3 100644 --- a/sdk/test/utils/config.test.ts +++ b/sdk/test/utils/config.test.ts @@ -3,22 +3,21 @@ import chaiSubset from "chai-subset"; import { ethers } from "ethers"; import sinon from "sinon"; -import { DEFAULT_CHAIN_ID } from "../../src/constants.js"; import { ConfigurationError, HypercertClientConfig, InvalidOrMissingError, UnsupportedChainError, } from "../../src/types/index.js"; -import { getConfig } from "../../src/utils/config.js"; -import { reloadEnv } from "../../test/setup-env.js"; +import { getReadOnlyConfig } from "../../src/utils/config"; +import { reloadEnv } from "../../test/setup-env"; chai.use(chaiSubset); describe("Config: chainId and chainName", () => { it("should throw an error when the chainId is not supported", () => { try { - getConfig({ chainId: 1337 }); + getReadOnlyConfig({ chainId: 1337 }); expect.fail("Should throw UnsupportedChainError"); } catch (e) { expect(e instanceof UnsupportedChainError).to.be.true; @@ -37,22 +36,13 @@ describe("Config: contractAddress", () => { it("should return the contract address specified by overrides", () => { const overrides: Partial = { contractAddress: "0x1234567890123456789012345678901234567890" }; - const config = getConfig(overrides); + const config = getReadOnlyConfig(overrides); expect(config.contractAddress).to.equal(overrides.contractAddress); }); - it("should return the contract address specified by the CONTRACT_ADDRESS environment variable", () => { - const CONTRACT_ADDRESS = "0x1234567890123456789012345678901234567890"; - sinon.stub(process, "env").value({ CONTRACT_ADDRESS }); - - const config = getConfig({}); - expect(config.contractAddress).to.equal(CONTRACT_ADDRESS); - delete process.env.CONTRACT_ADDRESS; - }); - it("should throw an error when the contract address specified by overrides is invalid", () => { const overrides: Partial = { contractAddress: "invalid-address" }; - expect(() => getConfig(overrides)).to.throw(InvalidOrMissingError, "Invalid contract address"); + expect(() => getReadOnlyConfig(overrides)).to.throw(InvalidOrMissingError, "Invalid contract address"); }); }); @@ -62,7 +52,7 @@ describe("Config: graphUrl", () => { }); it("should return the default graphUrl when no overrides are specified", () => { - const result = getConfig({}); + const result = getReadOnlyConfig({}); expect(result.graphUrl).to.equal("https://api.thegraph.com/subgraphs/name/hypercerts-admin/hypercerts-testnet"); }); @@ -73,7 +63,7 @@ describe("Config: graphUrl", () => { contractAddress: "0x1234567890123456789012345678901234567890", unsafeForceOverrideConfig: true, }; - const result = getConfig(overrides); + const result = getReadOnlyConfig(overrides); expect(result.graphUrl).to.equal(overrides.graphUrl); }); @@ -85,7 +75,7 @@ describe("Config: graphUrl", () => { unsafeForceOverrideConfig: true, }; - expect(() => getConfig(overrides)).to.throw(ConfigurationError, "Invalid graph URL"); + expect(() => getReadOnlyConfig(overrides)).to.throw(ConfigurationError, "Invalid graph URL"); }); it("should throw an error when the graph URL specified by overrides is missing", () => { @@ -94,7 +84,7 @@ describe("Config: graphUrl", () => { contractAddress: "0x1234567890123456789012345678901234567890", unsafeForceOverrideConfig: true, }; - expect(() => getConfig(overrides)).to.throw( + expect(() => getReadOnlyConfig(overrides)).to.throw( UnsupportedChainError, "attempted to override with chainId=5, but requires chainName, graphUrl, and contractAddress to be set", ); @@ -110,7 +100,7 @@ describe("Config: nftStorageToken", () => { it("should return an empty object when no overrides or environment variables are specified", () => { sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); - const result = getConfig({}); + const result = getReadOnlyConfig({}); expect(result).to.deep.include({ nftStorageToken: "NFTSTOR", }); @@ -120,7 +110,7 @@ describe("Config: nftStorageToken", () => { const overrides: Partial = { nftStorageToken: "NFTSTOR", }; - const result = getConfig(overrides); + const result = getReadOnlyConfig(overrides); expect(result).to.deep.include({ nftStorageToken: overrides.nftStorageToken, }); @@ -128,7 +118,7 @@ describe("Config: nftStorageToken", () => { it("should return the nftStorageToken specified by the NFT_STORAGE_TOKEN environment variable", () => { sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); - const result = getConfig({}); + const result = getReadOnlyConfig({}); expect(result).to.deep.include({ nftStorageToken: "NFTSTOR", }); @@ -137,7 +127,7 @@ describe("Config: nftStorageToken", () => { it("should return the nftStorageToken specified by the NEXT_PUBLIC_NFT_STORAGE_TOKEN environment variable", () => { sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: "NFTSTOR" }); - const result = getConfig({}); + const result = getReadOnlyConfig({}); expect(result).to.deep.include({ nftStorageToken: "NFTSTOR", }); @@ -147,7 +137,7 @@ describe("Config: nftStorageToken", () => { sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: null }); const overrides: Partial = {}; - expect(() => getConfig(overrides)).to.not.throw(); + expect(() => getReadOnlyConfig(overrides)).to.not.throw(); }); }); @@ -158,7 +148,7 @@ describe("Config: getOperator", () => { reloadEnv(); }); it("should return a default provider when no overrides or environment variables are specified", () => { - const result = getConfig({}); + const result = getReadOnlyConfig({}); //TODO: hacky solution to compare providers expect(JSON.stringify(result.operator)).to.equal(JSON.stringify(ethers.getDefaultProvider(DEFAULT_CHAIN_ID))); }); @@ -169,7 +159,7 @@ describe("Config: getOperator", () => { const overrides: Partial = { operator: wallet, }; - const result = getConfig(overrides); + const result = getReadOnlyConfig(overrides); expect(result.operator).to.equal(overrides.operator); }); @@ -177,7 +167,7 @@ describe("Config: getOperator", () => { const PRIVATE_KEY = "0x0123456789012345678901234567890123456789012345678901234567890123"; sinon.stub(process, "env").value({ PRIVATE_KEY }); - const result = getConfig({}); + const result = getReadOnlyConfig({}); const provider = ethers.getDefaultProvider(DEFAULT_CHAIN_ID); const wallet = new ethers.Wallet(PRIVATE_KEY, provider); expect(JSON.stringify(result.operator)).to.equal(JSON.stringify(wallet)); @@ -187,7 +177,7 @@ describe("Config: getOperator", () => { const overrides: Partial = { operator: "invalid" as unknown as ethers.Signer, }; - expect(() => getConfig(overrides)).to.throw(InvalidOrMissingError, "Invalid operator."); + expect(() => getReadOnlyConfig(overrides)).to.throw(InvalidOrMissingError, "Invalid operator."); }); }); @@ -201,7 +191,7 @@ describe("Config: web3StorageToken", () => { it("should return an empty object when no overrides or environment variables are specified", () => { const WEB3_STORAGE_TOKEN = "WEB3"; sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); - const result = getConfig({}); + const result = getReadOnlyConfig({}); expect(result).to.deep.include({ web3StorageToken: WEB3_STORAGE_TOKEN, }); @@ -211,7 +201,7 @@ describe("Config: web3StorageToken", () => { const overrides: Partial = { web3StorageToken: "WEB3STOR", }; - const result = getConfig(overrides); + const result = getReadOnlyConfig(overrides); expect(result).to.deep.include({ web3StorageToken: overrides.web3StorageToken, }); @@ -220,7 +210,7 @@ describe("Config: web3StorageToken", () => { it("should return the web3StorageToken specified by the WEB3_STORAGE_TOKEN environment variable", () => { const WEB3_STORAGE_TOKEN = "WEB3"; sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); - const result = getConfig({}); + const result = getReadOnlyConfig({}); expect(result).to.deep.include({ web3StorageToken: WEB3_STORAGE_TOKEN, }); @@ -230,7 +220,7 @@ describe("Config: web3StorageToken", () => { const NEXT_PUBLIC_WEB3_STORAGE_TOKEN = "WEB3"; sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN }); - const result = getConfig({}); + const result = getReadOnlyConfig({}); expect(result).to.deep.include({ web3StorageToken: NEXT_PUBLIC_WEB3_STORAGE_TOKEN, }); @@ -239,6 +229,6 @@ describe("Config: web3StorageToken", () => { it("should not throw an error when the web3StorageToken specified by overrides is invalid", () => { sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN: null }); const overrides: Partial = {}; - expect(() => getConfig(overrides)).to.not.throw(); + expect(() => getReadOnlyConfig(overrides)).to.not.throw(); }); }); diff --git a/sdk/tsconfig.json b/sdk/tsconfig.json index 368097f4..d0d23e7f 100644 --- a/sdk/tsconfig.json +++ b/sdk/tsconfig.json @@ -22,5 +22,5 @@ "skipLibCheck": true }, "exclude": ["node_modules"], - "include": ["./src/*.ts", "./src/**/*", "./test", "global.d.ts"] + "include": ["./src/*.ts", "./src/**/*.ts", "./test", "global.d.ts"] } From 6eb63f602edf9fb375b8f584339425ae0da12e2d Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Tue, 31 Oct 2023 14:46:42 +0100 Subject: [PATCH 18/49] feat(tests): fix all tests to use updated init --- graph/tests/.latest.json | 2 +- sdk/package.json | 2 +- sdk/src/client.ts | 72 ++++-- sdk/src/types/client.ts | 7 +- sdk/src/utils/config.ts | 104 +++++---- sdk/test/client.test.ts | 15 +- sdk/test/client/burn.test.ts | 12 +- sdk/test/client/minting.test.ts | 23 +- sdk/test/utils/config.test.ts | 380 +++++++++++++++++--------------- 9 files changed, 348 insertions(+), 269 deletions(-) diff --git a/graph/tests/.latest.json b/graph/tests/.latest.json index 4651dd06..97a0c116 100644 --- a/graph/tests/.latest.json +++ b/graph/tests/.latest.json @@ -1,4 +1,4 @@ { "version": "0.6.0", - "timestamp": 1698094053842 + "timestamp": 1698759751327 } diff --git a/sdk/package.json b/sdk/package.json index 1227f74b..2988fe18 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@hypercerts-org/sdk", - "version": "0.8.16", + "version": "0.9.0", "description": "SDK for hypercerts protocol", "repository": "git@github.com:hypercerts-org/hypercerts.git", "author": "Hypercerts team", diff --git a/sdk/src/client.ts b/sdk/src/client.ts index 350f01a4..76d8ccea 100644 --- a/sdk/src/client.ts +++ b/sdk/src/client.ts @@ -15,6 +15,7 @@ import { MalformedDataError, TransferRestrictions, Operator, + SupportedChainIds, } from "./types/index"; import { getWritableConfig, getReadOnlyConfig } from "./utils/config"; import logger from "./utils/logger"; @@ -34,7 +35,7 @@ export default class HypercertClient implements HypercertClientInterface { private _evaluator: HypercertEvaluator | undefined; private _indexer: HypercertIndexer; //TODO added the TypedDataSigner since that's needed for EAS signing. Will this work on front-end? - private _contract: HypercertMinter; + private _contract: HypercertMinter | undefined; readonly: boolean; /** @@ -48,9 +49,11 @@ export default class HypercertClient implements HypercertClientInterface { this._indexer = new HypercertIndexer(this._config); - this.readonly = this._config.readOnly || !this._config.contractAddress || this._storage.readonly; + this.readonly = this._config.readOnly || this._storage.readonly; - this._contract = new ethers.Contract(this._config.contractAddress, HypercertMinterAbi); + this._contract = this._config.contractAddress + ? new ethers.Contract(this._config.contractAddress, HypercertMinterAbi) + : undefined; if (this.readonly) { logger.warn("HypercertsClient is in readonly mode", "client"); @@ -62,13 +65,13 @@ export default class HypercertClient implements HypercertClientInterface { * @param operator The operator to connect to. */ connect = async (operator: Operator) => { - this._config = await getWritableConfig({ ...this._config, operator: operator }); + this._config = await getWritableConfig({ ...this._config, operator }); this._indexer = new HypercertIndexer(this._config); this._evaluator = new HypercertEvaluator(this._config); - this._contract = this._contract?.connect(operator); + this._contract = new ethers.Contract(this._config.contractAddress, HypercertMinterAbi, operator); this.readonly = this._config.readOnly || this._storage.readonly || !this._contract; @@ -108,7 +111,7 @@ export default class HypercertClient implements HypercertClientInterface { * Gets the HypercertMinter contract used by the client. * @returns The contract. */ - get contract(): HypercertMinter { + get contract(): HypercertMinter | undefined { return this._contract; } @@ -128,6 +131,9 @@ export default class HypercertClient implements HypercertClientInterface { ): Promise => { this.checkWritable(); + const contract = this.contract; + if (!contract) throw new ClientError("Contract is undefined", { client: this }); + if (!ethers.Signer.isSigner(this._config.operator)) { throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); } @@ -144,8 +150,8 @@ export default class HypercertClient implements HypercertClientInterface { const cid = await this.storage.storeMetadata(metaData); return overrides - ? this.contract.mintClaim(signerAddress, totalUnits, cid, transferRestriction, overrides) - : this.contract.mintClaim(signerAddress, totalUnits, cid, transferRestriction); + ? contract.mintClaim(signerAddress, totalUnits, cid, transferRestriction, overrides) + : contract.mintClaim(signerAddress, totalUnits, cid, transferRestriction); }; /** @@ -167,6 +173,9 @@ export default class HypercertClient implements HypercertClientInterface { ) => { this.checkWritable(); + const contract = this.contract; + if (!contract) throw new ClientError("Contract is undefined", { client: this }); + if (!ethers.Signer.isSigner(this._config.operator)) { throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); } @@ -196,8 +205,8 @@ export default class HypercertClient implements HypercertClientInterface { const cid = await this.storage.storeMetadata(metaData); return overrides - ? this.contract.createAllowlist(signerAddress, totalUnits, tree.root, cid, transferRestriction, overrides) - : this.contract.createAllowlist(signerAddress, totalUnits, tree.root, cid, transferRestriction); + ? contract.createAllowlist(signerAddress, totalUnits, tree.root, cid, transferRestriction, overrides) + : contract.createAllowlist(signerAddress, totalUnits, tree.root, cid, transferRestriction); }; /** @@ -211,6 +220,9 @@ export default class HypercertClient implements HypercertClientInterface { splitClaimUnits = async (claimId: BigNumberish, fractions: BigNumberish[], overrides?: ethers.Overrides) => { this.checkWritable(); + const contract = this.contract; + if (!contract) throw new ClientError("Contract is undefined", { client: this }); + // check if claim exists and is owned by the signer if (!ethers.Signer.isSigner(this._config.operator)) { throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); @@ -218,19 +230,19 @@ export default class HypercertClient implements HypercertClientInterface { const signerAddress = await this._config.operator.getAddress(); - const claimOwner = await this._contract.ownerOf(claimId); + const claimOwner = await contract.ownerOf(claimId); if (claimOwner.toLowerCase() !== signerAddress.toLowerCase()) throw new ClientError("Claim is not owned by the signer", { signer: signerAddress, claimOwner }); // check if the sum of the fractions is equal to the total units - const totalUnits = await this._contract["unitsOf(uint256)"](claimId); + const totalUnits = await contract["unitsOf(uint256)"](claimId); const sumFractions = fractions.reduce((a, b) => BigNumber.from(a).add(b), BigNumber.from(0)); if (!BigNumber.from(sumFractions).eq(totalUnits)) throw new ClientError("Sum of fractions is not equal to the total units", { totalUnits, sumFractions }); return overrides - ? this.contract.splitFraction(signerAddress, claimId, fractions, overrides) - : this.contract.splitFraction(signerAddress, claimId, fractions); + ? contract.splitFraction(signerAddress, claimId, fractions, overrides) + : contract.splitFraction(signerAddress, claimId, fractions); }; /** @@ -242,6 +254,9 @@ export default class HypercertClient implements HypercertClientInterface { mergeClaimUnits = async (claimIds: BigNumberish[], overrides?: ethers.Overrides) => { this.checkWritable(); + const contract = this.contract; + if (!contract) throw new ClientError("Contract is undefined", { client: this }); + // check if all claims exist and are owned by the signer if (!ethers.Signer.isSigner(this._config.operator)) { throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); @@ -249,7 +264,7 @@ export default class HypercertClient implements HypercertClientInterface { const signerAddress = await this._config.operator.getAddress(); - const claims = await Promise.all(claimIds.map(async (id) => ({ id, owner: await this._contract.ownerOf(id) }))); + const claims = await Promise.all(claimIds.map(async (id) => ({ id, owner: await contract.ownerOf(id) }))); if (claims.some((c) => c.owner.toLowerCase() !== signerAddress.toLowerCase())) { const invalidClaimIDs = claims.filter((c) => c.owner !== signerAddress).map((c) => c.id); throw new ClientError("One or more claims are not owned by the signer", { @@ -259,8 +274,8 @@ export default class HypercertClient implements HypercertClientInterface { } return overrides - ? this.contract.mergeFractions(signerAddress, claimIds, overrides) - : this.contract.mergeFractions(signerAddress, claimIds); + ? contract.mergeFractions(signerAddress, claimIds, overrides) + : contract.mergeFractions(signerAddress, claimIds); }; /** @@ -272,19 +287,22 @@ export default class HypercertClient implements HypercertClientInterface { burnClaimFraction = async (claimId: BigNumberish, overrides?: ethers.Overrides) => { this.checkWritable(); + const contract = this.contract; + if (!contract) throw new ClientError("Contract is undefined", { client: this }); + // check if claim exists and is owned by the signer if (!ethers.Signer.isSigner(this._config.operator)) { throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); } const signerAddress = await this._config.operator.getAddress(); - const claimOwner = await this._contract.ownerOf(claimId); + const claimOwner = await contract.ownerOf(claimId); if (claimOwner.toLowerCase() !== signerAddress.toLowerCase()) throw new ClientError("Claim is not owned by the signer", { signer: signerAddress, claimOwner }); return overrides - ? this.contract.burnFraction(signerAddress, claimId, overrides) - : this.contract.burnFraction(signerAddress, claimId); + ? contract.burnFraction(signerAddress, claimId, overrides) + : contract.burnFraction(signerAddress, claimId); }; /** @@ -305,6 +323,9 @@ export default class HypercertClient implements HypercertClientInterface { ): Promise => { this.checkWritable(); + const contract = this.contract; + if (!contract) throw new ClientError("Contract is undefined", { client: this }); + if (!ethers.Signer.isSigner(this._config.operator)) { throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); } @@ -321,8 +342,8 @@ export default class HypercertClient implements HypercertClientInterface { } return overrides - ? this.contract.mintClaimFromAllowlist(signerAddress, proof, claimId, units, overrides) - : this.contract.mintClaimFromAllowlist(signerAddress, proof, claimId, units); + ? contract.mintClaimFromAllowlist(signerAddress, proof, claimId, units, overrides) + : contract.mintClaimFromAllowlist(signerAddress, proof, claimId, units); }; /** @@ -344,6 +365,9 @@ export default class HypercertClient implements HypercertClientInterface { ): Promise => { this.checkWritable(); + const contract = this.contract; + if (!contract) throw new ClientError("Contract is undefined", { client: this }); + if (!ethers.Signer.isSigner(this._config.operator)) { throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); } @@ -361,8 +385,8 @@ export default class HypercertClient implements HypercertClientInterface { } return overrides - ? this.contract.batchMintClaimsFromAllowlists(signerAddress, proofs, claimIds, units, overrides) - : this.contract.batchMintClaimsFromAllowlists(signerAddress, proofs, claimIds, units); + ? contract.batchMintClaimsFromAllowlists(signerAddress, proofs, claimIds, units, overrides) + : contract.batchMintClaimsFromAllowlists(signerAddress, proofs, claimIds, units); }; private checkWritable = () => { diff --git a/sdk/src/types/client.ts b/sdk/src/types/client.ts index eafb63dd..72065f20 100644 --- a/sdk/src/types/client.ts +++ b/sdk/src/types/client.ts @@ -126,8 +126,11 @@ export interface HypercertClientState { storage: HypercertStorageInterface; /** The indexer used by the client. */ indexer: HypercertIndexer; - /** The contract used by the client. */ - contract: HypercertMinter; + /** The contract used by the client. + * The contract is only available when a specific chain is configured + * or provided by the operator (provider/signer) + **/ + contract: HypercertMinter | undefined; } /** diff --git a/sdk/src/utils/config.ts b/sdk/src/utils/config.ts index 96c5ccca..03aea857 100644 --- a/sdk/src/utils/config.ts +++ b/sdk/src/utils/config.ts @@ -1,6 +1,5 @@ -import { ethers } from "ethers"; +import { Signer, ethers } from "ethers"; -import { DEPLOYMENTS } from "../constants"; import { ConfigurationError, HypercertClientConfig, @@ -10,6 +9,8 @@ import { UnsupportedChainError, } from "../types"; import logger from "./logger"; +import { deployments } from "../../src"; +import { isAddress } from "ethers/lib/utils"; /** * Returns the configuration for the Hypercert client, based on the given overrides. @@ -31,23 +32,17 @@ export const getReadOnlyConfig = (config: Partial) => { // Configure for a specific chain based on chainID in environment or overrides (if provided) if (config.environment !== "test" && config.environment !== "production") { - deployment = DEPLOYMENTS[config.environment as SupportedChainIds]; + deployment = getDeployment(config.environment as SupportedChainIds); // If the config provided enables unsafeForceOverrideConfig, we can use that to get the deployment if (config.unsafeForceOverrideConfig) { - if (!config.chainId || !config.chainName || !config.contractAddress || !config.graphUrl) { - throw new UnsupportedChainError( - `attempted to override with chainId=${config.chainId}, but requires chainName, graphUrl, and contractAddress to be set`, - { chainID: config.chainId?.toString() || "undefined" }, - ); - } - deployment = { - chainId: config.chainId, - chainName: config.chainName, - contractAddress: config.contractAddress, - graphUrl: config.graphUrl, - unsafeForceOverrideConfig: config.unsafeForceOverrideConfig, - }; + deployment = { ...deployment, ...getDeploymentFromOverrides(config) }; + } + + if (!deployment) { + throw new UnsupportedChainError(`No default config for environment=${config.environment} found in SDK`, { + chainID: config.environment?.toString() || "undefined", + }); } } @@ -97,30 +92,18 @@ export const getWritableConfig = async (config: Partial) // If the chainId from environment and the operator are different, set to readOnly according to the environment chainID if (chainId && chainId !== config.environment) { - deployment = DEPLOYMENTS[config.environment as SupportedChainIds]; + deployment = getDeployment(config.environment as SupportedChainIds); readOnly = true; readOnlyReason = `ChainID mismatch between signer ${chainId} and configured environment ${config.environment}`; } else if (chainId && chainId === config.environment) { - deployment = DEPLOYMENTS[chainId as SupportedChainIds]; + deployment = getDeployment(chainId as SupportedChainIds); readOnly = false; readOnlyReason = undefined; } // If the config provided enables unsafeForceOverrideConfig, we can use that to get the deployment if (config.unsafeForceOverrideConfig) { - if (!config.chainId || !config.chainName || !config.contractAddress || !config.graphUrl) { - throw new UnsupportedChainError( - `attempted to override with chainId=${config.chainId}, but requires chainName, graphUrl, and contractAddress to be set`, - { chainID: config.chainId?.toString() || "undefined" }, - ); - } - deployment = { - chainId: config.chainId, - chainName: config.chainName, - contractAddress: config.contractAddress, - graphUrl: config.graphUrl, - unsafeForceOverrideConfig: config.unsafeForceOverrideConfig, - }; + deployment = { ...deployment, ...getDeploymentFromOverrides(config) }; } // TODO execute validations @@ -153,8 +136,9 @@ export const getWritableConfig = async (config: Partial) }; const checkOnMissingValues = (config: Partial) => { + const allowMissing = ["easContractAddress", "readOnlyReason"]; for (const [key, value] of Object.entries(config)) { - if (!value) { + if (!value && !allowMissing.includes(key)) { logger.warn(`Missing value in client config. ${key} is possibly undefined`); } } @@ -166,13 +150,58 @@ const getChaindId = async (operator?: Operator) => { return undefined; } else if (ethers.providers.Provider.isProvider(operator)) { chainId = await operator.getNetwork().then((network) => network.chainId); - } else { - chainId = await operator.getChainId().then((chainId) => chainId); + } else if (ethers.Signer.isSigner(operator)) { + chainId = await (operator as Signer).getChainId().then((chainId) => chainId); } return chainId; }; +const getDeployment = (chainId: SupportedChainIds) => { + return deployments[chainId]; +}; + +const getDeploymentFromOverrides = (overrides: Partial) => { + let deployment; + if (overrides.unsafeForceOverrideConfig) { + if (!overrides.chainId || !overrides.chainName || !overrides.contractAddress || !overrides.graphUrl) { + throw new InvalidOrMissingError( + `attempted to override with chainId=${overrides.chainId}, but requires chainId, chainName, graphUrl, and contractAddress to be set`, + { + chainID: overrides.chainId, + chainName: overrides.chainName, + contractAddress: overrides.contractAddress, + graphUrl: overrides.graphUrl, + }, + ); + } + + if (!isAddress(overrides.contractAddress)) { + throw new InvalidOrMissingError("Provided contract address in overrides is not an address", { + contractAddress: overrides.contractAddress, + }); + } + + try { + new URL(overrides.graphUrl); + } catch (e) { + throw new InvalidOrMissingError("Provided graph URL in overrides is not a valid URL", { + graphUrl: overrides.graphUrl, + }); + } + + deployment = { + chainId: overrides.chainId, + chainName: overrides.chainName, + contractAddress: overrides.contractAddress, + graphUrl: overrides.graphUrl, + unsafeForceOverrideConfig: overrides.unsafeForceOverrideConfig, + }; + } + + return deployment; +}; + const getGraphUrl = (config: Partial) => { // Overrides determine Graph URL so skip the magic bits if (config.unsafeForceOverrideConfig) { @@ -192,14 +221,9 @@ const getGraphUrl = (config: Partial) => { const getOperator = (config: Partial) => { let operator: Operator; - // If no operator is provided, we don't do anything - if (!config.operator) { - return undefined; - } - // Throw an error if the provided operator is not a Provider or Signer if ( - config.operator && + !config.operator && !ethers.providers.Provider.isProvider(config.operator) && !ethers.Signer.isSigner(config.operator) ) { diff --git a/sdk/test/client.test.ts b/sdk/test/client.test.ts index 8f2ec57c..a2ad8342 100644 --- a/sdk/test/client.test.ts +++ b/sdk/test/client.test.ts @@ -4,9 +4,9 @@ import { ethers } from "ethers"; import sinon from "sinon"; import { HypercertClient, HypercertMetadata, TransferRestrictions } from "../src"; -import { AllowlistEntry, ClientError, UnsupportedChainError } from "../src/types"; +import { AllowlistEntry, ClientError, SupportedChainIds, UnsupportedChainError } from "../src/types"; -const provider = new MockProvider(); +const provider = new MockProvider({ ganacheOptions: { chain: { chainId: 5 } } }); sinon.stub(provider, "on"); describe("HypercertClient setup tests", () => { @@ -27,24 +27,25 @@ describe("HypercertClient setup tests", () => { }); it("should be able to create a new instance", async () => { - const operator = ethers.Wallet.createRandom(); + const operator = ethers.Wallet.createRandom().connect(provider); - const config = { environment: 5, operator, nftStorageToken: "test", web3StorageToken: "test" }; + const config = { environment: 5, nftStorageToken: "test", web3StorageToken: "test" }; const client = await new HypercertClient(config).connect(operator); expect(client).to.be.an.instanceOf(HypercertClient); expect(client.readonly).to.be.false; }); it("should throw an error when the chainId is not supported", () => { + const falseChainId = 1337; try { - new HypercertClient({ operator: provider, chainId: 1337 }); + new HypercertClient({ environment: falseChainId as SupportedChainIds }); expect.fail("Should throw UnsupportedChainError"); } catch (e) { expect(e).to.be.instanceOf(UnsupportedChainError); const error = e as UnsupportedChainError; - expect(error.message).to.eq("chainId=1337 is not yet supported"); - expect(Number(error.payload?.chainID)).to.eq(1337); + expect(error.message).to.eq(`No default config for environment=${falseChainId} found in SDK`); + expect(Number(error.payload?.chainID)).to.eq(falseChainId); } }); diff --git a/sdk/test/client/burn.test.ts b/sdk/test/client/burn.test.ts index 85bc16fe..6d4810f9 100644 --- a/sdk/test/client/burn.test.ts +++ b/sdk/test/client/burn.test.ts @@ -47,10 +47,11 @@ describe("burn fraction tokens in HypercertClient", () => { expect(client.readonly).toBe(false); - await client.burnClaimFraction(fractionId); + const tx = await client.burnClaimFraction(fractionId); + expect((await tx.wait()).status).toBe(1); //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(5); + expect(provider.callHistory.length).toBe(4); }); it("throws on burning fraction not owned by signer", async () => { @@ -79,7 +80,7 @@ describe("burn fraction tokens in HypercertClient", () => { //TODO determine underlying calls and mock those out. Some are provider simulation calls // Owner - expect(provider.callHistory.length).toBe(3); + expect(provider.callHistory.length).toBe(2); expect.assertions(4); }); @@ -104,9 +105,10 @@ describe("burn fraction tokens in HypercertClient", () => { expect((e as Error).message).toMatch(/invalid BigNumber string/); } - await client.burnClaimFraction(fractionId, { gasLimit: "12300000" }); + const tx = await client.burnClaimFraction(fractionId, { gasLimit: "12300000" }); + expect((await tx.wait()).status).toBe(1); //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(6); + expect(provider.callHistory.length).toBe(5); }); }); diff --git a/sdk/test/client/minting.test.ts b/sdk/test/client/minting.test.ts index 3b491e4d..c273e719 100644 --- a/sdk/test/client/minting.test.ts +++ b/sdk/test/client/minting.test.ts @@ -4,11 +4,11 @@ import { ethers } from "ethers"; import sinon from "sinon"; import { jest, test } from "@jest/globals"; -import HypercertClient from "../../src/client.js"; -import { HypercertMetadata, HypercertsStorage, formatHypercertData } from "../../src/index.js"; -import { MalformedDataError } from "../../src/types/errors.js"; -import { TransferRestrictions } from "../../src/types/hypercerts.js"; -import { getRawInputData } from "../helpers.js"; +import HypercertClient from "../../src/client"; +import { HypercertMetadata, HypercertsStorage, deployments, formatHypercertData } from "../../src"; +import { MalformedDataError } from "../../src/types/errors"; +import { TransferRestrictions } from "../../src/types/hypercerts"; +import { getRawInputData } from "../helpers"; import { HypercertMinter, HypercertMinterAbi } from "@hypercerts-org/contracts"; const mockCorrectMetadataCid = "testCID1234fkreigdm2flneb4khd7eixodagst5nrndptgezrjux7gohxcngjn67x6u"; @@ -24,10 +24,13 @@ describe("mintClaim in HypercertClient", () => { const [user, other, admin] = provider.getWallets(); const stub = sinon.stub(provider, "on"); - const minter = await deployMockContract(user, HypercertMinterAbi); + const minter = await deployMockContract(user, HypercertMinterAbi, { + address: deployments[5].contractAddress, + override: true, + }); const client = await new HypercertClient({ - chainId: 5, + environment: 5, }).connect(user); sinon.replaceGetter(client, "contract", () => minter as unknown as HypercertMinter); @@ -99,14 +102,16 @@ describe("mintClaim in HypercertClient", () => { try { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await _client.mintClaim(formattedData!, 1000, TransferRestrictions.AllowAll, { gasPrice: "FALSE_VALUE" }); + await _client.mintClaim(formattedData!, 1000, TransferRestrictions.AllowAll, { + gasPrice: "FALSE_VALUE", + }); expect.fail("Should throw Error"); } catch (e) { expect((e as Error).message).to.match(/.*invalid BigNumber string.*/); } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await _client.mintClaim(formattedData!, 1000, TransferRestrictions.AllowAll, { gasPrice: "100" }); + await _client.mintClaim(formattedData!, 1000, TransferRestrictions.AllowAll, { gasPrice: "513690687" }); expect(_provider.callHistory.length).to.equal(2); }, 10000); diff --git a/sdk/test/utils/config.test.ts b/sdk/test/utils/config.test.ts index 507cc4d3..702a46bd 100644 --- a/sdk/test/utils/config.test.ts +++ b/sdk/test/utils/config.test.ts @@ -5,26 +5,46 @@ import sinon from "sinon"; import { ConfigurationError, + Environment, HypercertClientConfig, InvalidOrMissingError, + SupportedChainIds, UnsupportedChainError, -} from "../../src/types/index.js"; -import { getReadOnlyConfig } from "../../src/utils/config"; +} from "../../src/types"; +import { getReadOnlyConfig, getWritableConfig } from "../../src/utils/config"; import { reloadEnv } from "../../test/setup-env"; +import { deployments } from "../../src"; chai.use(chaiSubset); -describe("Config: chainId and chainName", () => { - it("should throw an error when the chainId is not supported", () => { +const defaultOverrides: Partial = { + environment: 5, + chainId: 5, + chainName: "testnet", + graphUrl: "https://api.example.com", + contractAddress: "0x1234567890123456789012345678901234567890", + unsafeForceOverrideConfig: true, +}; + +describe("Config: environment", () => { + it("should throw an error when the environment is not supported", () => { + const falseEnvironment = "DEGEN_COUNTRY" as Environment; try { - getReadOnlyConfig({ chainId: 1337 }); + getReadOnlyConfig({ environment: falseEnvironment }); expect.fail("Should throw UnsupportedChainError"); } catch (e) { expect(e instanceof UnsupportedChainError).to.be.true; const error = e as UnsupportedChainError; - expect(error.message).to.eq("chainId=1337 is not yet supported"); + expect(error.message).to.eq(`No default config for environment=${falseEnvironment} found in SDK`); } }); + + it("should return the environment according to the chainId provided", () => { + const environment = 5 as Environment; + const config = getReadOnlyConfig({ environment }); + const expectedDeployment = deployments[5]; + expect(config).to.deep.include(expectedDeployment); + }); }); describe("Config: contractAddress", () => { @@ -35,14 +55,18 @@ describe("Config: contractAddress", () => { }); it("should return the contract address specified by overrides", () => { - const overrides: Partial = { contractAddress: "0x1234567890123456789012345678901234567890" }; - const config = getReadOnlyConfig(overrides); - expect(config.contractAddress).to.equal(overrides.contractAddress); + const config = getReadOnlyConfig(defaultOverrides); + expect(config.contractAddress).to.equal(defaultOverrides.contractAddress); }); it("should throw an error when the contract address specified by overrides is invalid", () => { - const overrides: Partial = { contractAddress: "invalid-address" }; - expect(() => getReadOnlyConfig(overrides)).to.throw(InvalidOrMissingError, "Invalid contract address"); + try { + getReadOnlyConfig({ ...defaultOverrides, contractAddress: "invalid-address" }); + expect.fail("Should throw UnsupportedChainError"); + } catch (e) { + expect(e instanceof InvalidOrMissingError).to.be.true; + expect((e as Error).message).to.eq("Provided contract address in overrides is not an address"); + } }); }); @@ -51,184 +75,180 @@ describe("Config: graphUrl", () => { reloadEnv(); }); - it("should return the default graphUrl when no overrides are specified", () => { - const result = getReadOnlyConfig({}); - expect(result.graphUrl).to.equal("https://api.thegraph.com/subgraphs/name/hypercerts-admin/hypercerts-testnet"); + it("should return the default graphUrl for the environment when no overrides are specified", () => { + const result = getReadOnlyConfig({ environment: 5 }); + expect(result.graphUrl).to.equal(deployments[5].graphUrl); }); it("should return the config specified by overrides", () => { - const overrides: Partial = { - chainName: "testnet", - graphUrl: "https://api.example.com", - contractAddress: "0x1234567890123456789012345678901234567890", - unsafeForceOverrideConfig: true, - }; - const result = getReadOnlyConfig(overrides); - expect(result.graphUrl).to.equal(overrides.graphUrl); + const result = getReadOnlyConfig(defaultOverrides); + expect(result.graphUrl).to.equal(defaultOverrides.graphUrl); }); it("should throw an error when the graph URL specified by overrides is invalid", () => { - const overrides: Partial = { - chainName: "testnet", - graphUrl: "incorrect-url", - contractAddress: "0x1234567890123456789012345678901234567890", - unsafeForceOverrideConfig: true, - }; - - expect(() => getReadOnlyConfig(overrides)).to.throw(ConfigurationError, "Invalid graph URL"); + try { + getReadOnlyConfig({ ...defaultOverrides, graphUrl: "incorrect-url" }); + expect.fail("Should have failed on Graph URL"); + } catch (e) { + expect(e instanceof InvalidOrMissingError).to.be.true; + expect((e as Error).message).to.equal("Provided graph URL in overrides is not a valid URL"); + } }); it("should throw an error when the graph URL specified by overrides is missing", () => { - const overrides: Partial = { - chainName: "testnet", - contractAddress: "0x1234567890123456789012345678901234567890", - unsafeForceOverrideConfig: true, - }; - expect(() => getReadOnlyConfig(overrides)).to.throw( - UnsupportedChainError, - "attempted to override with chainId=5, but requires chainName, graphUrl, and contractAddress to be set", - ); - }); -}); - -describe("Config: nftStorageToken", () => { - afterEach(() => { - sinon.restore(); - - reloadEnv(); - }); - it("should return an empty object when no overrides or environment variables are specified", () => { - sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); - - const result = getReadOnlyConfig({}); - expect(result).to.deep.include({ - nftStorageToken: "NFTSTOR", - }); - }); - - it("should return the nftStorageToken specified by overrides", () => { - const overrides: Partial = { - nftStorageToken: "NFTSTOR", - }; - const result = getReadOnlyConfig(overrides); - expect(result).to.deep.include({ - nftStorageToken: overrides.nftStorageToken, - }); - }); - - it("should return the nftStorageToken specified by the NFT_STORAGE_TOKEN environment variable", () => { - sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); - const result = getReadOnlyConfig({}); - expect(result).to.deep.include({ - nftStorageToken: "NFTSTOR", - }); - }); - - it("should return the nftStorageToken specified by the NEXT_PUBLIC_NFT_STORAGE_TOKEN environment variable", () => { - sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: "NFTSTOR" }); - - const result = getReadOnlyConfig({}); - expect(result).to.deep.include({ - nftStorageToken: "NFTSTOR", - }); - }); - - it("should not throw an error when the nftStorageToken specified by overrides is invalid", () => { - sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: null }); - - const overrides: Partial = {}; - expect(() => getReadOnlyConfig(overrides)).to.not.throw(); - }); -}); - -describe("Config: getOperator", () => { - afterEach(() => { - sinon.restore(); - - reloadEnv(); - }); - it("should return a default provider when no overrides or environment variables are specified", () => { - const result = getReadOnlyConfig({}); - //TODO: hacky solution to compare providers - expect(JSON.stringify(result.operator)).to.equal(JSON.stringify(ethers.getDefaultProvider(DEFAULT_CHAIN_ID))); - }); - - it("should return the operator specified by overrides", () => { - const provider = ethers.getDefaultProvider(DEFAULT_CHAIN_ID); - const wallet = new ethers.Wallet("0x0123456789012345678901234567890123456789012345678901234567890123", provider); - const overrides: Partial = { - operator: wallet, - }; - const result = getReadOnlyConfig(overrides); - expect(result.operator).to.equal(overrides.operator); - }); - - it("should return the operator specified by the PRIVATE_KEY environment variable", () => { - const PRIVATE_KEY = "0x0123456789012345678901234567890123456789012345678901234567890123"; - sinon.stub(process, "env").value({ PRIVATE_KEY }); - - const result = getReadOnlyConfig({}); - const provider = ethers.getDefaultProvider(DEFAULT_CHAIN_ID); - const wallet = new ethers.Wallet(PRIVATE_KEY, provider); - expect(JSON.stringify(result.operator)).to.equal(JSON.stringify(wallet)); - }); - - it("should throw an error when the operator specified by overrides is invalid", () => { - const overrides: Partial = { - operator: "invalid" as unknown as ethers.Signer, - }; - expect(() => getReadOnlyConfig(overrides)).to.throw(InvalidOrMissingError, "Invalid operator."); + try { + getReadOnlyConfig({ ...defaultOverrides, graphUrl: undefined }); + expect.fail("Should have failed on Graph URL"); + } catch (e) { + expect(e instanceof InvalidOrMissingError).to.be.true; + expect((e as Error).message).to.equal( + "attempted to override with chainId=5, but requires chainId, chainName, graphUrl, and contractAddress to be set", + ); + } }); }); -describe("Config: web3StorageToken", () => { - afterEach(() => { - sinon.restore(); - - reloadEnv(); - }); - - it("should return an empty object when no overrides or environment variables are specified", () => { - const WEB3_STORAGE_TOKEN = "WEB3"; - sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); - const result = getReadOnlyConfig({}); - expect(result).to.deep.include({ - web3StorageToken: WEB3_STORAGE_TOKEN, - }); - }); - - it("should return the web3StorageToken specified by overrides", () => { - const overrides: Partial = { - web3StorageToken: "WEB3STOR", - }; - const result = getReadOnlyConfig(overrides); - expect(result).to.deep.include({ - web3StorageToken: overrides.web3StorageToken, - }); - }); - - it("should return the web3StorageToken specified by the WEB3_STORAGE_TOKEN environment variable", () => { - const WEB3_STORAGE_TOKEN = "WEB3"; - sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); - const result = getReadOnlyConfig({}); - expect(result).to.deep.include({ - web3StorageToken: WEB3_STORAGE_TOKEN, - }); - }); - - it("should return the web3StorageToken specified by the NEXT_PUBLIC_WEB3_STORAGE_TOKEN environment variable", () => { - const NEXT_PUBLIC_WEB3_STORAGE_TOKEN = "WEB3"; - sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN }); - - const result = getReadOnlyConfig({}); - expect(result).to.deep.include({ - web3StorageToken: NEXT_PUBLIC_WEB3_STORAGE_TOKEN, - }); - }); - - it("should not throw an error when the web3StorageToken specified by overrides is invalid", () => { - sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN: null }); - const overrides: Partial = {}; - expect(() => getReadOnlyConfig(overrides)).to.not.throw(); - }); -}); +// describe("Config: nftStorageToken", () => { +// afterEach(() => { +// sinon.restore(); + +// reloadEnv(); +// }); +// it("should return an empty object when no overrides or environment variables are specified", () => { +// sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); + +// const result = getReadOnlyConfig({}); +// expect(result).to.deep.include({ +// nftStorageToken: "NFTSTOR", +// }); +// }); + +// it("should return the nftStorageToken specified by overrides", () => { +// const overrides: Partial = { +// nftStorageToken: "NFTSTOR", +// }; +// const result = getReadOnlyConfig(overrides); +// expect(result).to.deep.include({ +// nftStorageToken: overrides.nftStorageToken, +// }); +// }); + +// it("should return the nftStorageToken specified by the NFT_STORAGE_TOKEN environment variable", () => { +// sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); +// const result = getReadOnlyConfig({}); +// expect(result).to.deep.include({ +// nftStorageToken: "NFTSTOR", +// }); +// }); + +// it("should return the nftStorageToken specified by the NEXT_PUBLIC_NFT_STORAGE_TOKEN environment variable", () => { +// sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: "NFTSTOR" }); + +// const result = getReadOnlyConfig({}); +// expect(result).to.deep.include({ +// nftStorageToken: "NFTSTOR", +// }); +// }); + +// it("should not throw an error when the nftStorageToken specified by overrides is invalid", () => { +// sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: null }); + +// const overrides: Partial = {}; +// expect(() => getReadOnlyConfig(overrides)).to.not.throw(); +// }); +// }); + +// describe("Config: getOperator", () => { +// afterEach(() => { +// sinon.restore(); + +// reloadEnv(); +// }); +// it("should not return a provider when no overrides or environment variables are specified", () => { +// try { +// const result = getWritableConfig({}); +// } catch (e) { +// expect(e instanceof InvalidOrMissingError).to.be.true; +// expect((e as Error).message).to.eq("Invalid operator."); +// } +// }); + +// it("should return the operator specified by client config", async () => { +// const overrides: Partial = { +// environment: 5, +// operator: ethers.getDefaultProvider(5), +// }; + +// const result = await getWritableConfig(overrides); +// expect(result.operator).to.equal(overrides.operator); +// }); + +// it("should return the operator specified by the PRIVATE_KEY environment variable", () => { +// const PRIVATE_KEY = "0x0123456789012345678901234567890123456789012345678901234567890123"; +// sinon.stub(process, "env").value({ PRIVATE_KEY }); + +// const result = getReadOnlyConfig({}); +// const provider = ethers.getDefaultProvider(5); +// const wallet = new ethers.Wallet(PRIVATE_KEY, provider); +// expect(JSON.stringify(result.operator)).to.equal(JSON.stringify(wallet)); +// }); + +// it("should throw an error when the operator specified by overrides is invalid", () => { +// const overrides: Partial = { +// operator: "invalid" as unknown as ethers.Signer, +// }; +// expect(() => getReadOnlyConfig(overrides)).to.throw(InvalidOrMissingError, "Invalid operator."); +// }); +// }); + +// describe("Config: web3StorageToken", () => { +// afterEach(() => { +// sinon.restore(); + +// reloadEnv(); +// }); + +// it("should return an empty object when no overrides or environment variables are specified", () => { +// const WEB3_STORAGE_TOKEN = "WEB3"; +// sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); +// const result = getReadOnlyConfig({}); +// expect(result).to.deep.include({ +// web3StorageToken: WEB3_STORAGE_TOKEN, +// }); +// }); + +// it("should return the web3StorageToken specified by overrides", () => { +// const overrides: Partial = { +// web3StorageToken: "WEB3STOR", +// }; +// const result = getReadOnlyConfig(overrides); +// expect(result).to.deep.include({ +// web3StorageToken: overrides.web3StorageToken, +// }); +// }); + +// it("should return the web3StorageToken specified by the WEB3_STORAGE_TOKEN environment variable", () => { +// const WEB3_STORAGE_TOKEN = "WEB3"; +// sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); +// const result = getReadOnlyConfig({}); +// expect(result).to.deep.include({ +// web3StorageToken: WEB3_STORAGE_TOKEN, +// }); +// }); + +// it("should return the web3StorageToken specified by the NEXT_PUBLIC_WEB3_STORAGE_TOKEN environment variable", () => { +// const NEXT_PUBLIC_WEB3_STORAGE_TOKEN = "WEB3"; +// sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN }); + +// const result = getReadOnlyConfig({}); +// expect(result).to.deep.include({ +// web3StorageToken: NEXT_PUBLIC_WEB3_STORAGE_TOKEN, +// }); +// }); + +// it("should not throw an error when the web3StorageToken specified by overrides is invalid", () => { +// sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN: null }); +// const overrides: Partial = {}; +// expect(() => getReadOnlyConfig(overrides)).to.not.throw(); +// }); +// }); From a9c7e44ea2d6dde15089c7bf66b0d5a006bd8ffa Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Tue, 31 Oct 2023 17:35:12 +0100 Subject: [PATCH 19/49] feat(test): uncommented all SDK tests --- sdk/src/client.ts | 39 ++-- sdk/src/types/client.ts | 10 +- sdk/src/utils/config.ts | 54 +++--- sdk/test/client.test.ts | 4 +- sdk/test/client/allowlist.minting.test.ts | 6 +- sdk/test/client/burn.test.ts | 39 ++-- sdk/test/client/minting.test.ts | 3 +- sdk/test/client/split.merge.test.ts | 172 +++++++---------- sdk/test/evaluations/easEvaluator.test.ts | 8 +- sdk/test/storage/nft.storage.test.ts | 5 +- sdk/test/storage/web3.storage.test.ts | 5 +- sdk/test/utils/config.test.ts | 224 ++++++++-------------- 12 files changed, 233 insertions(+), 336 deletions(-) diff --git a/sdk/src/client.ts b/sdk/src/client.ts index 76d8ccea..d70ffeb2 100644 --- a/sdk/src/client.ts +++ b/sdk/src/client.ts @@ -1,6 +1,6 @@ import { HypercertMinter, HypercertMinterAbi } from "@hypercerts-org/contracts"; import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; -import { BigNumber, BigNumberish, BytesLike, ContractTransaction, ethers, providers } from "ethers"; +import { BigNumber, BigNumberish, BytesLike, ContractTransaction, ethers } from "ethers"; import HypercertEvaluator from "./evaluations"; import HypercertIndexer from "./indexer"; @@ -15,7 +15,6 @@ import { MalformedDataError, TransferRestrictions, Operator, - SupportedChainIds, } from "./types/index"; import { getWritableConfig, getReadOnlyConfig } from "./utils/config"; import logger from "./utils/logger"; @@ -213,11 +212,11 @@ export default class HypercertClient implements HypercertClientInterface { * Split a Hypercert's unit into multiple claims with the given fractions * @dev Submit the ID of the claim to split and new fraction values. * @notice The sum of the fractions must be equal to the total units of the claim - * @param claimId - Hypercert claim id - * @param fractions - Fractions of the Hypercert claim to split + * @param fractionId - Hypercert claim id + * @param newFractions - Fractions of the Hypercert claim to split * @returns Contract transaction */ - splitClaimUnits = async (claimId: BigNumberish, fractions: BigNumberish[], overrides?: ethers.Overrides) => { + splitFractionUnits = async (fractionId: BigNumberish, newFractions: BigNumberish[], overrides?: ethers.Overrides) => { this.checkWritable(); const contract = this.contract; @@ -229,29 +228,29 @@ export default class HypercertClient implements HypercertClientInterface { } const signerAddress = await this._config.operator.getAddress(); + const claimOwner = await contract.ownerOf(fractionId); - const claimOwner = await contract.ownerOf(claimId); if (claimOwner.toLowerCase() !== signerAddress.toLowerCase()) throw new ClientError("Claim is not owned by the signer", { signer: signerAddress, claimOwner }); // check if the sum of the fractions is equal to the total units - const totalUnits = await contract["unitsOf(uint256)"](claimId); - const sumFractions = fractions.reduce((a, b) => BigNumber.from(a).add(b), BigNumber.from(0)); + const totalUnits = await contract["unitsOf(uint256)"](fractionId); + const sumFractions = newFractions.reduce((a, b) => BigNumber.from(a).add(b), BigNumber.from(0)); if (!BigNumber.from(sumFractions).eq(totalUnits)) throw new ClientError("Sum of fractions is not equal to the total units", { totalUnits, sumFractions }); return overrides - ? contract.splitFraction(signerAddress, claimId, fractions, overrides) - : contract.splitFraction(signerAddress, claimId, fractions); + ? contract.splitFraction(signerAddress, fractionId, newFractions, overrides) + : contract.splitFraction(signerAddress, fractionId, newFractions); }; /** * Merge multiple Hypercert claims fractions into one * @dev Merges multiple Hypercert claims into one - * @param claimIds - Hypercert claim ids + * @param fractionIds - Hypercert claim ids * @returns Contract transaction */ - mergeClaimUnits = async (claimIds: BigNumberish[], overrides?: ethers.Overrides) => { + mergeClaimFractions = async (fractionIds: BigNumberish[], overrides?: ethers.Overrides) => { this.checkWritable(); const contract = this.contract; @@ -264,7 +263,7 @@ export default class HypercertClient implements HypercertClientInterface { const signerAddress = await this._config.operator.getAddress(); - const claims = await Promise.all(claimIds.map(async (id) => ({ id, owner: await contract.ownerOf(id) }))); + const claims = await Promise.all(fractionIds.map(async (id) => ({ id, owner: await contract.ownerOf(id) }))); if (claims.some((c) => c.owner.toLowerCase() !== signerAddress.toLowerCase())) { const invalidClaimIDs = claims.filter((c) => c.owner !== signerAddress).map((c) => c.id); throw new ClientError("One or more claims are not owned by the signer", { @@ -274,17 +273,17 @@ export default class HypercertClient implements HypercertClientInterface { } return overrides - ? contract.mergeFractions(signerAddress, claimIds, overrides) - : contract.mergeFractions(signerAddress, claimIds); + ? contract.mergeFractions(signerAddress, fractionIds, overrides) + : contract.mergeFractions(signerAddress, fractionIds); }; /** * Burn a Hypercert claim by providing the claim id * @dev Burns a Hypercert claim - * @param claimId - Hypercert claim id + * @param fractionId - Hypercert claim id * @returns Contract transaction */ - burnClaimFraction = async (claimId: BigNumberish, overrides?: ethers.Overrides) => { + burnClaimFraction = async (fractionId: BigNumberish, overrides?: ethers.Overrides) => { this.checkWritable(); const contract = this.contract; @@ -296,13 +295,13 @@ export default class HypercertClient implements HypercertClientInterface { } const signerAddress = await this._config.operator.getAddress(); - const claimOwner = await contract.ownerOf(claimId); + const claimOwner = await contract.ownerOf(fractionId); if (claimOwner.toLowerCase() !== signerAddress.toLowerCase()) throw new ClientError("Claim is not owned by the signer", { signer: signerAddress, claimOwner }); return overrides - ? contract.burnFraction(signerAddress, claimId, overrides) - : contract.burnFraction(signerAddress, claimId); + ? contract.burnFraction(signerAddress, fractionId, overrides) + : contract.burnFraction(signerAddress, fractionId); }; /** diff --git a/sdk/src/types/client.ts b/sdk/src/types/client.ts index 72065f20..82f29027 100644 --- a/sdk/src/types/client.ts +++ b/sdk/src/types/client.ts @@ -170,25 +170,25 @@ export interface HypercertClientMethods { /** * Splits a claim into multiple fractions. - * @param claimId The ID of the claim to split. - * @param fractions The number of units for each fraction. + * @param fractionId The ID of the claim to split. + * @param newFractions The number of units for each fraction. * @returns A Promise that resolves to the transaction receipt */ - splitClaimUnits: (claimId: BigNumberish, fractions: BigNumberish[]) => Promise; + splitFractionUnits: (fractionId: BigNumberish, newFractions: BigNumberish[]) => Promise; /** * Merges multiple claim fractions into a single claim. * @param claimIds The IDs of the claim fractions to merge. * @returns A Promise that resolves to the transaction receipt */ - mergeClaimUnits: (claimIds: BigNumberish[]) => Promise; + mergeClaimFractions: (fractionIds: BigNumberish[]) => Promise; /** * Burns a claim fraction. * @param claimId The ID of the claim fraction to burn. * @returns A Promise that resolves to the transaction receipt */ - burnClaimFraction: (claimId: BigNumberish) => Promise; + burnClaimFraction: (fractionId: BigNumberish) => Promise; /** * Mints a claim fraction from an allowlist. diff --git a/sdk/src/utils/config.ts b/sdk/src/utils/config.ts index 03aea857..944e4497 100644 --- a/sdk/src/utils/config.ts +++ b/sdk/src/utils/config.ts @@ -16,7 +16,9 @@ import { isAddress } from "ethers/lib/utils"; * Returns the configuration for the Hypercert client, based on the given overrides. * @param overrides An object containing overrides for the default configuration. * @returns The configuration for the Hypercert client. - * @throws An `UnsupportedChainError` if the chain ID is not 5 or 10, or if the chain ID is missing or not found. + * @throws An `ConfigurationError` if the `environment` in `config` is not a supported environment, or if the chain ID was not found. + * @dev 5, 10, 42220, 11155111 and "test", "production" are supported environments. + * Test and production merge the Graphs by environment, while the chain IDs are specific to the chain. */ export const getReadOnlyConfig = (config: Partial) => { let deployment; @@ -60,6 +62,7 @@ export const getReadOnlyConfig = (config: Partial) => { } as HypercertClientConfig; checkOnMissingValues(_config); + checkOnRequiredValues(_config); return _config; }; @@ -68,7 +71,9 @@ export const getReadOnlyConfig = (config: Partial) => { * Returns the configuration for the Hypercert client, based on the given overrides. * @param overrides An object containing overrides for the default configuration. * @returns The configuration for the Hypercert client. - * @throws An `UnsupportedChainError` if the chain ID is not 5 or 10, or if the chain ID is missing or not found. + * @throws An `ConfigurationError` if the `environment` in `config` is not a supported environment, or if the chain ID was not found. + * @dev 5, 10, 42220, 11155111 and "test", "production" are supported environments. + * Test and production merge the Graphs by environment, while the chain IDs are specific to the chain. */ export const getWritableConfig = async (config: Partial) => { let deployment; @@ -82,6 +87,11 @@ export const getWritableConfig = async (config: Partial) ); } + // Need to get an provider for the writeable bits + if (!config.operator || !ethers.Signer.isSigner(config.operator)) { + throw new ConfigurationError("An operator must be provided to sign and submit transactions"); + } + // If we know the chainID from the operator or the config, we can use that to get the deployment const chainId = await getChaindId(config?.operator); @@ -106,16 +116,6 @@ export const getWritableConfig = async (config: Partial) deployment = { ...deployment, ...getDeploymentFromOverrides(config) }; } - // TODO execute validations - // else { - // if (!Object.values(SupportedChainIds).includes(deployment?.chainId as SupportedChainIds)) { - // throw new UnsupportedChainError(`Default config for chainId=${deployment?.chainId} is missing in SDK`, { - // chainID: deployment?.chainId, - // }); - // } - // } - // - const _config = { ...config, // Start with the hardcoded values @@ -131,6 +131,7 @@ export const getWritableConfig = async (config: Partial) } as HypercertClientConfig; checkOnMissingValues(_config); + checkOnRequiredValues(_config); return _config; }; @@ -144,6 +145,15 @@ const checkOnMissingValues = (config: Partial) => { } }; +const checkOnRequiredValues = (config: Partial) => { + const required = ["environment", "graphUrl"]; + for (const [key, value] of Object.entries(config)) { + if (!value && required.includes(key)) { + throw new InvalidOrMissingError(`Missing or incorrect ${key}`, Object.fromEntries([[key, value]])); + } + } +}; + const getChaindId = async (operator?: Operator) => { let chainId; if (!operator) { @@ -257,27 +267,13 @@ const getOperator = (config: Partial) => { }; export const getNftStorageToken = (overrides: Partial) => { - if (overrides.nftStorageToken) { - return overrides.nftStorageToken; - } - - if (process.env.NFT_STORAGE_TOKEN) { - return process.env.NFT_STORAGE_TOKEN; - } + return overrides.nftStorageToken; }; export const getWeb3StorageToken = (overrides: Partial) => { - if (overrides.web3StorageToken) { - return overrides.web3StorageToken; - } - - if (process.env.WEB3_STORAGE_TOKEN) { - return process.env.WEB3_STORAGE_TOKEN; - } + return overrides.web3StorageToken; }; const getEasContractAddress = (overrides: Partial) => { - if (overrides.easContractAddress) { - return overrides.easContractAddress; - } + return overrides.easContractAddress; }; diff --git a/sdk/test/client.test.ts b/sdk/test/client.test.ts index a2ad8342..7205db9f 100644 --- a/sdk/test/client.test.ts +++ b/sdk/test/client.test.ts @@ -95,7 +95,7 @@ describe("HypercertClient setup tests", () => { const claimId = 1; const fractions = [100, 200]; - await client.splitClaimUnits(claimId, fractions); + await client.splitFractionUnits(claimId, fractions); expect.fail("Should throw ClientError"); } catch (e) { expect(e).to.be.instanceOf(ClientError); @@ -109,7 +109,7 @@ describe("HypercertClient setup tests", () => { try { const claimIds = [1, 2]; - await client.mergeClaimUnits(claimIds); + await client.mergeClaimFractions(claimIds); expect.fail("Should throw ClientError"); } catch (e) { expect(e).to.be.instanceOf(ClientError); diff --git a/sdk/test/client/allowlist.minting.test.ts b/sdk/test/client/allowlist.minting.test.ts index 7c805790..32616533 100644 --- a/sdk/test/client/allowlist.minting.test.ts +++ b/sdk/test/client/allowlist.minting.test.ts @@ -3,9 +3,9 @@ import { BigNumber, ethers } from "ethers"; import sinon from "sinon"; import { expect } from "@jest/globals"; -import { HypercertClient, deployments } from "../../src/index"; +import { HypercertClient, deployments } from "../../src"; import HypercertsStorage from "../../src/storage"; -import { MalformedDataError, MintingError, TransferRestrictions } from "../../src/types/index"; +import { MalformedDataError, MintingError, TransferRestrictions } from "../../src/types"; import { getAllowlist, getFormattedMetadata } from "../helpers"; import { HypercertMinter, HypercertMinterAbi } from "@hypercerts-org/contracts"; const mockCorrectMetadataCid = "testCID1234fkreigdm2flneb4khd7eixodagst5nrndptgezrjux7gohxcngjn67x6u"; @@ -30,6 +30,8 @@ describe("Allows for minting claims from an allowlist", () => { const client = await new HypercertClient({ environment: 5, + nftStorageToken: process.env.NFT_STORAGE_TOKEN, + web3StorageToken: process.env.WEB3_STORAGE_TOKEN, }).connect(user); sinon.replaceGetter(client, "contract", () => minter as unknown as HypercertMinter); diff --git a/sdk/test/client/burn.test.ts b/sdk/test/client/burn.test.ts index 6d4810f9..ec4486b1 100644 --- a/sdk/test/client/burn.test.ts +++ b/sdk/test/client/burn.test.ts @@ -32,19 +32,27 @@ describe("burn fraction tokens in HypercertClient", () => { stub.restore(); }); - it("allows for a hypercert fraction to be burned", async () => { + const setUp = async () => { const userAddress = await user.getAddress(); const mockMinter = await deployMockContract(user, HypercertMinterAbi, { address: deployments[5].contractAddress, override: true, }); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock["burnFraction(address,uint256)"].withArgs(userAddress, fractionId).returns(); const client = await new HypercertClient({ - environment: 5, + environment: (await provider.getNetwork()).chainId, + nftStorageToken: process.env.NFT_STORAGE_TOKEN, + web3StorageToken: process.env.WEB3_STORAGE_TOKEN, }).connect(user); + return { userAddress, user, minter: mockMinter, client }; + }; + + it("allows for a hypercert fraction to be burned", async () => { + const { userAddress, minter, client } = await setUp(); + await minter.mock.ownerOf.withArgs(fractionId).returns(userAddress); + await minter.mock["burnFraction(address,uint256)"].withArgs(userAddress, fractionId).returns(); + expect(client.readonly).toBe(false); const tx = await client.burnClaimFraction(fractionId); @@ -56,15 +64,9 @@ describe("burn fraction tokens in HypercertClient", () => { it("throws on burning fraction not owned by signer", async () => { const otherUser = await other.getAddress(); - const mockMinter = await deployMockContract(user, HypercertMinterAbi, { - address: deployments[5].contractAddress, - override: true, - }); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(otherUser); + const { minter, client } = await setUp(); - const client = await new HypercertClient({ - environment: 5, - }).connect(user); + await minter.mock.ownerOf.withArgs(fractionId).returns(otherUser); expect(client.readonly).toBe(false); @@ -85,17 +87,10 @@ describe("burn fraction tokens in HypercertClient", () => { }); it("allows for a hypercert fraction to be burned with override params", async () => { - const userAddress = await user.getAddress(); - const mockMinter = await deployMockContract(user, HypercertMinterAbi, { - address: deployments[5].contractAddress, - override: true, - }); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock["burnFraction(address,uint256)"].withArgs(userAddress, fractionId).returns(); + const { userAddress, minter, client } = await setUp(); - const client = await new HypercertClient({ - environment: 5, - }).connect(user); + await minter.mock.ownerOf.withArgs(fractionId).returns(userAddress); + await minter.mock["burnFraction(address,uint256)"].withArgs(userAddress, fractionId).returns(); expect(client.readonly).toBe(false); diff --git a/sdk/test/client/minting.test.ts b/sdk/test/client/minting.test.ts index c273e719..bc042618 100644 --- a/sdk/test/client/minting.test.ts +++ b/sdk/test/client/minting.test.ts @@ -2,7 +2,6 @@ import { expect } from "chai"; import { MockContract, MockProvider, deployMockContract } from "ethereum-waffle"; import { ethers } from "ethers"; import sinon from "sinon"; -import { jest, test } from "@jest/globals"; import HypercertClient from "../../src/client"; import { HypercertMetadata, HypercertsStorage, deployments, formatHypercertData } from "../../src"; @@ -31,6 +30,8 @@ describe("mintClaim in HypercertClient", () => { const client = await new HypercertClient({ environment: 5, + nftStorageToken: process.env.NFT_STORAGE_TOKEN, + web3StorageToken: process.env.WEB3_STORAGE_TOKEN, }).connect(user); sinon.replaceGetter(client, "contract", () => minter as unknown as HypercertMinter); diff --git a/sdk/test/client/split.merge.test.ts b/sdk/test/client/split.merge.test.ts index 3ac67ab4..ba6cfff8 100644 --- a/sdk/test/client/split.merge.test.ts +++ b/sdk/test/client/split.merge.test.ts @@ -11,7 +11,7 @@ import { deployments } from "../../src"; describe("splitClaimUnits in HypercertClient", () => { let stub: sinon.SinonStub; let provider: MockProvider; - let wallet: Wallet; + let user: Wallet; const fractionId = BigNumber.from("9868188640707215440437863615521278132232"); beforeAll(() => { @@ -20,7 +20,7 @@ describe("splitClaimUnits in HypercertClient", () => { chain: { chainId: 5 }, }, }); - wallet = provider.getWallets()[0]; + user = provider.getWallets()[0]; stub = sinon.stub(provider, "on"); }); @@ -32,27 +32,33 @@ describe("splitClaimUnits in HypercertClient", () => { stub.restore(); }); - it("allows for a hypercert fractions to be splitted over value", async () => { - const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { + const setUp = async () => { + const userAddress = await user.getAddress(); + const mockMinter = await deployMockContract(user, HypercertMinterAbi, { address: deployments[5].contractAddress, override: true, }); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(300); - await mockMinter.mock["splitFraction(address,uint256,uint256[])"] - .withArgs(userAddress, fractionId, [100, 200]) - .returns(); - - const signer = wallet.connect(provider); const client = await new HypercertClient({ - environment: 5, - }).connect(signer); + environment: (await provider.getNetwork()).chainId, + nftStorageToken: process.env.NFT_STORAGE_TOKEN, + web3StorageToken: process.env.WEB3_STORAGE_TOKEN, + }).connect(user); + + return { userAddress, user, minter: mockMinter, client }; + }; + + it("allows for a hypercert fractions to be splitted over value", async () => { + const { userAddress, minter, client } = await setUp(); + await minter.mock.ownerOf.withArgs(fractionId).returns(userAddress); + await minter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(300); + await minter.mock["splitFraction(address,uint256,uint256[])"] + .withArgs(userAddress, fractionId, [100, 200]) + .returns(); expect(client.readonly).toBe(false); - const tx = await client.splitClaimUnits(fractionId, [100, 200]); + const tx = await client.splitFractionUnits(fractionId, [100, 200]); expect((await tx.wait()).status).toBe(1); //TODO determine underlying calls and mock those out. Some are provider simulation calls @@ -60,34 +66,25 @@ describe("splitClaimUnits in HypercertClient", () => { }, 10000); it("allows for a hypercert fractions to be splitted over value with override params", async () => { - const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { - address: deployments[5].contractAddress, - override: true, - }); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(300); - await mockMinter.mock["splitFraction(address,uint256,uint256[])"] + const { userAddress, minter, client } = await setUp(); + + await minter.mock.ownerOf.withArgs(fractionId).returns(userAddress); + await minter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(300); + await minter.mock["splitFraction(address,uint256,uint256[])"] .withArgs(userAddress, fractionId, [100, 200]) .returns(); - const signer = wallet.connect(provider); - - const client = await new HypercertClient({ - environment: 5, - }).connect(signer); - expect(client.readonly).toBe(false); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion try { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await client.splitClaimUnits(fractionId, [100, 200], { gasLimit: "FALSE_VALUE" }); + await client.splitFractionUnits(fractionId, [100, 200], { gasLimit: "FALSE_VALUE" }); } catch (e) { expect((e as Error).message).toMatch(/invalid BigNumber string/); } - const tx = await client.splitClaimUnits(fractionId, [100, 200], { gasLimit: "12300000" }); + const tx = await client.splitFractionUnits(fractionId, [100, 200], { gasLimit: "12300000" }); expect((await tx.wait()).status).toBe(1); //TODO determine underlying calls and mock those out. Some are provider simulation calls @@ -95,25 +92,15 @@ describe("splitClaimUnits in HypercertClient", () => { }, 10000); it("throws on splitting with incorrect new total value", async () => { - const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { - address: deployments[5].contractAddress, - override: true, - }); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(42); - - const signer = wallet.connect(provider); + const { userAddress, minter, client } = await setUp(); - const client = await new HypercertClient({ - environment: 5, - }).connect(signer); + await minter.mock.ownerOf.withArgs(fractionId).returns(userAddress); + await minter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(42); expect(client.readonly).toBe(false); try { - const tx = await client.splitClaimUnits(fractionId, [100, 200]); - expect((await tx.wait()).status).toBe(1); + await client.splitFractionUnits(fractionId, [100, 200]); } catch (e) { expect(e instanceof ClientError).toBeTruthy(); @@ -129,24 +116,15 @@ describe("splitClaimUnits in HypercertClient", () => { }); it("throws on splitting fractions not owned by signer", async () => { - const otherUser = await provider.getWallets()[1].getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { - address: deployments[5].contractAddress, - override: true, - }); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(otherUser); - - const signer = wallet.connect(provider); + const { minter, client } = await setUp(); - const client = await new HypercertClient({ - environment: 5, - }).connect(signer); + const otherUser = await provider.getWallets()[1].getAddress(); + await minter.mock.ownerOf.withArgs(fractionId).returns(otherUser); expect(client.readonly).toBe(false); try { - const tx = await client.splitClaimUnits(fractionId, [100, 200]); - expect((await tx.wait()).status).toBe(1); + await client.splitFractionUnits(fractionId, [100, 200]); } catch (e) { expect(e instanceof ClientError).toBeTruthy(); @@ -164,7 +142,7 @@ describe("splitClaimUnits in HypercertClient", () => { describe("mergeClaimUnits in HypercertClient", () => { let stub: sinon.SinonStub; let provider: MockProvider; - let wallet: Wallet; + let user: Wallet; const fractionId = BigNumber.from("9868188640707215440437863615521278132232"); beforeAll(() => { @@ -174,7 +152,7 @@ describe("mergeClaimUnits in HypercertClient", () => { }, }); - wallet = provider.getWallets()[0]; + user = provider.getWallets()[0]; stub = sinon.stub(provider, "on"); }); @@ -186,27 +164,34 @@ describe("mergeClaimUnits in HypercertClient", () => { stub.restore(); }); - it("allows for hypercert fractions to merge value", async () => { - const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { + const setUp = async () => { + const userAddress = await user.getAddress(); + const mockMinter = await deployMockContract(user, HypercertMinterAbi, { address: deployments[5].contractAddress, override: true, }); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock.ownerOf.withArgs(fractionId.add(1)).returns(userAddress); - await mockMinter.mock["mergeFractions(address,uint256[])"] - .withArgs(userAddress, [fractionId, fractionId.add(1)]) - .returns(); - - const signer = wallet.connect(provider); const client = await new HypercertClient({ - environment: 5, - }).connect(signer); + environment: (await provider.getNetwork()).chainId, + nftStorageToken: process.env.NFT_STORAGE_TOKEN, + web3StorageToken: process.env.WEB3_STORAGE_TOKEN, + }).connect(user); + + return { userAddress, user, minter: mockMinter, client }; + }; + + it("allows for hypercert fractions to merge value", async () => { + const { userAddress, minter, client } = await setUp(); + + await minter.mock.ownerOf.withArgs(fractionId).returns(userAddress); + await minter.mock.ownerOf.withArgs(fractionId.add(1)).returns(userAddress); + await minter.mock["mergeFractions(address,uint256[])"] + .withArgs(userAddress, [fractionId, fractionId.add(1)]) + .returns(); expect(client.readonly).toBe(false); - const tx = await client.mergeClaimUnits([fractionId, fractionId.add(1)]); + const tx = await client.mergeClaimFractions([fractionId, fractionId.add(1)]); expect((await tx.wait()).status).toBe(1); //TODO determine underlying calls and mock those out. Some are provider simulation calls @@ -214,34 +199,25 @@ describe("mergeClaimUnits in HypercertClient", () => { }, 10000); it("allows for hypercert fractions to merge value with override params", async () => { - const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { - address: deployments[5].contractAddress, - override: true, - }); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock.ownerOf.withArgs(fractionId.add(1)).returns(userAddress); - await mockMinter.mock["mergeFractions(address,uint256[])"] + const { userAddress, minter, client } = await setUp(); + + await minter.mock.ownerOf.withArgs(fractionId).returns(userAddress); + await minter.mock.ownerOf.withArgs(fractionId.add(1)).returns(userAddress); + await minter.mock["mergeFractions(address,uint256[])"] .withArgs(userAddress, [fractionId, fractionId.add(1)]) .returns(); - const signer = wallet.connect(provider); - - const client = await new HypercertClient({ - environment: 5, - }).connect(signer); - expect(client.readonly).toBe(false); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion try { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await client.mergeClaimUnits([fractionId, fractionId.add(1)], { gasLimit: "FALSE_VALUE" }); + await client.mergeClaimFractions([fractionId, fractionId.add(1)], { gasLimit: "FALSE_VALUE" }); } catch (e) { expect((e as Error).message).toMatch(/invalid BigNumber string/); } - const tx = await client.mergeClaimUnits([fractionId, fractionId.add(1)], { gasLimit: "12300000" }); + const tx = await client.mergeClaimFractions([fractionId, fractionId.add(1)], { gasLimit: "12300000" }); expect((await tx.wait()).status).toBe(1); //TODO determine underlying calls and mock those out. Some are provider simulation calls @@ -249,26 +225,16 @@ describe("mergeClaimUnits in HypercertClient", () => { }, 10000); it("throws on splitting fractions not owned by signer", async () => { - const userAddress = await wallet.getAddress(); + const { userAddress, minter, client } = await setUp(); const otherUser = await provider.getWallets()[1].getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi, { - address: deployments[5].contractAddress, - override: true, - }); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock.ownerOf.withArgs(fractionId.add(1)).returns(otherUser); - - const signer = wallet.connect(provider); - - const client = await new HypercertClient({ - environment: 5, - }).connect(signer); + await minter.mock.ownerOf.withArgs(fractionId).returns(userAddress); + await minter.mock.ownerOf.withArgs(fractionId.add(1)).returns(otherUser); expect(client.readonly).toBe(false); try { - const tx = await client.mergeClaimUnits([fractionId, fractionId.add(1)]); + const tx = await client.mergeClaimFractions([fractionId, fractionId.add(1)]); expect((await tx.wait()).status).toBe(1); } catch (e) { expect(e instanceof ClientError).toBeTruthy(); diff --git a/sdk/test/evaluations/easEvaluator.test.ts b/sdk/test/evaluations/easEvaluator.test.ts index 048ec024..8e735b9e 100644 --- a/sdk/test/evaluations/easEvaluator.test.ts +++ b/sdk/test/evaluations/easEvaluator.test.ts @@ -1,10 +1,10 @@ import { MockProvider } from "ethereum-waffle"; import sinon from "sinon"; -import { EAS_SCHEMAS } from "../../src/constants.js"; -import EasEvaluator from "../../src/evaluations/eas.js"; -import { HypercertClientConfig } from "../../src/index.js"; -import { DuplicateEvaluation, SimpleTextEvaluation } from "../../src/types/evaluation.js"; +import { EAS_SCHEMAS } from "../../src/constants"; +import EasEvaluator from "../../src/evaluations/eas"; +import { HypercertClientConfig } from "../../src"; +import { DuplicateEvaluation, SimpleTextEvaluation } from "../../src/types/evaluation"; describe("EasEvaluator", () => { let stub: sinon.SinonStub; diff --git a/sdk/test/storage/nft.storage.test.ts b/sdk/test/storage/nft.storage.test.ts index 5ba4fc1a..4e3ed4ff 100644 --- a/sdk/test/storage/nft.storage.test.ts +++ b/sdk/test/storage/nft.storage.test.ts @@ -30,7 +30,10 @@ describe("NFT.Storage Client", () => { }), ); - const storage = new HypercertsStorage({}); + const storage = new HypercertsStorage({ + nftStorageToken: process.env.NFT_STORAGE_TOKEN, + web3StorageToken: process.env.WEB3_STORAGE_TOKEN, + }); beforeAll(() => server.listen()); diff --git a/sdk/test/storage/web3.storage.test.ts b/sdk/test/storage/web3.storage.test.ts index 8acf5020..8178b8ae 100644 --- a/sdk/test/storage/web3.storage.test.ts +++ b/sdk/test/storage/web3.storage.test.ts @@ -28,8 +28,11 @@ describe("Web3.Storage Client", () => { return res(ctx.status(200), ctx.json(mockData)); }), ); - const storage = new HypercertsStorage({}); + const storage = new HypercertsStorage({ + nftStorageToken: process.env.NFT_STORAGE_TOKEN, + web3StorageToken: process.env.WEB3_STORAGE_TOKEN, + }); beforeAll(() => server.listen()); afterEach(() => { diff --git a/sdk/test/utils/config.test.ts b/sdk/test/utils/config.test.ts index 702a46bd..8637e45d 100644 --- a/sdk/test/utils/config.test.ts +++ b/sdk/test/utils/config.test.ts @@ -1,6 +1,5 @@ import chai, { expect } from "chai"; import chaiSubset from "chai-subset"; -import { ethers } from "ethers"; import sinon from "sinon"; import { @@ -8,12 +7,13 @@ import { Environment, HypercertClientConfig, InvalidOrMissingError, - SupportedChainIds, UnsupportedChainError, } from "../../src/types"; import { getReadOnlyConfig, getWritableConfig } from "../../src/utils/config"; import { reloadEnv } from "../../test/setup-env"; import { deployments } from "../../src"; +import { ethers } from "ethers"; +import { MockProvider } from "ethereum-waffle"; chai.use(chaiSubset); @@ -108,147 +108,79 @@ describe("Config: graphUrl", () => { }); }); -// describe("Config: nftStorageToken", () => { -// afterEach(() => { -// sinon.restore(); - -// reloadEnv(); -// }); -// it("should return an empty object when no overrides or environment variables are specified", () => { -// sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); - -// const result = getReadOnlyConfig({}); -// expect(result).to.deep.include({ -// nftStorageToken: "NFTSTOR", -// }); -// }); - -// it("should return the nftStorageToken specified by overrides", () => { -// const overrides: Partial = { -// nftStorageToken: "NFTSTOR", -// }; -// const result = getReadOnlyConfig(overrides); -// expect(result).to.deep.include({ -// nftStorageToken: overrides.nftStorageToken, -// }); -// }); - -// it("should return the nftStorageToken specified by the NFT_STORAGE_TOKEN environment variable", () => { -// sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); -// const result = getReadOnlyConfig({}); -// expect(result).to.deep.include({ -// nftStorageToken: "NFTSTOR", -// }); -// }); - -// it("should return the nftStorageToken specified by the NEXT_PUBLIC_NFT_STORAGE_TOKEN environment variable", () => { -// sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: "NFTSTOR" }); - -// const result = getReadOnlyConfig({}); -// expect(result).to.deep.include({ -// nftStorageToken: "NFTSTOR", -// }); -// }); - -// it("should not throw an error when the nftStorageToken specified by overrides is invalid", () => { -// sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: null }); - -// const overrides: Partial = {}; -// expect(() => getReadOnlyConfig(overrides)).to.not.throw(); -// }); -// }); - -// describe("Config: getOperator", () => { -// afterEach(() => { -// sinon.restore(); - -// reloadEnv(); -// }); -// it("should not return a provider when no overrides or environment variables are specified", () => { -// try { -// const result = getWritableConfig({}); -// } catch (e) { -// expect(e instanceof InvalidOrMissingError).to.be.true; -// expect((e as Error).message).to.eq("Invalid operator."); -// } -// }); - -// it("should return the operator specified by client config", async () => { -// const overrides: Partial = { -// environment: 5, -// operator: ethers.getDefaultProvider(5), -// }; - -// const result = await getWritableConfig(overrides); -// expect(result.operator).to.equal(overrides.operator); -// }); - -// it("should return the operator specified by the PRIVATE_KEY environment variable", () => { -// const PRIVATE_KEY = "0x0123456789012345678901234567890123456789012345678901234567890123"; -// sinon.stub(process, "env").value({ PRIVATE_KEY }); - -// const result = getReadOnlyConfig({}); -// const provider = ethers.getDefaultProvider(5); -// const wallet = new ethers.Wallet(PRIVATE_KEY, provider); -// expect(JSON.stringify(result.operator)).to.equal(JSON.stringify(wallet)); -// }); - -// it("should throw an error when the operator specified by overrides is invalid", () => { -// const overrides: Partial = { -// operator: "invalid" as unknown as ethers.Signer, -// }; -// expect(() => getReadOnlyConfig(overrides)).to.throw(InvalidOrMissingError, "Invalid operator."); -// }); -// }); - -// describe("Config: web3StorageToken", () => { -// afterEach(() => { -// sinon.restore(); - -// reloadEnv(); -// }); - -// it("should return an empty object when no overrides or environment variables are specified", () => { -// const WEB3_STORAGE_TOKEN = "WEB3"; -// sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); -// const result = getReadOnlyConfig({}); -// expect(result).to.deep.include({ -// web3StorageToken: WEB3_STORAGE_TOKEN, -// }); -// }); - -// it("should return the web3StorageToken specified by overrides", () => { -// const overrides: Partial = { -// web3StorageToken: "WEB3STOR", -// }; -// const result = getReadOnlyConfig(overrides); -// expect(result).to.deep.include({ -// web3StorageToken: overrides.web3StorageToken, -// }); -// }); - -// it("should return the web3StorageToken specified by the WEB3_STORAGE_TOKEN environment variable", () => { -// const WEB3_STORAGE_TOKEN = "WEB3"; -// sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); -// const result = getReadOnlyConfig({}); -// expect(result).to.deep.include({ -// web3StorageToken: WEB3_STORAGE_TOKEN, -// }); -// }); - -// it("should return the web3StorageToken specified by the NEXT_PUBLIC_WEB3_STORAGE_TOKEN environment variable", () => { -// const NEXT_PUBLIC_WEB3_STORAGE_TOKEN = "WEB3"; -// sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN }); - -// const result = getReadOnlyConfig({}); -// expect(result).to.deep.include({ -// web3StorageToken: NEXT_PUBLIC_WEB3_STORAGE_TOKEN, -// }); -// }); - -// it("should not throw an error when the web3StorageToken specified by overrides is invalid", () => { -// sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN: null }); -// const overrides: Partial = {}; -// expect(() => getReadOnlyConfig(overrides)).to.not.throw(); -// }); -// }); +describe("Config: nftStorageToken & web3storageToken", () => { + afterEach(() => { + sinon.restore(); + + reloadEnv(); + }); + it("should not return an nftStorageToken when no overrides are specified", () => { + const result = getReadOnlyConfig({ environment: 5 }); + expect(result.nftStorageToken).to.be.undefined; + expect(result.web3StorageToken).to.be.undefined; + }); + + it("should return the nftStorageToken specified by overrides", () => { + const overrides: Partial = { + ...defaultOverrides, + nftStorageToken: "NFTSTOR", + web3StorageToken: "WEB3STOR", + }; + const result = getReadOnlyConfig(overrides); + expect(result).to.deep.include({ + nftStorageToken: overrides.nftStorageToken, + web3StorageToken: overrides.web3StorageToken, + }); + }); +}); + +describe("Config: getOperator", () => { + afterEach(() => { + sinon.restore(); + + reloadEnv(); + }); + it("should not return a provider when no overrides or environment variables are specified", async () => { + try { + await getWritableConfig(defaultOverrides); + } catch (e) { + expect(e instanceof ConfigurationError).to.be.true; + expect((e as Error).message).to.eq("An operator must be provided to sign and submit transactions"); + } + }); + + it("should return the operator specified by client config", async () => { + const chainIdStub = sinon.stub(ethers.Signer.prototype, "getChainId").resolves(5); + const provider = new MockProvider({ + ganacheOptions: { + chain: { chainId: 5 }, + }, + }); + + const signer = ethers.Wallet.createRandom().connect(provider); + + const overrides: Partial = { + ...defaultOverrides, + operator: signer, + }; + + const result = await getWritableConfig(overrides); + console.log(result); + expect(result.operator).to.not.be.undefined; + }); + + it("should throw an error when the operator specified by overrides is invalid", async () => { + const overrides: Partial = { + ...defaultOverrides, + operator: "invalid" as unknown as ethers.Signer, + }; + + try { + await getWritableConfig(overrides); + expect.fail("Should have failed on incorrect operator"); + } catch (e) { + expect(e instanceof ConfigurationError).to.be.true; + expect((e as Error).message).to.eq("An operator must be provided to sign and submit transactions"); + } + }); +}); From abb7daa00cb65e4aa01d0c17d8b7d23ddebeb5bb Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Tue, 31 Oct 2023 17:36:52 +0100 Subject: [PATCH 20/49] fix(log): remove result logging --- sdk/test/utils/config.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/test/utils/config.test.ts b/sdk/test/utils/config.test.ts index 8637e45d..d6a8e728 100644 --- a/sdk/test/utils/config.test.ts +++ b/sdk/test/utils/config.test.ts @@ -165,7 +165,6 @@ describe("Config: getOperator", () => { }; const result = await getWritableConfig(overrides); - console.log(result); expect(result.operator).to.not.be.undefined; }); From d01c7b0306eb342eb0e832dc2342eda9a662da1f Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Fri, 3 Nov 2023 16:00:02 +0100 Subject: [PATCH 21/49] [Test] Release marketplace contracts on testnet and add to contracts package (#1150) * feat(deploy): deploy to testnets * chore(build): hardhat build * feat(pack): release, test, bump updated contracts * chore(gha): updated env vars * chore(pnpm): updated lock file * fix(build): build error, replaced util with viem * fix(pnpm): root dir ethers resolution * chore(pnpm): updated lockfile * fix(pnpm): overrides * chore(build): resolving build issues sdk * chore(refactor): dep resolution bug - del eth v5 * fix(test): mock ipfs in minting, remove timeout --- .github/workflows/ci-default.yml | 4 +- contracts/.env.example | 15 +- contracts/.gitignore | 2 +- contracts/foundry.toml | 18 +- contracts/hardhat.config.ts | 80 +- contracts/package.json | 42 +- contracts/rollup.config.mjs | 4 +- contracts/scripts/deployment/Deployment.s.sol | 117 ++ .../ProtocolFeeRecipientDeployment.s.sol | 43 + contracts/src/deployments.json | 22 + contracts/src/index.ts | 60 +- .../CreatorFeeManagerWithRebates.sol | 2 +- .../CreatorFeeManagerWithRoyalties.sol | 2 +- .../src/marketplace/ProtocolFeeRecipient.sol | 2 +- contracts/src/protocol/AllowlistMinter.sol | 2 +- contracts/src/protocol/HypercertMinter.sol | 2 +- contracts/src/protocol/SemiFungible1155.sol | 2 +- .../src/protocol/interfaces/IAllowlist.sol | 2 +- .../protocol/interfaces/IHypercertToken.sol | 2 +- contracts/tasks/deploy.ts | 45 - contracts/test/HypercertMinter.test.ts | 10 +- .../marketplace/ProtocolFeeRecipient.t.sol | 2 +- .../Chainlink/USDDynamicAskOrders.t.sol | 2 +- contracts/tsconfig.build.json | 18 +- contracts/tsconfig.json | 21 +- .../v0.8/interfaces/AggregatorV3Interface.md | 77 + .../marketplace/BatchOrderTypehashRegistry.md | 46 + .../CreatorFeeManagerWithRebates.md | 76 + .../CreatorFeeManagerWithRoyalties.md | 64 + .../contracts/marketplace/CurrencyManager.md | 250 ++++ .../contracts/marketplace/ExecutionManager.md | 751 ++++++++++ .../marketplace/InheritedStrategy.md | 9 + .../marketplace/LooksRareProtocol.md | 1157 +++++++++++++++ .../api/contracts/marketplace/NonceManager.md | 193 +++ .../marketplace/ProtocolFeeRecipient.md | 75 + .../contracts/marketplace/StrategyManager.md | 391 +++++ .../contracts/marketplace/TransferManager.md | 547 +++++++ .../marketplace/TransferSelectorNFT.md | 779 ++++++++++ .../executionStrategies/BaseStrategy.md | 41 + .../BaseStrategyChainlinkPriceLatency.md | 212 +++ .../StrategyChainlinkUSDDynamicAsk.md | 342 +++++ .../StrategyCollectionOffer.md | 107 ++ .../StrategyDutchAuction.md | 83 ++ .../StrategyItemIdsRange.md | 75 + .../marketplace/helpers/OrderValidatorV2A.md | 201 +++ .../marketplace/helpers/ProtocolHelpers.md | 159 ++ .../interfaces/ICreatorFeeManager.md | 60 + .../interfaces/ICurrencyManager.md | 22 + .../interfaces/IExecutionManager.md | 99 ++ .../interfaces/IImmutableCreate2Factory.md | 22 + .../interfaces/ILooksRareProtocol.md | 157 ++ .../marketplace/interfaces/INonceManager.md | 53 + .../interfaces/IRoyaltyFeeRegistry.md | 29 + .../marketplace/interfaces/IStrategy.md | 41 + .../interfaces/IStrategyManager.md | 84 ++ .../interfaces/ITransferManager.md | 111 ++ .../libraries/CurrencyValidator.md | 7 + .../MerkleProofCalldataWithNodes.md | 7 + .../OpenZeppelin/MerkleProofMemory.md | 7 + .../marketplace/libraries/OrderStructs.md | 7 + .../api/contracts/protocol/AllowlistMinter.md | 84 ++ .../api/contracts/protocol/HypercertMinter.md | 895 ++++++++++++ .../contracts/protocol/SemiFungible1155.md | 457 ++++++ .../protocol/interfaces/IAllowlist.md | 29 + .../protocol/interfaces/IHypercertToken.md | 192 +++ .../api/contracts/protocol/libs/Errors.md | 59 + frontend/lib/parse-blockchain-error.ts | 13 +- graph/tests/.latest.json | 2 +- package.json | 9 +- pnpm-lock.yaml | 1278 ++++++++++------- pnpm-workspace.yaml | 2 +- sdk/.graphclient/index.ts | 3 +- sdk/jest.config.ts | 1 + sdk/package.json | 15 +- sdk/src/client.ts | 303 ++-- sdk/src/constants.ts | 12 +- sdk/src/evaluations/eas.ts | 155 -- sdk/src/evaluations/index.ts | 49 +- sdk/src/index.ts | 6 +- sdk/src/indexer.ts | 4 +- sdk/src/storage.ts | 17 +- sdk/src/types/client.ts | 60 +- sdk/src/types/hypercerts.ts | 4 +- sdk/src/utils/adapters.ts | 41 + sdk/src/utils/config.ts | 185 +-- sdk/src/validator/index.ts | 15 +- sdk/test/client.test.ts | 65 +- sdk/test/client/allowlist.minting.test.ts | 240 ++-- sdk/test/client/burn.test.ts | 126 +- sdk/test/client/minting.test.ts | 123 +- sdk/test/client/split.merge.test.ts | 411 +++--- sdk/test/evaluations/easEvaluator.test.ts | 90 -- sdk/test/evaluations/evaluator.test.ts | 72 +- sdk/test/helpers.ts | 105 +- sdk/test/indexer.test.ts | 2 +- sdk/test/resources/HypercertMinter.json | 1139 +++++++++++++++ sdk/test/setup-env.ts | 10 + sdk/test/storage.test.ts | 2 +- sdk/test/storage/nft.storage.test.ts | 2 + sdk/test/types/errors.test.ts | 2 +- sdk/test/utils/config.test.ts | 114 +- sdk/test/utils/errors.test.ts | 4 +- sdk/test/validator.test.ts | 10 +- sdk/tsconfig.json | 4 +- 104 files changed, 11385 insertions(+), 1888 deletions(-) create mode 100644 contracts/scripts/deployment/Deployment.s.sol create mode 100644 contracts/scripts/deployment/ProtocolFeeRecipientDeployment.s.sol create mode 100644 contracts/src/deployments.json create mode 100644 docs/docs/developer/api/contracts/ainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.md create mode 100644 docs/docs/developer/api/contracts/marketplace/BatchOrderTypehashRegistry.md create mode 100644 docs/docs/developer/api/contracts/marketplace/CreatorFeeManagerWithRebates.md create mode 100644 docs/docs/developer/api/contracts/marketplace/CreatorFeeManagerWithRoyalties.md create mode 100644 docs/docs/developer/api/contracts/marketplace/CurrencyManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/ExecutionManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/InheritedStrategy.md create mode 100644 docs/docs/developer/api/contracts/marketplace/LooksRareProtocol.md create mode 100644 docs/docs/developer/api/contracts/marketplace/NonceManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/ProtocolFeeRecipient.md create mode 100644 docs/docs/developer/api/contracts/marketplace/StrategyManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/TransferManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/TransferSelectorNFT.md create mode 100644 docs/docs/developer/api/contracts/marketplace/executionStrategies/BaseStrategy.md create mode 100644 docs/docs/developer/api/contracts/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.md create mode 100644 docs/docs/developer/api/contracts/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.md create mode 100644 docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyCollectionOffer.md create mode 100644 docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyDutchAuction.md create mode 100644 docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyItemIdsRange.md create mode 100644 docs/docs/developer/api/contracts/marketplace/helpers/OrderValidatorV2A.md create mode 100644 docs/docs/developer/api/contracts/marketplace/helpers/ProtocolHelpers.md create mode 100644 docs/docs/developer/api/contracts/marketplace/interfaces/ICreatorFeeManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/interfaces/ICurrencyManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/interfaces/IExecutionManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/interfaces/IImmutableCreate2Factory.md create mode 100644 docs/docs/developer/api/contracts/marketplace/interfaces/ILooksRareProtocol.md create mode 100644 docs/docs/developer/api/contracts/marketplace/interfaces/INonceManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/interfaces/IRoyaltyFeeRegistry.md create mode 100644 docs/docs/developer/api/contracts/marketplace/interfaces/IStrategy.md create mode 100644 docs/docs/developer/api/contracts/marketplace/interfaces/IStrategyManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/interfaces/ITransferManager.md create mode 100644 docs/docs/developer/api/contracts/marketplace/libraries/CurrencyValidator.md create mode 100644 docs/docs/developer/api/contracts/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.md create mode 100644 docs/docs/developer/api/contracts/marketplace/libraries/OpenZeppelin/MerkleProofMemory.md create mode 100644 docs/docs/developer/api/contracts/marketplace/libraries/OrderStructs.md create mode 100644 docs/docs/developer/api/contracts/protocol/AllowlistMinter.md create mode 100644 docs/docs/developer/api/contracts/protocol/HypercertMinter.md create mode 100644 docs/docs/developer/api/contracts/protocol/SemiFungible1155.md create mode 100644 docs/docs/developer/api/contracts/protocol/interfaces/IAllowlist.md create mode 100644 docs/docs/developer/api/contracts/protocol/interfaces/IHypercertToken.md create mode 100644 docs/docs/developer/api/contracts/protocol/libs/Errors.md delete mode 100644 sdk/src/evaluations/eas.ts create mode 100644 sdk/src/utils/adapters.ts delete mode 100644 sdk/test/evaluations/easEvaluator.test.ts create mode 100644 sdk/test/resources/HypercertMinter.json diff --git a/.github/workflows/ci-default.yml b/.github/workflows/ci-default.yml index c25b49e0..7c338fa1 100644 --- a/.github/workflows/ci-default.yml +++ b/.github/workflows/ci-default.yml @@ -13,8 +13,8 @@ env: NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }} NEXT_PUBLIC_SUPABASE_TABLE: ${{ vars.NEXT_PUBLIC_SUPABASE_TABLE }} NEXT_PUBLIC_WALLETCONNECT_ID: ${{ secrets.NEXT_PUBLIC_WALLETCONNECT_ID }} - GOERLI_RPC_URL: ${{ vars.GOERLI_RPC_URL }} - MAINNET_RPC_URL: ${{ vars.MAINNET_RPC_URL }} + INFURA_API_KEY: ${{ vars.INFURA_API_KEY }} + ALCHEMY_API_KEY: ${{ vars.ALCHEMY_API_KEY }} DOCKER_PLATFORM: "amd64" # Trigger the workflow when: diff --git a/contracts/.env.example b/contracts/.env.example index 8cef70d1..235bb631 100644 --- a/contracts/.env.example +++ b/contracts/.env.example @@ -2,11 +2,7 @@ MNEMONIC="test test test test test test test test test test test junk" MNEMONIC_CELO=="test test test test test test test test test test test junk" INFURA_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" - -# RPCs -MAINNET_RPC_URL="" -OPTIMISM_RPC_URL="" -GOERLI_RPC_URL="" +ALCHEMY_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" # OpenZeppelin OPENZEPPELIN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" @@ -18,6 +14,13 @@ OPTIMISTIC_ETHERSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" CELOSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" # Unused, ignore below -POLYGONSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" REPORT_GAS=false CMC_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + +# Marketplace +OWNER_ADDRESS="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +TRANSFER_MANAGER_SALT="bbbbbbbbbbbbbb" +LOOKSRARE_PROTOCOL_SALT="cccccccccccccc" +STRATEGY_COLLECTION_OFFER_SALT="dddddddddddddd" +PROTOCOL_FEE_RECIPIENT_ADDRESS="eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + diff --git a/contracts/.gitignore b/contracts/.gitignore index 45e7e641..2d812b19 100644 --- a/contracts/.gitignore +++ b/contracts/.gitignore @@ -18,7 +18,7 @@ **/deployments/localhost **/out* **/typechain -**/src/types +**/types **/cache** **/abi **/rollup-cache diff --git a/contracts/foundry.toml b/contracts/foundry.toml index a3a0c8f9..efe3aa83 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -2,7 +2,7 @@ [profile.default] auto_detect_solc = true -allow_paths = ["../node_modules", "lib"] +allow_paths = ["../node_modules", "node_modules", "lib"] bytecode_hash = "none" force = false fuzz = { runs = 1025 } @@ -13,6 +13,7 @@ optimizer = true optimizer_runs = 5_000 out = "out" src = "src" +script = "scripts/deployment" test = "test/foundry" no_match_test = "testCannotExecuteOrderIfInvalidUserGlobal" @@ -20,10 +21,19 @@ no_match_test = "testCannotExecuteOrderIfInvalidUserGlobal" fuzz = { runs = 1024 } verbosity = 1 +[etherscan] +mainnet = { key = "${ETHERSCAN_API_KEY}" } +goerli = { key = "${ETHERSCAN_API_KEY}" } +optimism = { key = "${OPTIMISTIC_ETHERSCAN_API_KEY}" } +sepolia = { key = "${ETHERSCAN_API_KEY}" } +celo = { key = "${CELOSCAN_API_KEY}" } + [rpc_endpoints] -mainnet = "${MAINNET_RPC_URL}" -goerli = "${GOERLI_RPC_URL}" -optimism = "${OPTIMISM_RPC_URL}" +mainnet = "https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}" +goerli = "https://eth-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}" +optimism = "https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}" +sepolia = "https://sepolia.infura.io/v3/${INFURA_API_KEY}" +celo = "https://forno.celo.org" [fmt] number_underscore = "thousands" diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index 87cd1dc7..dce7d9ca 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -1,8 +1,7 @@ -import "@nomicfoundation/hardhat-chai-matchers"; +import { HardhatUserConfig } from "hardhat/config"; import "@nomicfoundation/hardhat-toolbox"; -import "@nomiclabs/hardhat-ethers"; +import "@nomicfoundation/hardhat-chai-matchers"; import "@openzeppelin/hardhat-upgrades"; -import "@openzeppelin/hardhat-defender"; import "@primitivefi/hardhat-dodoc"; import { config as dotenvConfig } from "dotenv"; @@ -34,17 +33,20 @@ const dotenvConfigPath: string = process.env.DOTENV_PATH ?? fs.existsSync("./.en dotenvConfig({ path: resolve(__dirname, dotenvConfigPath) }); // Ensure that we have all the environment variables we need. -const mnemonic = requireEnv(process.env.MNEMONIC, "MNEMONIC"); -const mnemonic_celo = requireEnv(process.env.MNEMONIC_CELO, "MNEMONIC_CELO"); -const infuraApiKey = requireEnv(process.env.INFURA_API_KEY, "INFURA_API_KEY"); -const optimismRpcUrl = requireEnv(process.env.OPTIMISM_RPC_URL, "OPTIMISM_RPC_URL"); +const MNEMONIC = requireEnv(process.env.MNEMONIC, "MNEMONIC"); +const MNEMONIC_CELO = requireEnv(process.env.MNEMONIC_CELO, "MNEMONIC_CELO"); +const INFURA_API_KEY = requireEnv(process.env.INFURA_API_KEY, "INFURA_API_KEY"); +const ALCHEMY_API_KEY = requireEnv(process.env.ALCHEMY_API_KEY, "ALCHEMY_API_KEY"); -const etherscanApiKey = requireEnv(process.env.ETHERSCAN_API_KEY, "ETHERSCAN_API_KEY"); -const optimisticEtherscanApiKey = requireEnv(process.env.OPTIMISTIC_ETHERSCAN_API_KEY, "OPTIMISTIC_ETHERSCAN_API_KEY"); -const celoscanApiKey = requireEnv(process.env.CELOSCAN_API_KEY, "CELOSCAN_API_KEY"); +const ETHERSCAN_API_KEY = requireEnv(process.env.ETHERSCAN_API_KEY, "ETHERSCAN_API_KEY"); +const OPTIMISTIC_ETHERSCAN_API_KEY = requireEnv( + process.env.OPTIMISTIC_ETHERSCAN_API_KEY, + "OPTIMISTIC_ETHERSCAN_API_KEY", +); +const CELOSCAN_API_KEY = requireEnv(process.env.CELOSCAN_API_KEY, "CELOSCAN_API_KEY"); -const ozApiKey = requireEnv(process.env.OPENZEPPELIN_API_KEY, "OPENZEPPELIN_API_KEY"); -const ozSecretKey = requireEnv(process.env.OPENZEPPELIN_SECRET_KEY, "OPENZEPPELIN_SECRET_KEY"); +const OPENZEPPELIN_API_KEY = requireEnv(process.env.OPENZEPPELIN_API_KEY, "OPENZEPPELIN_API_KEY"); +const OPENZEPPELIN_SECRET_KEY = requireEnv(process.env.OPENZEPPELIN_SECRET_KEY, "OPENZEPPELIN_SECRET_KEY"); /** * Maps a key to the chain ID @@ -64,23 +66,30 @@ const chainIds = { }; function getChainConfig(chain: keyof typeof chainIds) { - const jsonRpcUrl = "https://" + chain + ".infura.io/v3/" + infuraApiKey; + const jsonRpcUrl = "https://" + chain + ".infura.io/v3/" + INFURA_API_KEY; let config = { accounts: { count: 10, - mnemonic, + mnemonic: MNEMONIC, path: "m/44'/60'/0'/0", }, chainId: chainIds[chain], url: jsonRpcUrl, }; + if (chain === "optimism-mainnet") { + config = { + ...config, + url: `https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}`, + }; + } + if (chain === "celo-mainnet") { config = { ...config, accounts: { count: 10, - mnemonic: mnemonic_celo, + mnemonic: MNEMONIC_CELO, path: "m/44'/52752'/0'/0", }, }; @@ -89,9 +98,9 @@ function getChainConfig(chain: keyof typeof chainIds) { return config; } -const config = { +const config: HardhatUserConfig = { abiExporter: { - path: "./src/abi", + path: "./abi", runOnCompile: true, clear: true, flat: true, @@ -99,8 +108,8 @@ const config = { except: ["@openzeppelin"], }, defender: { - apiKey: ozApiKey!, - apiSecret: ozSecretKey!, + apiKey: OPENZEPPELIN_API_KEY!, + apiSecret: OPENZEPPELIN_SECRET_KEY!, useDefenderDeploy: true, }, dodoc: { @@ -111,10 +120,10 @@ const config = { }, etherscan: { apiKey: { - goerli: etherscanApiKey!, - sepolia: etherscanApiKey!, - optimisticEthereum: optimisticEtherscanApiKey!, - celo: celoscanApiKey!, + goerli: ETHERSCAN_API_KEY!, + sepolia: ETHERSCAN_API_KEY!, + optimisticEthereum: OPTIMISTIC_ETHERSCAN_API_KEY!, + celo: CELOSCAN_API_KEY!, }, customChains: [ { @@ -133,7 +142,7 @@ const config = { // metamask can't transfer when connected to hardhat's network. initialBaseFeePerGas: 0, accounts: { - mnemonic, + mnemonic: MNEMONIC, }, chainId: chainIds.hardhat, }, @@ -145,32 +154,30 @@ const config = { sepolia: getChainConfig("sepolia"), mainnet: getChainConfig("mainnet"), "optimism-goerli": getChainConfig("optimism-goerli"), - "optimism-mainnet": { - ...getChainConfig("optimism-mainnet"), - url: optimismRpcUrl, - }, + "optimism-mainnet": getChainConfig("optimism-mainnet"), }, paths: { cache: "./cache_hardhat", // Use a different cache for Hardhat than Foundry - sources: "./src/protocol", + sources: "./src", tests: "./test", }, preprocess: { - eachLine: () => ({ + eachLine: (hre) => ({ transform: (line: string) => { if (line.match(/^\s*import /i)) { - getRemappings().forEach(([find, replace]) => { - if (line.match(find)) { - line = line.replace(find, replace); + for (const [from, to] of getRemappings()) { + if (line.includes(from)) { + line = line.replace(from, to); + break; } - }); + } } return line; }, }), }, solidity: { - version: "0.8.16", + version: "0.8.17", settings: { optimizer: { enabled: true, @@ -179,8 +186,7 @@ const config = { }, }, typechain: { - outDir: "./src/types", - target: "ethers-v5", + outDir: "./types", }, }; diff --git a/contracts/package.json b/contracts/package.json index 5ad67eae..78530c9c 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,7 +1,7 @@ { "name": "@hypercerts-org/contracts", "description": "EVM compatible protocol for managing impact claims", - "version": "0.8.11", + "version": "0.9.0", "author": { "name": "Hypercerts Foundation", "url": "/~https://github.com/hypercerts-org/hypercerts" @@ -26,50 +26,33 @@ "files": [ "dist", "README.md", - "package.json", - "contracts" + "package.json" ], "devDependencies": { "@chainlink/contracts": "^0.8.0", "@commitlint/cli": "^17.1.2", "@commitlint/config-conventional": "^17.1.0", "@dlsl/hardhat-markup": "^1.0.0-rc.7", - "@ethersproject/abi": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/providers": "^5.7.2", "@looksrare/contracts-libs": "^3.4.0", - "@nomicfoundation/hardhat-chai-matchers": "^1.0.5", - "@nomicfoundation/hardhat-network-helpers": "^1.0.7", - "@nomicfoundation/hardhat-toolbox": "^2.0.0", - "@nomiclabs/hardhat-ethers": "^2.2.1", - "@nomiclabs/hardhat-etherscan": "^3.1.3", + "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@openzeppelin/contracts": "<5.0.0", - "@openzeppelin/hardhat-defender": "^1.8.2", - "@openzeppelin/hardhat-upgrades": "^1.28", + "@openzeppelin/hardhat-upgrades": "2.3.3", "@primitivefi/hardhat-dodoc": "^0.2.3", "@rollup/plugin-commonjs": "^24.0.1", "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-node-resolve": "^15.0.1", "@trivago/prettier-plugin-sort-imports": "^3.3.0", - "@typechain/ethers-v5": "^11.1.1", - "@typechain/hardhat": "^9.0.0", - "@types/chai": "^4.3.4", - "@types/mocha": "9.1.0", "@types/node": "^18.11.11", "@typescript-eslint/eslint-plugin": "^5.38.0", "@typescript-eslint/parser": "^5.38.0", - "chai": "^4.3.7", "commitizen": "^4.2.5", - "copyfiles": "^2.4.1", "cross-env": "^7.0.3", "cz-conventional-changelog": "^3.3.0", "dotenv": "^16.0.2", "eslint": "^8.23.1", "eslint-config-prettier": "^8.5.0", - "ethers": "^5.7.2", - "hardhat": "2.13.1", + "ethers": "^6.8.0", "hardhat-abi-exporter": "^2.10.1", - "hardhat-gas-reporter": "^1.0.9", "hardhat-preprocessor": "^0.1.5", "husky": "^8.0.1", "lint-staged": "^13.0.3", @@ -100,14 +83,16 @@ "template" ], "scripts": { - "build": "hardhat compile && pnpm tsc -p tsconfig.build.json && rollup -c && pnpm copy:contracts", - "build:forge": "forge build", - "clean": "rimraf cache out dist src/typechain src/abi", - "copy:contracts": "copyfiles -u 1 ./src/**/*.sol ./src/*.sol ./contracts", + "build": "pnpm clean && hardhat compile && pnpm tsc -p tsconfig.build.json && rollup -c", + "build:forge": "pnpm clean && forge build", + "clean": "rimraf abi artifacts build cache cache_hardhat dist out types", + "deploy:marketplace:goerli": "forge script scripts/deployment/Deployment.s.sol:Deployment --broadcast --verify --fork-url goerli", + "deploy:marketplace:sepolia": "forge script scripts/deployment/Deployment.s.sol:Deployment --broadcast --verify --fork-url sepolia", + "deploy:marketplace:test": "pnpm deploy:marketplace:goerli && pnpm deploy:marketplace:sepolia", + "deploy:marketplace:dryrun": "forge script scripts/deployment/Deployment.s.sol:Deployment --fork-url", "docs": "hardhat dodoc", "lint": "pnpm lint:sol && pnpm prettier:check", "lint:sol": "forge fmt --check && solhint \"./{src,test/protocol,test/marketplace}/**/*.sol\"", - "prebuild": "pnpm clean", "prepublish": "pnpm build", "prettier": "prettier --config \"./.prettierrc.yml\" --write \"**/*.{json,md,ts,yml}\"", "prettier:check": "prettier --config \"./.prettierrc.yml\" --check \"**/*.{json,md,ts,yml}\"", @@ -117,5 +102,8 @@ "test:hardhat": "hardhat test", "test:gas": "forge test --match-path test/foundry/PerformanceTesting.t.sol --gas-report", "hardhat": "hardhat" + }, + "dependencies": { + "hardhat": "^2.18.3" } } diff --git a/contracts/rollup.config.mjs b/contracts/rollup.config.mjs index f6e55c8b..77c81300 100644 --- a/contracts/rollup.config.mjs +++ b/contracts/rollup.config.mjs @@ -8,7 +8,7 @@ import nodePolyfills from "rollup-plugin-node-polyfills"; export default [ { - input: `build/index.js`, + input: `build/src/index.js`, plugins: [ autoExternal(), nodePolyfills(), @@ -33,7 +33,7 @@ export default [ ], }, { - input: `build/index.d.ts`, + input: `build/src/index.d.ts`, plugins: [json(), dts()], output: { file: `dist/index.d.ts`, diff --git a/contracts/scripts/deployment/Deployment.s.sol b/contracts/scripts/deployment/Deployment.s.sol new file mode 100644 index 00000000..244652e5 --- /dev/null +++ b/contracts/scripts/deployment/Deployment.s.sol @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +// Scripting tool +import {Script} from "forge-std/Script.sol"; + +// Core contracts +import {LooksRareProtocol} from "@hypercerts/marketplace/LooksRareProtocol.sol"; +import {TransferManager} from "@hypercerts/marketplace/TransferManager.sol"; +import {StrategyCollectionOffer} from "@hypercerts/marketplace/executionStrategies/StrategyCollectionOffer.sol"; + +// Create2 factory interface +import {IImmutableCreate2Factory} from "@hypercerts/marketplace/interfaces/IImmutableCreate2Factory.sol"; + +// Other contracts +import {OrderValidatorV2A} from "@hypercerts/marketplace/helpers/OrderValidatorV2A.sol"; + +contract Deployment is Script { + address internal deployer; + IImmutableCreate2Factory private constant IMMUTABLE_CREATE2_FACTORY = + IImmutableCreate2Factory(0x0000000000FFe8B47B3e2130213B802212439497); + + error ChainIdInvalid(uint256 chainId); + error MnemonicInvalid(); + + address public weth; + + // address public royaltyFeeRegistry; + + uint16 internal constant _standardProtocolFeeBp = uint16(50); + uint16 internal constant _minTotalFeeBp = uint16(50); + uint16 internal constant _maxProtocolFeeBp = uint16(200); + + function setUp() public virtual { + string memory mnemonic = vm.envString("MNEMONIC"); + if (bytes(mnemonic).length > 0) { + (deployer,) = deriveRememberKey(mnemonic, 0); + } else { + revert MnemonicInvalid(); + } + } + + function run() external { + uint256 chainId = block.chainid; + + if (chainId == 5) { + weth = 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6; + } else if (chainId == 11_155_111) { + weth = 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14; + } else { + revert ChainIdInvalid(chainId); + } + + vm.startBroadcast(deployer); + + // 1. Deploy TransferManager + address transferManagerAddress = IMMUTABLE_CREATE2_FACTORY.safeCreate2({ + salt: vm.envBytes32("TRANSFER_MANAGER_SALT"), + initializationCode: abi.encodePacked( + type(TransferManager).creationCode, abi.encode(vm.envAddress("OWNER_ADDRESS")) + ) + }); + + // 2. Transfer 1 wei to LooksRareProtocol before it is deployed. + // It cannot receive ETH after it is deployed. + payable(0x0000000000E655fAe4d56241588680F86E3b2377).transfer(1 wei); + + // 3. Deploy LooksRareProtocol + address looksRareProtocolAddress = IMMUTABLE_CREATE2_FACTORY.safeCreate2({ + salt: vm.envBytes32("LOOKSRARE_PROTOCOL_SALT"), + initializationCode: abi.encodePacked( + type(LooksRareProtocol).creationCode, + abi.encode( + vm.envAddress("OWNER_ADDRESS"), + vm.envAddress("PROTOCOL_FEE_RECIPIENT_ADDRESS"), + transferManagerAddress, + weth + ) + ) + }); + + // 4. Other operations + TransferManager(transferManagerAddress).allowOperator(looksRareProtocolAddress); + LooksRareProtocol(looksRareProtocolAddress).updateCurrencyStatus(address(0), true); + LooksRareProtocol(looksRareProtocolAddress).updateCurrencyStatus(weth, true); + + // 5. Deploy OrderValidatorV2A, this needs to happen after updateCreatorFeeManager + // as the order validator calls creator fee manager to retrieve the royalty fee registry + new OrderValidatorV2A(looksRareProtocolAddress); + + // 6. Deploy StrategyCollectionOffer + address strategyCollectionOfferAddress = IMMUTABLE_CREATE2_FACTORY.safeCreate2({ + salt: vm.envBytes32("STRATEGY_COLLECTION_OFFER_SALT"), + initializationCode: type(StrategyCollectionOffer).creationCode + }); + + LooksRareProtocol(looksRareProtocolAddress).addStrategy( + _standardProtocolFeeBp, + _minTotalFeeBp, + _maxProtocolFeeBp, + StrategyCollectionOffer.executeCollectionStrategyWithTakerAsk.selector, + true, + strategyCollectionOfferAddress + ); + + LooksRareProtocol(looksRareProtocolAddress).addStrategy( + _standardProtocolFeeBp, + _minTotalFeeBp, + _maxProtocolFeeBp, + StrategyCollectionOffer.executeCollectionStrategyWithTakerAskWithProof.selector, + true, + strategyCollectionOfferAddress + ); + + vm.stopBroadcast(); + } +} diff --git a/contracts/scripts/deployment/ProtocolFeeRecipientDeployment.s.sol b/contracts/scripts/deployment/ProtocolFeeRecipientDeployment.s.sol new file mode 100644 index 00000000..dc08c0b7 --- /dev/null +++ b/contracts/scripts/deployment/ProtocolFeeRecipientDeployment.s.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +// Scripting tool +import {Script} from "forge-std/Script.sol"; + +// Core contracts +import {ProtocolFeeRecipient} from "@hypercerts/marketplace/ProtocolFeeRecipient.sol"; + +contract ProtocolFeeRecipientDeployment is Script { + error ChainIdInvalid(uint256 chainId); + + // WETH + address public weth; + address private feeSharingSetter; + + function run() external { + uint256 chainId = block.chainid; + uint256 deployerPrivateKey; + + if (chainId == 1) { + weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + feeSharingSetter = 0x5924A28caAF1cc016617874a2f0C3710d881f3c1; + deployerPrivateKey = vm.envUint("MAINNET_KEY"); + } else if (chainId == 5) { + weth = 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6; + feeSharingSetter = 0x3d1E1521b659b0C942836DeF24dd254aBdEb873b; + deployerPrivateKey = vm.envUint("TESTNET_KEY"); + } else if (chainId == 11_155_111) { + weth = 0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9; + feeSharingSetter = 0x8a7c709648160a5A1191D07dfAB316224E4C6b07; + deployerPrivateKey = vm.envUint("TESTNET_KEY"); + } else { + revert ChainIdInvalid(chainId); + } + + vm.startBroadcast(deployerPrivateKey); + + new ProtocolFeeRecipient(feeSharingSetter, weth); + + vm.stopBroadcast(); + } +} diff --git a/contracts/src/deployments.json b/contracts/src/deployments.json new file mode 100644 index 00000000..4156e8e6 --- /dev/null +++ b/contracts/src/deployments.json @@ -0,0 +1,22 @@ +{ + "5": { + "HypercertMinterUUPS": "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", + "HypercertMinterImplementation": "0x0a00a2f09cd37b24e7429c5238323bfebcff3ed9", + "TransferManager": "0x91CC106977934becc64e56987a89547077E95186", + "HypercertExchange": "0xE6563d73D19794d50526eB1B02441530ED190dc5" + }, + "11155111": { + "HypercertMinterUUPS": "0xa16DFb32Eb140a6f3F2AC68f41dAd8c7e83C4941", + "HypercertMinterImplementation": "0x0a0df97bddb36eef95fef089a4aeb7aceabf2101", + "TransferManager": "0x91CC106977934becc64e56987a89547077E95186", + "HypercertExchange": "0x7AFc7938130bd03b792C0B05C796f42E9beBB2D6" + }, + "10": { + "HypercertMinterUUPS": "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", + "HypercertMinterImplementation": "0x396d5f1ef3aa92ddad4dead04388374a03bc5577" + }, + "42220": { + "HypercertMinterUUPS": "0x16bA53B74c234C870c61EFC04cD418B8f2865959", + "HypercertMinterImplementation": "0x620257e9301a813be7cc5b75aae8dda3f6a926d2" + } +} diff --git a/contracts/src/index.ts b/contracts/src/index.ts index 641f675b..3019f4fc 100644 --- a/contracts/src/index.ts +++ b/contracts/src/index.ts @@ -1,10 +1,28 @@ -import HypercertMinterAbi from "./abi/HypercertMinter.json"; -// import { HypercertMinter__factory } from "./types/factories/src/HypercertMinter__factory"; -import type { AllowlistMinter } from "./types/src/protocol/AllowlistMinter"; -import type { HypercertMinter } from "./types/src/protocol/HypercertMinter"; -import type { IAllowlist } from "./types/src/protocol/interfaces/IAllowlist"; -import type { IHypercertToken } from "./types/src/protocol/interfaces/IHypercertToken"; -import type { Errors } from "./types/src/protocol/libs/Errors"; +import HypercertMinterAbi from "../abi/HypercertMinter.json"; +import AllowlistMinterAbi from "../abi/AllowlistMinter.json"; +import CurrencyManagerAbi from "../abi/CurrencyManager.json"; +import ExecutionManagerAbi from "../abi/ExecutionManager.json"; +import LooksRareProtocolAbi from "../abi/LooksRareProtocol.json"; +import NonceManagerAbi from "../abi/NonceManager.json"; +import OrderValidatorV2AAbi from "../abi/OrderValidatorV2A.json"; +import StrategyManagerAbi from "../abi/StrategyManager.json"; +import TransferManagerAbi from "../abi/TransferManager.json"; + +import type { CurrencyManager } from "../types/src/marketplace/CurrencyManager"; +import type { ExecutionManager } from "../types/src/marketplace/ExecutionManager"; +import type { LooksRareProtocol } from "../types/src/marketplace/LooksRareProtocol"; +import type { NonceManager } from "../types/src/marketplace/NonceManager"; +import type { OrderValidatorV2A } from "../types/src/marketplace/helpers/OrderValidatorV2A"; +import type { StrategyManager } from "../types/src/marketplace/StrategyManager"; +import type { TransferManager } from "../types/src/marketplace/TransferManager"; +import type { AllowlistMinter } from "../types/src/protocol/AllowlistMinter"; +import type { HypercertMinter } from "../types/src/protocol/HypercertMinter"; +import type { IAllowlist } from "../types/src/protocol/interfaces/IAllowlist"; +import type { IHypercertToken } from "../types/src/protocol/interfaces/IHypercertToken"; +import type { Errors } from "../types/src/protocol/libs/Errors"; + +import deployments from "./deployments.json"; + /* in order to adjust the build folder: 1) import any files here you want in the final build package. @@ -13,15 +31,35 @@ import type { Errors } from "./types/src/protocol/libs/Errors"; 4) bump package.json version to publish a new package to npm. */ -// Factory -// export { HypercertMinter__factory }; +// Deployments +export { deployments }; // Interfaces export { IAllowlist, IHypercertToken }; -export { HypercertMinterAbi }; +export { + HypercertMinterAbi, + AllowlistMinterAbi, + CurrencyManagerAbi, + ExecutionManagerAbi, + LooksRareProtocolAbi as HypercertExchangeAbi, + NonceManagerAbi, + OrderValidatorV2AAbi, + StrategyManagerAbi, + TransferManagerAbi, +}; // Contracts -export { HypercertMinter, AllowlistMinter }; +export { + HypercertMinter, + AllowlistMinter, + CurrencyManager, + ExecutionManager, + LooksRareProtocol as HypercertExchange, + NonceManager, + OrderValidatorV2A, + StrategyManager, + TransferManager, +}; // Libs export { Errors }; diff --git a/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol b/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol index 3a1de368..9f0bcc3d 100644 --- a/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol +++ b/contracts/src/marketplace/CreatorFeeManagerWithRebates.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity ^0.8.17; // LooksRare unopinionated libraries import {IERC2981} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC2981.sol"; diff --git a/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol b/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol index a50dde6a..4b72630f 100644 --- a/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol +++ b/contracts/src/marketplace/CreatorFeeManagerWithRoyalties.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity ^0.8.17; // LooksRare unopinionated libraries import {IERC2981} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC2981.sol"; diff --git a/contracts/src/marketplace/ProtocolFeeRecipient.sol b/contracts/src/marketplace/ProtocolFeeRecipient.sol index 33cfceb4..4eb12174 100644 --- a/contracts/src/marketplace/ProtocolFeeRecipient.sol +++ b/contracts/src/marketplace/ProtocolFeeRecipient.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity ^0.8.17; // LooksRare unopinionated libraries import {LowLevelERC20Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC20Transfer.sol"; diff --git a/contracts/src/protocol/AllowlistMinter.sol b/contracts/src/protocol/AllowlistMinter.sol index 599831cb..881e0e68 100644 --- a/contracts/src/protocol/AllowlistMinter.sol +++ b/contracts/src/protocol/AllowlistMinter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.16; +pragma solidity ^0.8.16; import {MerkleProofUpgradeable} from "oz-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol"; import {IAllowlist} from "./interfaces/IAllowlist.sol"; diff --git a/contracts/src/protocol/HypercertMinter.sol b/contracts/src/protocol/HypercertMinter.sol index cf387a86..63cf8cb4 100644 --- a/contracts/src/protocol/HypercertMinter.sol +++ b/contracts/src/protocol/HypercertMinter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.16; +pragma solidity ^0.8.16; import {IHypercertToken} from "./interfaces/IHypercertToken.sol"; import {SemiFungible1155} from "./SemiFungible1155.sol"; diff --git a/contracts/src/protocol/SemiFungible1155.sol b/contracts/src/protocol/SemiFungible1155.sol index fb409bbe..4fe25e1c 100644 --- a/contracts/src/protocol/SemiFungible1155.sol +++ b/contracts/src/protocol/SemiFungible1155.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // Used components of Enjin example implementation for mixed fungibility // /~https://github.com/enjin/erc-1155/blob/master/contracts/ERC1155MixedFungibleMintable.sol -pragma solidity 0.8.16; +pragma solidity ^0.8.16; import {ERC1155Upgradeable} from "oz-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; import {ERC1155BurnableUpgradeable} from "oz-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol"; diff --git a/contracts/src/protocol/interfaces/IAllowlist.sol b/contracts/src/protocol/interfaces/IAllowlist.sol index 2ce9a044..b4415d42 100644 --- a/contracts/src/protocol/interfaces/IAllowlist.sol +++ b/contracts/src/protocol/interfaces/IAllowlist.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.16; +pragma solidity ^0.8.16; /// @title Interface for allowlist /// @author bitbeckers diff --git a/contracts/src/protocol/interfaces/IHypercertToken.sol b/contracts/src/protocol/interfaces/IHypercertToken.sol index fd3d4b5b..afd257bf 100644 --- a/contracts/src/protocol/interfaces/IHypercertToken.sol +++ b/contracts/src/protocol/interfaces/IHypercertToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.16; +pragma solidity ^0.8.16; /// @title Interface for hypercert token interactions /// @author bitbeckers diff --git a/contracts/tasks/deploy.ts b/contracts/tasks/deploy.ts index e9c53ffd..28767a74 100644 --- a/contracts/tasks/deploy.ts +++ b/contracts/tasks/deploy.ts @@ -48,48 +48,3 @@ task("deploy-minter", "Deploy contracts and verify") } } }); - -task("deploy-trader", "Deploy HypercertTrader and verify") - .addOptionalParam("output", "write the details of the deployment to this file if this is set") - .setAction(async ({ output }, { ethers, upgrades }) => { - const HypercertTrader = await ethers.getContractFactory("HypercertTrader"); - const hypercertTrader = await upgrades.deployProxy(HypercertTrader, { - kind: "uups", - unsafeAllow: ["constructor"], - }); - const contract = await hypercertTrader.deployed(); - console.log(`hypercertTrader is deployed to proxy address: ${hypercertTrader.address}`); - - // If the `deploymentFile` option is set then write the deployed address to - // a json object on disk. This is intended to be deliberate with how we - // output the contract address and other contract information. - if (output) { - const txReceipt = await contract.provider.getTransactionReceipt(hypercertTrader.deployTransaction.hash); - await writeFile( - output, - JSON.stringify({ - address: hypercertTrader.address, - blockNumber: txReceipt.blockNumber, - }), - "utf-8", - ); - } - - if (hre.network.name !== "hardhat" && hre.network.name !== "localhost") { - try { - const code = await hypercertTrader.instance?.provider.getCode(hypercertTrader.address); - if (code === "0x") { - console.log(`${hypercertTrader.name} contract deployment has not completed. waiting to verify...`); - await hypercertTrader.instance?.deployed(); - } - await hre.run("verify:verify", { - address: hypercertTrader.address, - }); - } catch ({ message }) { - if ((message as string).includes("Reason: Already Verified")) { - console.log("Reason: Already Verified"); - } - console.error(message); - } - } - }); diff --git a/contracts/test/HypercertMinter.test.ts b/contracts/test/HypercertMinter.test.ts index 9cb0af6f..437b1fe4 100644 --- a/contracts/test/HypercertMinter.test.ts +++ b/contracts/test/HypercertMinter.test.ts @@ -1,16 +1,16 @@ -import { expect } from "chai"; import { ethers, upgrades } from "hardhat"; +import { expect } from "chai"; -import { HypercertMinter } from "../src/types"; - -describe("Hypercert Minter", function () { +describe("HypercertMinter", function () { it("is upgradeable", async () => { const HypercertMinter = await ethers.getContractFactory("HypercertMinter"); - const instance = await upgrades.deployProxy(HypercertMinter, { + const instance = await upgrades.deployProxy(HypercertMinter, { kind: "uups", unsafeAllow: ["constructor"], + useDefenderDeploy: false, }); + await instance.waitForDeployment(); const name = await instance.name(); expect(name).to.equal("HypercertMinter"); await expect(instance.initialize()).to.be.revertedWith("Initializable: contract is already initialized"); diff --git a/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol b/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol index a161feaf..0b30803f 100644 --- a/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol +++ b/contracts/test/foundry/marketplace/ProtocolFeeRecipient.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity ^0.8.17; // LooksRare unopinionated libraries import {IERC20} from "@looksrare/contracts-libs/contracts/interfaces/generic/IERC20.sol"; diff --git a/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol b/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol index 066df8a6..40a74239 100644 --- a/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol +++ b/contracts/test/foundry/marketplace/executionStrategies/Chainlink/USDDynamicAskOrders.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity ^0.8.17; // Libraries and interfaces import {OrderStructs} from "@hypercerts/marketplace/libraries/OrderStructs.sol"; diff --git a/contracts/tsconfig.build.json b/contracts/tsconfig.build.json index baa92593..e9929279 100644 --- a/contracts/tsconfig.build.json +++ b/contracts/tsconfig.build.json @@ -22,11 +22,17 @@ }, "include": ["./src"], "files": [ - "src/abi/HypercertMinter.json", - "src/types/src/protocol/AllowlistMinter.ts", - "src/types/src/protocol/HypercertMinter.ts", - "src/types/src/protocol/interfaces/IAllowlist.ts", - "src/types/src/protocol/interfaces/IHypercertToken.ts", - "src/types/src/protocol/libs/Errors.ts" + "types/src/marketplace/CurrencyManager.ts", + "types/src/marketplace/ExecutionManager.ts", + "types/src/marketplace/LooksRareProtocol.ts", + "types/src/marketplace/NonceManager.ts", + "types/src/marketplace/helpers/OrderValidatorV2A.ts", + "types/src/marketplace/StrategyManager.ts", + "types/src/marketplace/TransferManager.ts", + "types/src/protocol/AllowlistMinter.ts", + "types/src/protocol/HypercertMinter.ts", + "types/src/protocol/interfaces/IAllowlist.ts", + "types/src/protocol/interfaces/IHypercertToken.ts", + "types/src/protocol/libs/Errors.ts" ] } diff --git a/contracts/tsconfig.json b/contracts/tsconfig.json index b58408fb..a3e3d8dc 100644 --- a/contracts/tsconfig.json +++ b/contracts/tsconfig.json @@ -20,14 +20,19 @@ "target": "ESNext", "outDir": "dist" }, - "include": ["./tasks", "./test", "./types", "./src"], + "include": ["./tasks", "./test", "./src"], "files": [ - "hardhat.config.ts", - "src/abi/HypercertMinter.json", - "src/types/src/protocol/AllowlistMinter.ts", - "src/types/src/protocol/HypercertMinter.ts", - "src/types/src/protocol/interfaces/IAllowlist.ts", - "src/types/src/protocol/interfaces/IHypercertToken.ts", - "src/types/src/protocol/libs/Errors.ts" + "types/src/marketplace/CurrencyManager.ts", + "types/src/marketplace/ExecutionManager.ts", + "types/src/marketplace/LooksRareProtocol.ts", + "types/src/marketplace/NonceManager.ts", + "types/src/marketplace/helpers/OrderValidatorV2A.ts", + "types/src/marketplace/StrategyManager.ts", + "types/src/marketplace/TransferManager.ts", + "types/src/protocol/AllowlistMinter.ts", + "types/src/protocol/HypercertMinter.ts", + "types/src/protocol/interfaces/IAllowlist.ts", + "types/src/protocol/interfaces/IHypercertToken.ts", + "types/src/protocol/libs/Errors.ts" ] } diff --git a/docs/docs/developer/api/contracts/ainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.md b/docs/docs/developer/api/contracts/ainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.md new file mode 100644 index 00000000..6be07157 --- /dev/null +++ b/docs/docs/developer/api/contracts/ainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.md @@ -0,0 +1,77 @@ +# AggregatorV3Interface + +## Methods + +### decimals + +```solidity +function decimals() external view returns (uint8) +``` + +#### Returns + +| Name | Type | Description | +| ---- | ----- | ----------- | +| \_0 | uint8 | undefined | + +### description + +```solidity +function description() external view returns (string) +``` + +#### Returns + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | string | undefined | + +### getRoundData + +```solidity +function getRoundData(uint80 _roundId) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) +``` + +#### Parameters + +| Name | Type | Description | +| --------- | ------ | ----------- | +| \_roundId | uint80 | undefined | + +#### Returns + +| Name | Type | Description | +| --------------- | ------- | ----------- | +| roundId | uint80 | undefined | +| answer | int256 | undefined | +| startedAt | uint256 | undefined | +| updatedAt | uint256 | undefined | +| answeredInRound | uint80 | undefined | + +### latestRoundData + +```solidity +function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) +``` + +#### Returns + +| Name | Type | Description | +| --------------- | ------- | ----------- | +| roundId | uint80 | undefined | +| answer | int256 | undefined | +| startedAt | uint256 | undefined | +| updatedAt | uint256 | undefined | +| answeredInRound | uint80 | undefined | + +### version + +```solidity +function version() external view returns (uint256) +``` + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | diff --git a/docs/docs/developer/api/contracts/marketplace/BatchOrderTypehashRegistry.md b/docs/docs/developer/api/contracts/marketplace/BatchOrderTypehashRegistry.md new file mode 100644 index 00000000..4cb96bfc --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/BatchOrderTypehashRegistry.md @@ -0,0 +1,46 @@ +# BatchOrderTypehashRegistry + +_LooksRare protocol team (👀,💎)_ + +> BatchOrderTypehashRegistry + +The contract generates the batch order hash that is used to compute the digest for signature verification. + +## Methods + +### hashBatchOrder + +```solidity +function hashBatchOrder(bytes32 root, uint256 proofLength) external pure returns (bytes32 batchOrderHash) +``` + +This function returns the hash of the concatenation of batch order type hash and merkle root. + +#### Parameters + +| Name | Type | Description | +| ----------- | ------- | ------------------- | +| root | bytes32 | Merkle root | +| proofLength | uint256 | Merkle proof length | + +#### Returns + +| Name | Type | Description | +| -------------- | ------- | -------------------- | +| batchOrderHash | bytes32 | The batch order hash | + +## Errors + +### MerkleProofTooLarge + +```solidity +error MerkleProofTooLarge(uint256 length) +``` + +It is returned if the length of the merkle proof provided is greater than tolerated. + +#### Parameters + +| Name | Type | Description | +| ------ | ------- | ------------ | +| length | uint256 | Proof length | diff --git a/docs/docs/developer/api/contracts/marketplace/CreatorFeeManagerWithRebates.md b/docs/docs/developer/api/contracts/marketplace/CreatorFeeManagerWithRebates.md new file mode 100644 index 00000000..a32aef65 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/CreatorFeeManagerWithRebates.md @@ -0,0 +1,76 @@ +# CreatorFeeManagerWithRebates + +_LooksRare protocol team (👀,💎)_ + +> CreatorFeeManagerWithRebates + +This contract returns the creator fee address and the creator rebate amount. + +## Methods + +### STANDARD_ROYALTY_FEE_BP + +```solidity +function STANDARD_ROYALTY_FEE_BP() external view returns (uint256) +``` + +Standard royalty fee (in basis point). + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +### royaltyFeeRegistry + +```solidity +function royaltyFeeRegistry() external view returns (contract IRoyaltyFeeRegistry) +``` + +Royalty fee registry interface. + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------------- | ----------- | +| \_0 | contract IRoyaltyFeeRegistry | undefined | + +### viewCreatorFeeInfo + +```solidity +function viewCreatorFeeInfo(address collection, uint256 price, uint256[] itemIds) external view returns (address creator, uint256 creatorFeeAmount) +``` + +This function returns the creator address and calculates the creator fee amount. + +#### Parameters + +| Name | Type | Description | +| ---------- | --------- | ------------------ | +| collection | address | Collection address | +| price | uint256 | Transaction price | +| itemIds | uint256[] | Array of item ids | + +#### Returns + +| Name | Type | Description | +| ---------------- | ------- | ------------------ | +| creator | address | Creator address | +| creatorFeeAmount | uint256 | Creator fee amount | + +## Errors + +### BundleEIP2981NotAllowed + +```solidity +error BundleEIP2981NotAllowed(address collection) +``` + +It is returned if the bundle contains multiple itemIds with different creator fee structure. + +#### Parameters + +| Name | Type | Description | +| ---------- | ------- | ----------- | +| collection | address | undefined | diff --git a/docs/docs/developer/api/contracts/marketplace/CreatorFeeManagerWithRoyalties.md b/docs/docs/developer/api/contracts/marketplace/CreatorFeeManagerWithRoyalties.md new file mode 100644 index 00000000..41cab900 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/CreatorFeeManagerWithRoyalties.md @@ -0,0 +1,64 @@ +# CreatorFeeManagerWithRoyalties + +_LooksRare protocol team (👀,💎)_ + +> CreatorFeeManagerWithRoyalties + +This contract returns the creator fee address and the creator fee amount. + +## Methods + +### royaltyFeeRegistry + +```solidity +function royaltyFeeRegistry() external view returns (contract IRoyaltyFeeRegistry) +``` + +Royalty fee registry interface. + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------------- | ----------- | +| \_0 | contract IRoyaltyFeeRegistry | undefined | + +### viewCreatorFeeInfo + +```solidity +function viewCreatorFeeInfo(address collection, uint256 price, uint256[] itemIds) external view returns (address creator, uint256 creatorFeeAmount) +``` + +This function returns the creator address and calculates the creator fee amount. + +_There are two on-chain sources for the royalty fee to distribute. 1. RoyaltyFeeRegistry: It is an on-chain registry where creator fee is defined for all items of a collection. 2. ERC2981: The NFT Royalty Standard where royalty fee is defined at a itemId level in a collection. The on-chain logic looks up the registry first. If it does not find anything, it checks if a collection is ERC2981. If so, it fetches the proper royalty information for the itemId. For a bundle that contains multiple itemIds (for a collection using ERC2981), if the royalty fee/recipient differ among the itemIds part of the bundle, the trade reverts. This contract DOES NOT enforce any restriction for extremely high creator fee, nor verifies the creator fee fetched is inferior to the total price. If any contract relies on it to build an on-chain royalty logic, it should implement protection against: (1) high royalties (2) potential unexpected royalty changes that can occur after the creation of the order._ + +#### Parameters + +| Name | Type | Description | +| ---------- | --------- | ------------------ | +| collection | address | Collection address | +| price | uint256 | Transaction price | +| itemIds | uint256[] | Array of item ids | + +#### Returns + +| Name | Type | Description | +| ---------------- | ------- | ------------------ | +| creator | address | Creator address | +| creatorFeeAmount | uint256 | Creator fee amount | + +## Errors + +### BundleEIP2981NotAllowed + +```solidity +error BundleEIP2981NotAllowed(address collection) +``` + +It is returned if the bundle contains multiple itemIds with different creator fee structure. + +#### Parameters + +| Name | Type | Description | +| ---------- | ------- | ----------- | +| collection | address | undefined | diff --git a/docs/docs/developer/api/contracts/marketplace/CurrencyManager.md b/docs/docs/developer/api/contracts/marketplace/CurrencyManager.md new file mode 100644 index 00000000..9ff1c0fc --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/CurrencyManager.md @@ -0,0 +1,250 @@ +# CurrencyManager + +_LooksRare protocol team (👀,💎)_ + +> CurrencyManager + +This contract manages the list of valid fungible currencies. + +## Methods + +### cancelOwnershipTransfer + +```solidity +function cancelOwnershipTransfer() external nonpayable +``` + +This function is used to cancel the ownership transfer. + +_This function can be used for both cancelling a transfer to a new owner and cancelling the renouncement of the ownership._ + +### confirmOwnershipRenouncement + +```solidity +function confirmOwnershipRenouncement() external nonpayable +``` + +This function is used to confirm the ownership renouncement. + +### confirmOwnershipTransfer + +```solidity +function confirmOwnershipTransfer() external nonpayable +``` + +This function is used to confirm the ownership transfer. + +_This function can only be called by the current potential owner._ + +### initiateOwnershipRenouncement + +```solidity +function initiateOwnershipRenouncement() external nonpayable +``` + +This function is used to initiate the ownership renouncement. + +### initiateOwnershipTransfer + +```solidity +function initiateOwnershipTransfer(address newPotentialOwner) external nonpayable +``` + +This function is used to initiate the transfer of ownership to a new owner. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | --------------------------- | +| newPotentialOwner | address | New potential owner address | + +### isCurrencyAllowed + +```solidity +function isCurrencyAllowed(address) external view returns (bool) +``` + +It checks whether the currency is allowed for transacting. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +Address of the current owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### ownershipStatus + +```solidity +function ownershipStatus() external view returns (enum IOwnableTwoSteps.Status) +``` + +Ownership status. + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------------- | ----------- | +| \_0 | enum IOwnableTwoSteps.Status | undefined | + +### potentialOwner + +```solidity +function potentialOwner() external view returns (address) +``` + +Address of the potential owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### updateCurrencyStatus + +```solidity +function updateCurrencyStatus(address currency, bool isAllowed) external nonpayable +``` + +This function allows the owner to update the status of a currency. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | -------------------------------------------------- | +| currency | address | Currency address (address(0) for ETH) | +| isAllowed | bool | Whether the currency should be allowed for trading | + +## Events + +### CancelOwnershipTransfer + +```solidity +event CancelOwnershipTransfer() +``` + +This is emitted if the ownership transfer is cancelled. + +### CurrencyStatusUpdated + +```solidity +event CurrencyStatusUpdated(address currency, bool isAllowed) +``` + +It is emitted if the currency status in the allowlist is updated. + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | ----------- | +| currency | address | undefined | +| isAllowed | bool | undefined | + +### InitiateOwnershipRenouncement + +```solidity +event InitiateOwnershipRenouncement() +``` + +This is emitted if the ownership renouncement is initiated. + +### InitiateOwnershipTransfer + +```solidity +event InitiateOwnershipTransfer(address previousOwner, address potentialOwner) +``` + +This is emitted if the ownership transfer is initiated. + +#### Parameters + +| Name | Type | Description | +| -------------- | ------- | ----------- | +| previousOwner | address | undefined | +| potentialOwner | address | undefined | + +### NewOwner + +```solidity +event NewOwner(address newOwner) +``` + +This is emitted when there is a new owner. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +## Errors + +### NoOngoingTransferInProgress + +```solidity +error NoOngoingTransferInProgress() +``` + +This is returned when there is no transfer of ownership in progress. + +### NotOwner + +```solidity +error NotOwner() +``` + +This is returned when the caller is not the owner. + +### RenouncementNotInProgress + +```solidity +error RenouncementNotInProgress() +``` + +This is returned when there is no renouncement in progress but the owner tries to validate the ownership renouncement. + +### TransferAlreadyInProgress + +```solidity +error TransferAlreadyInProgress() +``` + +This is returned when the transfer is already in progress but the owner tries initiate a new ownership transfer. + +### TransferNotInProgress + +```solidity +error TransferNotInProgress() +``` + +This is returned when there is no ownership transfer in progress but the ownership change tries to be approved. + +### WrongPotentialOwner + +```solidity +error WrongPotentialOwner() +``` + +This is returned when the ownership transfer is attempted to be validated by the a caller that is not the potential owner. diff --git a/docs/docs/developer/api/contracts/marketplace/ExecutionManager.md b/docs/docs/developer/api/contracts/marketplace/ExecutionManager.md new file mode 100644 index 00000000..981cb3a7 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/ExecutionManager.md @@ -0,0 +1,751 @@ +# ExecutionManager + +_LooksRare protocol team (👀,💎)_ + +> ExecutionManager + +This contract handles the execution and resolution of transactions. A transaction is executed on-chain when an off-chain maker order is matched by on-chain taker order of a different kind. For instance, a taker ask is executed against a maker bid (or a taker bid against a maker ask). + +## Methods + +### MAGIC_VALUE_ORDER_NONCE_EXECUTED + +```solidity +function MAGIC_VALUE_ORDER_NONCE_EXECUTED() external view returns (bytes32) +``` + +Magic value nonce returned if executed (or cancelled). + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### addStrategy + +```solidity +function addStrategy(uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) external nonpayable +``` + +This function allows the owner to add a new execution strategy to the protocol. + +_Strategies have an id that is incremental. Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ---------------------------------------------- | +| standardProtocolFeeBp | uint16 | Standard protocol fee (in basis point) | +| minTotalFeeBp | uint16 | Minimum total fee (in basis point) | +| maxProtocolFeeBp | uint16 | Maximum protocol fee (in basis point) | +| selector | bytes4 | Function selector for the strategy | +| isMakerBid | bool | Whether the function selector is for maker bid | +| implementation | address | Implementation address | + +### cancelOrderNonces + +```solidity +function cancelOrderNonces(uint256[] orderNonces) external nonpayable +``` + +This function allows a user to cancel an array of order nonces. + +_It does not check the status of the nonces to save gas and to prevent revertion if one of the orders is filled in the same block._ + +#### Parameters + +| Name | Type | Description | +| ----------- | --------- | --------------------- | +| orderNonces | uint256[] | Array of order nonces | + +### cancelOwnershipTransfer + +```solidity +function cancelOwnershipTransfer() external nonpayable +``` + +This function is used to cancel the ownership transfer. + +_This function can be used for both cancelling a transfer to a new owner and cancelling the renouncement of the ownership._ + +### cancelSubsetNonces + +```solidity +function cancelSubsetNonces(uint256[] subsetNonces) external nonpayable +``` + +This function allows a user to cancel an array of subset nonces. + +_It does not check the status of the nonces to save gas._ + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | ---------------------- | +| subsetNonces | uint256[] | Array of subset nonces | + +### confirmOwnershipRenouncement + +```solidity +function confirmOwnershipRenouncement() external nonpayable +``` + +This function is used to confirm the ownership renouncement. + +### confirmOwnershipTransfer + +```solidity +function confirmOwnershipTransfer() external nonpayable +``` + +This function is used to confirm the ownership transfer. + +_This function can only be called by the current potential owner._ + +### creatorFeeManager + +```solidity +function creatorFeeManager() external view returns (contract ICreatorFeeManager) +``` + +Creator fee manager. + +#### Returns + +| Name | Type | Description | +| ---- | --------------------------- | ----------- | +| \_0 | contract ICreatorFeeManager | undefined | + +### incrementBidAskNonces + +```solidity +function incrementBidAskNonces(bool bid, bool ask) external nonpayable +``` + +This function increments a user's bid/ask nonces. + +_The logic for computing the quasi-random number is inspired by Seaport v1.2. The pseudo-randomness allows non-deterministic computation of the next ask/bid nonce. A deterministic increment would make the cancel-all process non-effective in certain cases (orders signed with a greater ask/bid nonce). The same quasi-random number is used for incrementing both the bid and ask nonces if both values are incremented in the same transaction. If this function is used twice in the same block, it will return the same quasiRandomNumber but this will not impact the overall business logic._ + +#### Parameters + +| Name | Type | Description | +| ---- | ---- | --------------------------------------- | +| bid | bool | Whether to increment the user bid nonce | +| ask | bool | Whether to increment the user ask nonce | + +### initiateOwnershipRenouncement + +```solidity +function initiateOwnershipRenouncement() external nonpayable +``` + +This function is used to initiate the ownership renouncement. + +### initiateOwnershipTransfer + +```solidity +function initiateOwnershipTransfer(address newPotentialOwner) external nonpayable +``` + +This function is used to initiate the transfer of ownership to a new owner. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | --------------------------- | +| newPotentialOwner | address | New potential owner address | + +### isCurrencyAllowed + +```solidity +function isCurrencyAllowed(address) external view returns (bool) +``` + +It checks whether the currency is allowed for transacting. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### maxCreatorFeeBp + +```solidity +function maxCreatorFeeBp() external view returns (uint16) +``` + +Maximum creator fee (in basis point). + +#### Returns + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | uint16 | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +Address of the current owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### ownershipStatus + +```solidity +function ownershipStatus() external view returns (enum IOwnableTwoSteps.Status) +``` + +Ownership status. + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------------- | ----------- | +| \_0 | enum IOwnableTwoSteps.Status | undefined | + +### potentialOwner + +```solidity +function potentialOwner() external view returns (address) +``` + +Address of the potential owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### protocolFeeRecipient + +```solidity +function protocolFeeRecipient() external view returns (address) +``` + +Protocol fee recipient. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### strategyInfo + +```solidity +function strategyInfo(uint256) external view returns (bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) +``` + +This returns the strategy information for a strategy id. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| isActive | bool | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | +| maxProtocolFeeBp | uint16 | undefined | +| selector | bytes4 | undefined | +| isMakerBid | bool | undefined | +| implementation | address | undefined | + +### updateCreatorFeeManager + +```solidity +function updateCreatorFeeManager(address newCreatorFeeManager) external nonpayable +``` + +This function allows the owner to update the creator fee manager address. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| -------------------- | ------- | ---------------------------------- | +| newCreatorFeeManager | address | Address of the creator fee manager | + +### updateCurrencyStatus + +```solidity +function updateCurrencyStatus(address currency, bool isAllowed) external nonpayable +``` + +This function allows the owner to update the status of a currency. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | -------------------------------------------------- | +| currency | address | Currency address (address(0) for ETH) | +| isAllowed | bool | Whether the currency should be allowed for trading | + +### updateMaxCreatorFeeBp + +```solidity +function updateMaxCreatorFeeBp(uint16 newMaxCreatorFeeBp) external nonpayable +``` + +This function allows the owner to update the maximum creator fee (in basis point). + +_The maximum value that can be set is 25%. Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ------------------ | ------ | ---------------------------------------- | +| newMaxCreatorFeeBp | uint16 | New maximum creator fee (in basis point) | + +### updateProtocolFeeRecipient + +```solidity +function updateProtocolFeeRecipient(address newProtocolFeeRecipient) external nonpayable +``` + +This function allows the owner to update the protocol fee recipient. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ----------------------- | ------- | ---------------------------------- | +| newProtocolFeeRecipient | address | New protocol fee recipient address | + +### updateStrategy + +```solidity +function updateStrategy(uint256 strategyId, bool isActive, uint16 newStandardProtocolFee, uint16 newMinTotalFee) external nonpayable +``` + +This function allows the owner to update parameters for an existing execution strategy. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ---------------------- | ------- | ------------------------------------------ | +| strategyId | uint256 | Strategy id | +| isActive | bool | Whether the strategy must be active | +| newStandardProtocolFee | uint16 | New standard protocol fee (in basis point) | +| newMinTotalFee | uint16 | New minimum total fee (in basis point) | + +### userBidAskNonces + +```solidity +function userBidAskNonces(address) external view returns (uint256 bidNonce, uint256 askNonce) +``` + +This tracks the bid and ask nonces for a user address. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +#### Returns + +| Name | Type | Description | +| -------- | ------- | ----------- | +| bidNonce | uint256 | undefined | +| askNonce | uint256 | undefined | + +### userOrderNonce + +```solidity +function userOrderNonce(address, uint256) external view returns (bytes32) +``` + +This checks whether the order nonce for a user was executed or cancelled. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | +| \_1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### userSubsetNonce + +```solidity +function userSubsetNonce(address, uint256) external view returns (bool) +``` + +This checks whether the subset nonce for a user was cancelled. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | +| \_1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +## Events + +### CancelOwnershipTransfer + +```solidity +event CancelOwnershipTransfer() +``` + +This is emitted if the ownership transfer is cancelled. + +### CurrencyStatusUpdated + +```solidity +event CurrencyStatusUpdated(address currency, bool isAllowed) +``` + +It is emitted if the currency status in the allowlist is updated. + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | ----------- | +| currency | address | undefined | +| isAllowed | bool | undefined | + +### InitiateOwnershipRenouncement + +```solidity +event InitiateOwnershipRenouncement() +``` + +This is emitted if the ownership renouncement is initiated. + +### InitiateOwnershipTransfer + +```solidity +event InitiateOwnershipTransfer(address previousOwner, address potentialOwner) +``` + +This is emitted if the ownership transfer is initiated. + +#### Parameters + +| Name | Type | Description | +| -------------- | ------- | ----------- | +| previousOwner | address | undefined | +| potentialOwner | address | undefined | + +### NewBidAskNonces + +```solidity +event NewBidAskNonces(address user, uint256 bidNonce, uint256 askNonce) +``` + +It is emitted when there is an update of the global bid/ask nonces for a user. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| user | address | undefined | +| bidNonce | uint256 | undefined | +| askNonce | uint256 | undefined | + +### NewCreatorFeeManager + +```solidity +event NewCreatorFeeManager(address creatorFeeManager) +``` + +It is issued when there is a new creator fee manager. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| creatorFeeManager | address | undefined | + +### NewMaxCreatorFeeBp + +```solidity +event NewMaxCreatorFeeBp(uint256 maxCreatorFeeBp) +``` + +It is issued when there is a new maximum creator fee (in basis point). + +#### Parameters + +| Name | Type | Description | +| --------------- | ------- | ----------- | +| maxCreatorFeeBp | uint256 | undefined | + +### NewOwner + +```solidity +event NewOwner(address newOwner) +``` + +This is emitted when there is a new owner. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +### NewProtocolFeeRecipient + +```solidity +event NewProtocolFeeRecipient(address protocolFeeRecipient) +``` + +It is issued when there is a new protocol fee recipient address. + +#### Parameters + +| Name | Type | Description | +| -------------------- | ------- | ----------- | +| protocolFeeRecipient | address | undefined | + +### NewStrategy + +```solidity +event NewStrategy(uint256 strategyId, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) +``` + +It is emitted when a new strategy is added. + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| strategyId | uint256 | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | +| maxProtocolFeeBp | uint16 | undefined | +| selector | bytes4 | undefined | +| isMakerBid | bool | undefined | +| implementation | address | undefined | + +### OrderNoncesCancelled + +```solidity +event OrderNoncesCancelled(address user, uint256[] orderNonces) +``` + +It is emitted when order nonces are cancelled for a user. + +#### Parameters + +| Name | Type | Description | +| ----------- | --------- | ----------- | +| user | address | undefined | +| orderNonces | uint256[] | undefined | + +### StrategyUpdated + +```solidity +event StrategyUpdated(uint256 strategyId, bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp) +``` + +It is emitted when an existing strategy is updated. + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| strategyId | uint256 | undefined | +| isActive | bool | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | + +### SubsetNoncesCancelled + +```solidity +event SubsetNoncesCancelled(address user, uint256[] subsetNonces) +``` + +It is emitted when subset nonces are cancelled for a user. + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | ----------- | +| user | address | undefined | +| subsetNonces | uint256[] | undefined | + +## Errors + +### CreatorFeeBpTooHigh + +```solidity +error CreatorFeeBpTooHigh() +``` + +It is returned if the creator fee (in basis point) is too high. + +### LengthsInvalid + +```solidity +error LengthsInvalid() +``` + +It is returned if there is either a mismatch or an error in the length of the array(s). + +### NewProtocolFeeRecipientCannotBeNullAddress + +```solidity +error NewProtocolFeeRecipientCannotBeNullAddress() +``` + +It is returned if the new protocol fee recipient is set to address(0). + +### NoOngoingTransferInProgress + +```solidity +error NoOngoingTransferInProgress() +``` + +This is returned when there is no transfer of ownership in progress. + +### NoSelectorForStrategy + +```solidity +error NoSelectorForStrategy() +``` + +It is returned if there is no selector for maker ask/bid for a given strategyId, depending on the quote type. + +### NotOwner + +```solidity +error NotOwner() +``` + +This is returned when the caller is not the owner. + +### NotV2Strategy + +```solidity +error NotV2Strategy() +``` + +If the strategy has not set properly its implementation contract. + +_It can only be returned for owner operations._ + +### OutsideOfTimeRange + +```solidity +error OutsideOfTimeRange() +``` + +It is returned if the current block timestamp is not between start and end times in the maker order. + +### RenouncementNotInProgress + +```solidity +error RenouncementNotInProgress() +``` + +This is returned when there is no renouncement in progress but the owner tries to validate the ownership renouncement. + +### StrategyHasNoSelector + +```solidity +error StrategyHasNoSelector() +``` + +It is returned if the strategy has no selector. + +_It can only be returned for owner operations._ + +### StrategyNotAvailable + +```solidity +error StrategyNotAvailable(uint256 strategyId) +``` + +It is returned if the strategy id has no implementation. + +_It is returned if there is no implementation address and the strategyId is strictly greater than 0._ + +#### Parameters + +| Name | Type | Description | +| ---------- | ------- | ----------- | +| strategyId | uint256 | undefined | + +### StrategyNotUsed + +```solidity +error StrategyNotUsed() +``` + +It is returned if the strategyId is invalid. + +### StrategyProtocolFeeTooHigh + +```solidity +error StrategyProtocolFeeTooHigh() +``` + +It is returned if the strategy's protocol fee is too high. + +_It can only be returned for owner operations._ + +### TransferAlreadyInProgress + +```solidity +error TransferAlreadyInProgress() +``` + +This is returned when the transfer is already in progress but the owner tries initiate a new ownership transfer. + +### TransferNotInProgress + +```solidity +error TransferNotInProgress() +``` + +This is returned when there is no ownership transfer in progress but the ownership change tries to be approved. + +### WrongPotentialOwner + +```solidity +error WrongPotentialOwner() +``` + +This is returned when the ownership transfer is attempted to be validated by the a caller that is not the potential owner. diff --git a/docs/docs/developer/api/contracts/marketplace/InheritedStrategy.md b/docs/docs/developer/api/contracts/marketplace/InheritedStrategy.md new file mode 100644 index 00000000..022cce57 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/InheritedStrategy.md @@ -0,0 +1,9 @@ +# InheritedStrategy + +_LooksRare protocol team (👀,💎)_ + +> InheritedStrategy + +This contract handles the verification of parameters for standard transactions. It does not verify the taker struct's itemIds and amounts array as well as minPrice (taker ask) / maxPrice (taker bid) because before the taker executes the transaction and the maker itemIds/amounts/price should have already been confirmed off-chain. + +_A standard transaction (bid or ask) is mapped to strategyId = 0._ diff --git a/docs/docs/developer/api/contracts/marketplace/LooksRareProtocol.md b/docs/docs/developer/api/contracts/marketplace/LooksRareProtocol.md new file mode 100644 index 00000000..fca005d6 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/LooksRareProtocol.md @@ -0,0 +1,1157 @@ +# LooksRareProtocol + +_LooksRare protocol team (👀,💎)_ + +> LooksRareProtocol + +This contract is the core smart contract of the LooksRare protocol ("v2"). It is the main entry point for users to initiate transactions with taker orders and manage the cancellation of maker orders, which exist off-chain. ~~~~~~ ~~~~ ~~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~~~~~~~ ~~~ ~~~ ~~~~~~~~~ ~~~ ~~~~~~~~~ ~~~~ ~~~~ ~~~~~~~~~ ~~~ ~~~ ~~~~~~~ ~~~~~~~ ~~~ ~~~- ~~~~~~~~ ~~~~ ~~~ ~~~~ ~~~~ ~~~ ~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~ ~~~ ~~~~~~~~~~~ ~~~~~~~~~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~~~~~~~~ ~~~ ~~~ ~~~~~ ~~~ ~~~~~~ ~~~~~~ ~~~ ~~~~~ ~~~~~~~ ~~~ ~~~ ~~~ ~~~ ~~~~~~~ ~~~~~~ ~~~~ ~~~ ~~~ ~~~~ ~~~~~~ ~~~~ ~~~ ~~~ ~~~ ~~~ ~~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~~ ~~~ ~~~ ~~~ ~~~ ~~~~ ~~~~~~ ~~~~ ~~~ ~~~ ~~~~~ ~~~~~~ ~~~~~~~ ~~~ ~~~ ~~~ ~~~ ~~~~~~~ ~~~~~ ~~~ ~~~~~~ ~~~~~~ ~~~ ~~~~~ ~~~ ~~~ ~~~~~~~~~~ ~~~ ~~~ ~~ ~~~ ~~~ ~~~ ~~~ ~~~~~~~~~~~ ~~~~~~~~~~~ ~~~ ~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~ ~~~ ~~~~ ~~~~ ~~~ ~~~~ ~~~~~~~~ ~~~~ ~~~ ~~~~~~~ ~~~~~~~ ~~~ ~~~ ~~~~~~~~ ~~~~ ~~~~ ~~~~~~~~ ~~~ ~~~~~~~~~ ~~~ ~~~ ~~~~~~~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~~ ~~~~ ~~~~~~ + +## Methods + +### MAGIC_VALUE_ORDER_NONCE_EXECUTED + +```solidity +function MAGIC_VALUE_ORDER_NONCE_EXECUTED() external view returns (bytes32) +``` + +Magic value nonce returned if executed (or cancelled). + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### WETH + +```solidity +function WETH() external view returns (address) +``` + +Wrapped ETH. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### addStrategy + +```solidity +function addStrategy(uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) external nonpayable +``` + +This function allows the owner to add a new execution strategy to the protocol. + +_Strategies have an id that is incremental. Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ---------------------------------------------- | +| standardProtocolFeeBp | uint16 | Standard protocol fee (in basis point) | +| minTotalFeeBp | uint16 | Minimum total fee (in basis point) | +| maxProtocolFeeBp | uint16 | Maximum protocol fee (in basis point) | +| selector | bytes4 | Function selector for the strategy | +| isMakerBid | bool | Whether the function selector is for maker bid | +| implementation | address | Implementation address | + +### cancelOrderNonces + +```solidity +function cancelOrderNonces(uint256[] orderNonces) external nonpayable +``` + +This function allows a user to cancel an array of order nonces. + +_It does not check the status of the nonces to save gas and to prevent revertion if one of the orders is filled in the same block._ + +#### Parameters + +| Name | Type | Description | +| ----------- | --------- | --------------------- | +| orderNonces | uint256[] | Array of order nonces | + +### cancelOwnershipTransfer + +```solidity +function cancelOwnershipTransfer() external nonpayable +``` + +This function is used to cancel the ownership transfer. + +_This function can be used for both cancelling a transfer to a new owner and cancelling the renouncement of the ownership._ + +### cancelSubsetNonces + +```solidity +function cancelSubsetNonces(uint256[] subsetNonces) external nonpayable +``` + +This function allows a user to cancel an array of subset nonces. + +_It does not check the status of the nonces to save gas._ + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | ---------------------- | +| subsetNonces | uint256[] | Array of subset nonces | + +### chainId + +```solidity +function chainId() external view returns (uint256) +``` + +Current chainId. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +### confirmOwnershipRenouncement + +```solidity +function confirmOwnershipRenouncement() external nonpayable +``` + +This function is used to confirm the ownership renouncement. + +### confirmOwnershipTransfer + +```solidity +function confirmOwnershipTransfer() external nonpayable +``` + +This function is used to confirm the ownership transfer. + +_This function can only be called by the current potential owner._ + +### creatorFeeManager + +```solidity +function creatorFeeManager() external view returns (contract ICreatorFeeManager) +``` + +Creator fee manager. + +#### Returns + +| Name | Type | Description | +| ---- | --------------------------- | ----------- | +| \_0 | contract ICreatorFeeManager | undefined | + +### domainSeparator + +```solidity +function domainSeparator() external view returns (bytes32) +``` + +Current domain separator. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### executeMultipleTakerBids + +```solidity +function executeMultipleTakerBids(OrderStructs.Taker[] takerBids, OrderStructs.Maker[] makerAsks, bytes[] makerSignatures, OrderStructs.MerkleTree[] merkleTrees, bool isAtomic) external payable +``` + +#### Parameters + +| Name | Type | Description | +| --------------- | ------------------------- | ----------- | +| takerBids | OrderStructs.Taker[] | undefined | +| makerAsks | OrderStructs.Maker[] | undefined | +| makerSignatures | bytes[] | undefined | +| merkleTrees | OrderStructs.MerkleTree[] | undefined | +| isAtomic | bool | undefined | + +### executeTakerAsk + +```solidity +function executeTakerAsk(OrderStructs.Taker takerAsk, OrderStructs.Maker makerBid, bytes makerSignature, OrderStructs.MerkleTree merkleTree) external nonpayable +``` + +#### Parameters + +| Name | Type | Description | +| -------------- | ----------------------- | ----------- | +| takerAsk | OrderStructs.Taker | undefined | +| makerBid | OrderStructs.Maker | undefined | +| makerSignature | bytes | undefined | +| merkleTree | OrderStructs.MerkleTree | undefined | + +### executeTakerBid + +```solidity +function executeTakerBid(OrderStructs.Taker takerBid, OrderStructs.Maker makerAsk, bytes makerSignature, OrderStructs.MerkleTree merkleTree) external payable +``` + +#### Parameters + +| Name | Type | Description | +| -------------- | ----------------------- | ----------- | +| takerBid | OrderStructs.Taker | undefined | +| makerAsk | OrderStructs.Maker | undefined | +| makerSignature | bytes | undefined | +| merkleTree | OrderStructs.MerkleTree | undefined | + +### hashBatchOrder + +```solidity +function hashBatchOrder(bytes32 root, uint256 proofLength) external pure returns (bytes32 batchOrderHash) +``` + +This function returns the hash of the concatenation of batch order type hash and merkle root. + +#### Parameters + +| Name | Type | Description | +| ----------- | ------- | ------------------- | +| root | bytes32 | Merkle root | +| proofLength | uint256 | Merkle proof length | + +#### Returns + +| Name | Type | Description | +| -------------- | ------- | -------------------- | +| batchOrderHash | bytes32 | The batch order hash | + +### incrementBidAskNonces + +```solidity +function incrementBidAskNonces(bool bid, bool ask) external nonpayable +``` + +This function increments a user's bid/ask nonces. + +_The logic for computing the quasi-random number is inspired by Seaport v1.2. The pseudo-randomness allows non-deterministic computation of the next ask/bid nonce. A deterministic increment would make the cancel-all process non-effective in certain cases (orders signed with a greater ask/bid nonce). The same quasi-random number is used for incrementing both the bid and ask nonces if both values are incremented in the same transaction. If this function is used twice in the same block, it will return the same quasiRandomNumber but this will not impact the overall business logic._ + +#### Parameters + +| Name | Type | Description | +| ---- | ---- | --------------------------------------- | +| bid | bool | Whether to increment the user bid nonce | +| ask | bool | Whether to increment the user ask nonce | + +### initiateOwnershipRenouncement + +```solidity +function initiateOwnershipRenouncement() external nonpayable +``` + +This function is used to initiate the ownership renouncement. + +### initiateOwnershipTransfer + +```solidity +function initiateOwnershipTransfer(address newPotentialOwner) external nonpayable +``` + +This function is used to initiate the transfer of ownership to a new owner. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | --------------------------- | +| newPotentialOwner | address | New potential owner address | + +### isCurrencyAllowed + +```solidity +function isCurrencyAllowed(address) external view returns (bool) +``` + +It checks whether the currency is allowed for transacting. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### maxCreatorFeeBp + +```solidity +function maxCreatorFeeBp() external view returns (uint16) +``` + +Maximum creator fee (in basis point). + +#### Returns + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | uint16 | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +Address of the current owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### ownershipStatus + +```solidity +function ownershipStatus() external view returns (enum IOwnableTwoSteps.Status) +``` + +Ownership status. + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------------- | ----------- | +| \_0 | enum IOwnableTwoSteps.Status | undefined | + +### potentialOwner + +```solidity +function potentialOwner() external view returns (address) +``` + +Address of the potential owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### protocolFeeRecipient + +```solidity +function protocolFeeRecipient() external view returns (address) +``` + +Protocol fee recipient. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### restrictedExecuteTakerBid + +```solidity +function restrictedExecuteTakerBid(OrderStructs.Taker takerBid, OrderStructs.Maker makerAsk, address sender, bytes32 orderHash) external nonpayable returns (uint256 protocolFeeAmount) +``` + +#### Parameters + +| Name | Type | Description | +| --------- | ------------------ | ----------- | +| takerBid | OrderStructs.Taker | undefined | +| makerAsk | OrderStructs.Maker | undefined | +| sender | address | undefined | +| orderHash | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| protocolFeeAmount | uint256 | undefined | + +### strategyInfo + +```solidity +function strategyInfo(uint256) external view returns (bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) +``` + +This returns the strategy information for a strategy id. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| isActive | bool | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | +| maxProtocolFeeBp | uint16 | undefined | +| selector | bytes4 | undefined | +| isMakerBid | bool | undefined | +| implementation | address | undefined | + +### transferManager + +```solidity +function transferManager() external view returns (contract TransferManager) +``` + +Transfer manager for ERC721 and ERC1155. + +#### Returns + +| Name | Type | Description | +| ---- | ------------------------ | ----------- | +| \_0 | contract TransferManager | undefined | + +### updateCreatorFeeManager + +```solidity +function updateCreatorFeeManager(address newCreatorFeeManager) external nonpayable +``` + +This function allows the owner to update the creator fee manager address. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| -------------------- | ------- | ---------------------------------- | +| newCreatorFeeManager | address | Address of the creator fee manager | + +### updateCurrencyStatus + +```solidity +function updateCurrencyStatus(address currency, bool isAllowed) external nonpayable +``` + +This function allows the owner to update the status of a currency. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | -------------------------------------------------- | +| currency | address | Currency address (address(0) for ETH) | +| isAllowed | bool | Whether the currency should be allowed for trading | + +### updateDomainSeparator + +```solidity +function updateDomainSeparator() external nonpayable +``` + +This function allows the owner to update the domain separator (if possible). + +_Only callable by owner. If there is a fork of the network with a new chainId, it allows the owner to reset the domain separator for the new chain id._ + +### updateETHGasLimitForTransfer + +```solidity +function updateETHGasLimitForTransfer(uint256 newGasLimitETHTransfer) external nonpayable +``` + +This function allows the owner to update the maximum ETH gas limit for a standard transfer. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ---------------------- | ------- | ------------------------------ | +| newGasLimitETHTransfer | uint256 | New gas limit for ETH transfer | + +### updateMaxCreatorFeeBp + +```solidity +function updateMaxCreatorFeeBp(uint16 newMaxCreatorFeeBp) external nonpayable +``` + +This function allows the owner to update the maximum creator fee (in basis point). + +_The maximum value that can be set is 25%. Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ------------------ | ------ | ---------------------------------------- | +| newMaxCreatorFeeBp | uint16 | New maximum creator fee (in basis point) | + +### updateProtocolFeeRecipient + +```solidity +function updateProtocolFeeRecipient(address newProtocolFeeRecipient) external nonpayable +``` + +This function allows the owner to update the protocol fee recipient. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ----------------------- | ------- | ---------------------------------- | +| newProtocolFeeRecipient | address | New protocol fee recipient address | + +### updateStrategy + +```solidity +function updateStrategy(uint256 strategyId, bool isActive, uint16 newStandardProtocolFee, uint16 newMinTotalFee) external nonpayable +``` + +This function allows the owner to update parameters for an existing execution strategy. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ---------------------- | ------- | ------------------------------------------ | +| strategyId | uint256 | Strategy id | +| isActive | bool | Whether the strategy must be active | +| newStandardProtocolFee | uint16 | New standard protocol fee (in basis point) | +| newMinTotalFee | uint16 | New minimum total fee (in basis point) | + +### userBidAskNonces + +```solidity +function userBidAskNonces(address) external view returns (uint256 bidNonce, uint256 askNonce) +``` + +This tracks the bid and ask nonces for a user address. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +#### Returns + +| Name | Type | Description | +| -------- | ------- | ----------- | +| bidNonce | uint256 | undefined | +| askNonce | uint256 | undefined | + +### userOrderNonce + +```solidity +function userOrderNonce(address, uint256) external view returns (bytes32) +``` + +This checks whether the order nonce for a user was executed or cancelled. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | +| \_1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### userSubsetNonce + +```solidity +function userSubsetNonce(address, uint256) external view returns (bool) +``` + +This checks whether the subset nonce for a user was cancelled. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | +| \_1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +## Events + +### CancelOwnershipTransfer + +```solidity +event CancelOwnershipTransfer() +``` + +This is emitted if the ownership transfer is cancelled. + +### CurrencyStatusUpdated + +```solidity +event CurrencyStatusUpdated(address currency, bool isAllowed) +``` + +It is emitted if the currency status in the allowlist is updated. + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | ----------- | +| currency | address | undefined | +| isAllowed | bool | undefined | + +### InitiateOwnershipRenouncement + +```solidity +event InitiateOwnershipRenouncement() +``` + +This is emitted if the ownership renouncement is initiated. + +### InitiateOwnershipTransfer + +```solidity +event InitiateOwnershipTransfer(address previousOwner, address potentialOwner) +``` + +This is emitted if the ownership transfer is initiated. + +#### Parameters + +| Name | Type | Description | +| -------------- | ------- | ----------- | +| previousOwner | address | undefined | +| potentialOwner | address | undefined | + +### NewBidAskNonces + +```solidity +event NewBidAskNonces(address user, uint256 bidNonce, uint256 askNonce) +``` + +It is emitted when there is an update of the global bid/ask nonces for a user. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| user | address | undefined | +| bidNonce | uint256 | undefined | +| askNonce | uint256 | undefined | + +### NewCreatorFeeManager + +```solidity +event NewCreatorFeeManager(address creatorFeeManager) +``` + +It is issued when there is a new creator fee manager. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| creatorFeeManager | address | undefined | + +### NewDomainSeparator + +```solidity +event NewDomainSeparator() +``` + +It is emitted if there is a change in the domain separator. + +### NewGasLimitETHTransfer + +```solidity +event NewGasLimitETHTransfer(uint256 gasLimitETHTransfer) +``` + +It is emitted when there is a new gas limit for a ETH transfer (before it is wrapped to WETH). + +#### Parameters + +| Name | Type | Description | +| ------------------- | ------- | ----------- | +| gasLimitETHTransfer | uint256 | undefined | + +### NewMaxCreatorFeeBp + +```solidity +event NewMaxCreatorFeeBp(uint256 maxCreatorFeeBp) +``` + +It is issued when there is a new maximum creator fee (in basis point). + +#### Parameters + +| Name | Type | Description | +| --------------- | ------- | ----------- | +| maxCreatorFeeBp | uint256 | undefined | + +### NewOwner + +```solidity +event NewOwner(address newOwner) +``` + +This is emitted when there is a new owner. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +### NewProtocolFeeRecipient + +```solidity +event NewProtocolFeeRecipient(address protocolFeeRecipient) +``` + +It is issued when there is a new protocol fee recipient address. + +#### Parameters + +| Name | Type | Description | +| -------------------- | ------- | ----------- | +| protocolFeeRecipient | address | undefined | + +### NewStrategy + +```solidity +event NewStrategy(uint256 strategyId, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) +``` + +It is emitted when a new strategy is added. + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| strategyId | uint256 | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | +| maxProtocolFeeBp | uint16 | undefined | +| selector | bytes4 | undefined | +| isMakerBid | bool | undefined | +| implementation | address | undefined | + +### OrderNoncesCancelled + +```solidity +event OrderNoncesCancelled(address user, uint256[] orderNonces) +``` + +It is emitted when order nonces are cancelled for a user. + +#### Parameters + +| Name | Type | Description | +| ----------- | --------- | ----------- | +| user | address | undefined | +| orderNonces | uint256[] | undefined | + +### StrategyUpdated + +```solidity +event StrategyUpdated(uint256 strategyId, bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp) +``` + +It is emitted when an existing strategy is updated. + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| strategyId | uint256 | undefined | +| isActive | bool | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | + +### SubsetNoncesCancelled + +```solidity +event SubsetNoncesCancelled(address user, uint256[] subsetNonces) +``` + +It is emitted when subset nonces are cancelled for a user. + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | ----------- | +| user | address | undefined | +| subsetNonces | uint256[] | undefined | + +### TakerAsk + +```solidity +event TakerAsk(ILooksRareProtocol.NonceInvalidationParameters nonceInvalidationParameters, address askUser, address bidUser, uint256 strategyId, address currency, address collection, uint256[] itemIds, uint256[] amounts, address[2] feeRecipients, uint256[3] feeAmounts) +``` + +It is emitted when a taker ask transaction is completed. + +#### Parameters + +| Name | Type | Description | +| --------------------------- | ---------------------------------------------- | ----------- | +| nonceInvalidationParameters | ILooksRareProtocol.NonceInvalidationParameters | undefined | +| askUser | address | undefined | +| bidUser | address | undefined | +| strategyId | uint256 | undefined | +| currency | address | undefined | +| collection | address | undefined | +| itemIds | uint256[] | undefined | +| amounts | uint256[] | undefined | +| feeRecipients | address[2] | undefined | +| feeAmounts | uint256[3] | undefined | + +### TakerBid + +```solidity +event TakerBid(ILooksRareProtocol.NonceInvalidationParameters nonceInvalidationParameters, address bidUser, address bidRecipient, uint256 strategyId, address currency, address collection, uint256[] itemIds, uint256[] amounts, address[2] feeRecipients, uint256[3] feeAmounts) +``` + +It is emitted when a taker bid transaction is completed. + +#### Parameters + +| Name | Type | Description | +| --------------------------- | ---------------------------------------------- | ----------- | +| nonceInvalidationParameters | ILooksRareProtocol.NonceInvalidationParameters | undefined | +| bidUser | address | undefined | +| bidRecipient | address | undefined | +| strategyId | uint256 | undefined | +| currency | address | undefined | +| collection | address | undefined | +| itemIds | uint256[] | undefined | +| amounts | uint256[] | undefined | +| feeRecipients | address[2] | undefined | +| feeAmounts | uint256[3] | undefined | + +## Errors + +### CallerInvalid + +```solidity +error CallerInvalid() +``` + +It is returned if the function cannot be called by the sender. + +### ChainIdInvalid + +```solidity +error ChainIdInvalid() +``` + +It is returned if the domain separator should change. + +### CreatorFeeBpTooHigh + +```solidity +error CreatorFeeBpTooHigh() +``` + +It is returned if the creator fee (in basis point) is too high. + +### CurrencyInvalid + +```solidity +error CurrencyInvalid() +``` + +It is returned if the currency is invalid. + +### ERC20TransferFromFail + +```solidity +error ERC20TransferFromFail() +``` + +It is emitted if the ERC20 transferFrom fails. + +### LengthsInvalid + +```solidity +error LengthsInvalid() +``` + +It is returned if there is either a mismatch or an error in the length of the array(s). + +### MerkleProofInvalid + +```solidity +error MerkleProofInvalid() +``` + +It is returned if the merkle proof provided is invalid. + +### MerkleProofTooLarge + +```solidity +error MerkleProofTooLarge(uint256 length) +``` + +It is returned if the length of the merkle proof provided is greater than tolerated. + +#### Parameters + +| Name | Type | Description | +| ------ | ------- | ------------ | +| length | uint256 | Proof length | + +### NewGasLimitETHTransferTooLow + +```solidity +error NewGasLimitETHTransferTooLow() +``` + +It is returned if the gas limit for a standard ETH transfer is too low. + +### NewProtocolFeeRecipientCannotBeNullAddress + +```solidity +error NewProtocolFeeRecipientCannotBeNullAddress() +``` + +It is returned if the new protocol fee recipient is set to address(0). + +### NoOngoingTransferInProgress + +```solidity +error NoOngoingTransferInProgress() +``` + +This is returned when there is no transfer of ownership in progress. + +### NoSelectorForStrategy + +```solidity +error NoSelectorForStrategy() +``` + +It is returned if there is no selector for maker ask/bid for a given strategyId, depending on the quote type. + +### NoncesInvalid + +```solidity +error NoncesInvalid() +``` + +It is returned if the nonces are invalid. + +### NotAContract + +```solidity +error NotAContract() +``` + +It is emitted if the call recipient is not a contract. + +### NotOwner + +```solidity +error NotOwner() +``` + +This is returned when the caller is not the owner. + +### NotV2Strategy + +```solidity +error NotV2Strategy() +``` + +If the strategy has not set properly its implementation contract. + +_It can only be returned for owner operations._ + +### NullSignerAddress + +```solidity +error NullSignerAddress() +``` + +It is emitted if the signer is null. + +### OutsideOfTimeRange + +```solidity +error OutsideOfTimeRange() +``` + +It is returned if the current block timestamp is not between start and end times in the maker order. + +### QuoteTypeInvalid + +```solidity +error QuoteTypeInvalid() +``` + +It is returned if the maker quote type is invalid. + +### ReentrancyFail + +```solidity +error ReentrancyFail() +``` + +This is returned when there is a reentrant call. + +### RenouncementNotInProgress + +```solidity +error RenouncementNotInProgress() +``` + +This is returned when there is no renouncement in progress but the owner tries to validate the ownership renouncement. + +### SameDomainSeparator + +```solidity +error SameDomainSeparator() +``` + +It is returned if the domain separator cannot be updated (i.e. the chainId is the same). + +### SignatureEOAInvalid + +```solidity +error SignatureEOAInvalid() +``` + +It is emitted if the signature is invalid for an EOA (the address recovered is not the expected one). + +### SignatureERC1271Invalid + +```solidity +error SignatureERC1271Invalid() +``` + +It is emitted if the signature is invalid for a ERC1271 contract signer. + +### SignatureLengthInvalid + +```solidity +error SignatureLengthInvalid(uint256 length) +``` + +It is emitted if the signature's length is neither 64 nor 65 bytes. + +#### Parameters + +| Name | Type | Description | +| ------ | ------- | ----------- | +| length | uint256 | undefined | + +### SignatureParameterSInvalid + +```solidity +error SignatureParameterSInvalid() +``` + +It is emitted if the signature is invalid due to S parameter. + +### SignatureParameterVInvalid + +```solidity +error SignatureParameterVInvalid(uint8 v) +``` + +It is emitted if the signature is invalid due to V parameter. + +#### Parameters + +| Name | Type | Description | +| ---- | ----- | ----------- | +| v | uint8 | undefined | + +### StrategyHasNoSelector + +```solidity +error StrategyHasNoSelector() +``` + +It is returned if the strategy has no selector. + +_It can only be returned for owner operations._ + +### StrategyNotAvailable + +```solidity +error StrategyNotAvailable(uint256 strategyId) +``` + +It is returned if the strategy id has no implementation. + +_It is returned if there is no implementation address and the strategyId is strictly greater than 0._ + +#### Parameters + +| Name | Type | Description | +| ---------- | ------- | ----------- | +| strategyId | uint256 | undefined | + +### StrategyNotUsed + +```solidity +error StrategyNotUsed() +``` + +It is returned if the strategyId is invalid. + +### StrategyProtocolFeeTooHigh + +```solidity +error StrategyProtocolFeeTooHigh() +``` + +It is returned if the strategy's protocol fee is too high. + +_It can only be returned for owner operations._ + +### TransferAlreadyInProgress + +```solidity +error TransferAlreadyInProgress() +``` + +This is returned when the transfer is already in progress but the owner tries initiate a new ownership transfer. + +### TransferNotInProgress + +```solidity +error TransferNotInProgress() +``` + +This is returned when there is no ownership transfer in progress but the ownership change tries to be approved. + +### UnsupportedCollectionType + +```solidity +error UnsupportedCollectionType() +``` + +### WrongPotentialOwner + +```solidity +error WrongPotentialOwner() +``` + +This is returned when the ownership transfer is attempted to be validated by the a caller that is not the potential owner. diff --git a/docs/docs/developer/api/contracts/marketplace/NonceManager.md b/docs/docs/developer/api/contracts/marketplace/NonceManager.md new file mode 100644 index 00000000..fea95495 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/NonceManager.md @@ -0,0 +1,193 @@ +# NonceManager + +_LooksRare protocol team (👀,💎)_ + +> NonceManager + +This contract handles the nonce logic that is used for invalidating maker orders that exist off-chain. The nonce logic revolves around three parts at the user level: - order nonce (orders sharing an order nonce are conditional, OCO-like) - subset (orders can be grouped under a same subset) - bid/ask (all orders can be executed only if the bid/ask nonce matches the user's one on-chain) Only the order nonce is invalidated at the time of the execution of a maker order that contains it. + +## Methods + +### MAGIC_VALUE_ORDER_NONCE_EXECUTED + +```solidity +function MAGIC_VALUE_ORDER_NONCE_EXECUTED() external view returns (bytes32) +``` + +Magic value nonce returned if executed (or cancelled). + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### cancelOrderNonces + +```solidity +function cancelOrderNonces(uint256[] orderNonces) external nonpayable +``` + +This function allows a user to cancel an array of order nonces. + +_It does not check the status of the nonces to save gas and to prevent revertion if one of the orders is filled in the same block._ + +#### Parameters + +| Name | Type | Description | +| ----------- | --------- | --------------------- | +| orderNonces | uint256[] | Array of order nonces | + +### cancelSubsetNonces + +```solidity +function cancelSubsetNonces(uint256[] subsetNonces) external nonpayable +``` + +This function allows a user to cancel an array of subset nonces. + +_It does not check the status of the nonces to save gas._ + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | ---------------------- | +| subsetNonces | uint256[] | Array of subset nonces | + +### incrementBidAskNonces + +```solidity +function incrementBidAskNonces(bool bid, bool ask) external nonpayable +``` + +This function increments a user's bid/ask nonces. + +_The logic for computing the quasi-random number is inspired by Seaport v1.2. The pseudo-randomness allows non-deterministic computation of the next ask/bid nonce. A deterministic increment would make the cancel-all process non-effective in certain cases (orders signed with a greater ask/bid nonce). The same quasi-random number is used for incrementing both the bid and ask nonces if both values are incremented in the same transaction. If this function is used twice in the same block, it will return the same quasiRandomNumber but this will not impact the overall business logic._ + +#### Parameters + +| Name | Type | Description | +| ---- | ---- | --------------------------------------- | +| bid | bool | Whether to increment the user bid nonce | +| ask | bool | Whether to increment the user ask nonce | + +### userBidAskNonces + +```solidity +function userBidAskNonces(address) external view returns (uint256 bidNonce, uint256 askNonce) +``` + +This tracks the bid and ask nonces for a user address. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +#### Returns + +| Name | Type | Description | +| -------- | ------- | ----------- | +| bidNonce | uint256 | undefined | +| askNonce | uint256 | undefined | + +### userOrderNonce + +```solidity +function userOrderNonce(address, uint256) external view returns (bytes32) +``` + +This checks whether the order nonce for a user was executed or cancelled. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | +| \_1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### userSubsetNonce + +```solidity +function userSubsetNonce(address, uint256) external view returns (bool) +``` + +This checks whether the subset nonce for a user was cancelled. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | +| \_1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +## Events + +### NewBidAskNonces + +```solidity +event NewBidAskNonces(address user, uint256 bidNonce, uint256 askNonce) +``` + +It is emitted when there is an update of the global bid/ask nonces for a user. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| user | address | undefined | +| bidNonce | uint256 | undefined | +| askNonce | uint256 | undefined | + +### OrderNoncesCancelled + +```solidity +event OrderNoncesCancelled(address user, uint256[] orderNonces) +``` + +It is emitted when order nonces are cancelled for a user. + +#### Parameters + +| Name | Type | Description | +| ----------- | --------- | ----------- | +| user | address | undefined | +| orderNonces | uint256[] | undefined | + +### SubsetNoncesCancelled + +```solidity +event SubsetNoncesCancelled(address user, uint256[] subsetNonces) +``` + +It is emitted when subset nonces are cancelled for a user. + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | ----------- | +| user | address | undefined | +| subsetNonces | uint256[] | undefined | + +## Errors + +### LengthsInvalid + +```solidity +error LengthsInvalid() +``` + +It is returned if there is either a mismatch or an error in the length of the array(s). diff --git a/docs/docs/developer/api/contracts/marketplace/ProtocolFeeRecipient.md b/docs/docs/developer/api/contracts/marketplace/ProtocolFeeRecipient.md new file mode 100644 index 00000000..36f6a35c --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/ProtocolFeeRecipient.md @@ -0,0 +1,75 @@ +# ProtocolFeeRecipient + +_LooksRare protocol team (👀,💎)_ + +> ProtocolFeeRecipient + +This contract is used to receive protocol fees and transfer them to the fee sharing setter. Fee sharing setter cannot receive ETH directly, so we need to use this contract as a middleman to convert ETH into WETH before sending it. + +## Methods + +### FEE_SHARING_SETTER + +```solidity +function FEE_SHARING_SETTER() external view returns (address) +``` + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### WETH + +```solidity +function WETH() external view returns (contract IWETH) +``` + +#### Returns + +| Name | Type | Description | +| ---- | -------------- | ----------- | +| \_0 | contract IWETH | undefined | + +### transferERC20 + +```solidity +function transferERC20(address currency) external nonpayable +``` + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ---------------------- | +| currency | address | ERC20 currency address | + +### transferETH + +```solidity +function transferETH() external nonpayable +``` + +## Errors + +### ERC20TransferFail + +```solidity +error ERC20TransferFail() +``` + +It is emitted if the ERC20 transfer fails. + +### NotAContract + +```solidity +error NotAContract() +``` + +It is emitted if the call recipient is not a contract. + +### NothingToTransfer + +```solidity +error NothingToTransfer() +``` diff --git a/docs/docs/developer/api/contracts/marketplace/StrategyManager.md b/docs/docs/developer/api/contracts/marketplace/StrategyManager.md new file mode 100644 index 00000000..a55f3985 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/StrategyManager.md @@ -0,0 +1,391 @@ +# StrategyManager + +_LooksRare protocol team (👀,💎)_ + +> StrategyManager + +This contract handles the addition and the update of execution strategies. + +## Methods + +### addStrategy + +```solidity +function addStrategy(uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) external nonpayable +``` + +This function allows the owner to add a new execution strategy to the protocol. + +_Strategies have an id that is incremental. Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ---------------------------------------------- | +| standardProtocolFeeBp | uint16 | Standard protocol fee (in basis point) | +| minTotalFeeBp | uint16 | Minimum total fee (in basis point) | +| maxProtocolFeeBp | uint16 | Maximum protocol fee (in basis point) | +| selector | bytes4 | Function selector for the strategy | +| isMakerBid | bool | Whether the function selector is for maker bid | +| implementation | address | Implementation address | + +### cancelOwnershipTransfer + +```solidity +function cancelOwnershipTransfer() external nonpayable +``` + +This function is used to cancel the ownership transfer. + +_This function can be used for both cancelling a transfer to a new owner and cancelling the renouncement of the ownership._ + +### confirmOwnershipRenouncement + +```solidity +function confirmOwnershipRenouncement() external nonpayable +``` + +This function is used to confirm the ownership renouncement. + +### confirmOwnershipTransfer + +```solidity +function confirmOwnershipTransfer() external nonpayable +``` + +This function is used to confirm the ownership transfer. + +_This function can only be called by the current potential owner._ + +### initiateOwnershipRenouncement + +```solidity +function initiateOwnershipRenouncement() external nonpayable +``` + +This function is used to initiate the ownership renouncement. + +### initiateOwnershipTransfer + +```solidity +function initiateOwnershipTransfer(address newPotentialOwner) external nonpayable +``` + +This function is used to initiate the transfer of ownership to a new owner. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | --------------------------- | +| newPotentialOwner | address | New potential owner address | + +### isCurrencyAllowed + +```solidity +function isCurrencyAllowed(address) external view returns (bool) +``` + +It checks whether the currency is allowed for transacting. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +Address of the current owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### ownershipStatus + +```solidity +function ownershipStatus() external view returns (enum IOwnableTwoSteps.Status) +``` + +Ownership status. + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------------- | ----------- | +| \_0 | enum IOwnableTwoSteps.Status | undefined | + +### potentialOwner + +```solidity +function potentialOwner() external view returns (address) +``` + +Address of the potential owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### strategyInfo + +```solidity +function strategyInfo(uint256) external view returns (bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) +``` + +This returns the strategy information for a strategy id. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| isActive | bool | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | +| maxProtocolFeeBp | uint16 | undefined | +| selector | bytes4 | undefined | +| isMakerBid | bool | undefined | +| implementation | address | undefined | + +### updateCurrencyStatus + +```solidity +function updateCurrencyStatus(address currency, bool isAllowed) external nonpayable +``` + +This function allows the owner to update the status of a currency. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | -------------------------------------------------- | +| currency | address | Currency address (address(0) for ETH) | +| isAllowed | bool | Whether the currency should be allowed for trading | + +### updateStrategy + +```solidity +function updateStrategy(uint256 strategyId, bool isActive, uint16 newStandardProtocolFee, uint16 newMinTotalFee) external nonpayable +``` + +This function allows the owner to update parameters for an existing execution strategy. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ---------------------- | ------- | ------------------------------------------ | +| strategyId | uint256 | Strategy id | +| isActive | bool | Whether the strategy must be active | +| newStandardProtocolFee | uint16 | New standard protocol fee (in basis point) | +| newMinTotalFee | uint16 | New minimum total fee (in basis point) | + +## Events + +### CancelOwnershipTransfer + +```solidity +event CancelOwnershipTransfer() +``` + +This is emitted if the ownership transfer is cancelled. + +### CurrencyStatusUpdated + +```solidity +event CurrencyStatusUpdated(address currency, bool isAllowed) +``` + +It is emitted if the currency status in the allowlist is updated. + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | ----------- | +| currency | address | undefined | +| isAllowed | bool | undefined | + +### InitiateOwnershipRenouncement + +```solidity +event InitiateOwnershipRenouncement() +``` + +This is emitted if the ownership renouncement is initiated. + +### InitiateOwnershipTransfer + +```solidity +event InitiateOwnershipTransfer(address previousOwner, address potentialOwner) +``` + +This is emitted if the ownership transfer is initiated. + +#### Parameters + +| Name | Type | Description | +| -------------- | ------- | ----------- | +| previousOwner | address | undefined | +| potentialOwner | address | undefined | + +### NewOwner + +```solidity +event NewOwner(address newOwner) +``` + +This is emitted when there is a new owner. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +### NewStrategy + +```solidity +event NewStrategy(uint256 strategyId, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) +``` + +It is emitted when a new strategy is added. + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| strategyId | uint256 | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | +| maxProtocolFeeBp | uint16 | undefined | +| selector | bytes4 | undefined | +| isMakerBid | bool | undefined | +| implementation | address | undefined | + +### StrategyUpdated + +```solidity +event StrategyUpdated(uint256 strategyId, bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp) +``` + +It is emitted when an existing strategy is updated. + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| strategyId | uint256 | undefined | +| isActive | bool | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | + +## Errors + +### NoOngoingTransferInProgress + +```solidity +error NoOngoingTransferInProgress() +``` + +This is returned when there is no transfer of ownership in progress. + +### NotOwner + +```solidity +error NotOwner() +``` + +This is returned when the caller is not the owner. + +### NotV2Strategy + +```solidity +error NotV2Strategy() +``` + +If the strategy has not set properly its implementation contract. + +_It can only be returned for owner operations._ + +### RenouncementNotInProgress + +```solidity +error RenouncementNotInProgress() +``` + +This is returned when there is no renouncement in progress but the owner tries to validate the ownership renouncement. + +### StrategyHasNoSelector + +```solidity +error StrategyHasNoSelector() +``` + +It is returned if the strategy has no selector. + +_It can only be returned for owner operations._ + +### StrategyNotUsed + +```solidity +error StrategyNotUsed() +``` + +It is returned if the strategyId is invalid. + +### StrategyProtocolFeeTooHigh + +```solidity +error StrategyProtocolFeeTooHigh() +``` + +It is returned if the strategy's protocol fee is too high. + +_It can only be returned for owner operations._ + +### TransferAlreadyInProgress + +```solidity +error TransferAlreadyInProgress() +``` + +This is returned when the transfer is already in progress but the owner tries initiate a new ownership transfer. + +### TransferNotInProgress + +```solidity +error TransferNotInProgress() +``` + +This is returned when there is no ownership transfer in progress but the ownership change tries to be approved. + +### WrongPotentialOwner + +```solidity +error WrongPotentialOwner() +``` + +This is returned when the ownership transfer is attempted to be validated by the a caller that is not the potential owner. diff --git a/docs/docs/developer/api/contracts/marketplace/TransferManager.md b/docs/docs/developer/api/contracts/marketplace/TransferManager.md new file mode 100644 index 00000000..6091a918 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/TransferManager.md @@ -0,0 +1,547 @@ +# TransferManager + +_LooksRare protocol team (👀,💎)_ + +> TransferManager + +This contract provides the transfer functions for ERC721/ERC1155/Hypercert/Hyperboard for contracts that require them. Collection type "0" refers to ERC721 transfer functions. Collection type "1" refers to ERC1155 transfer functions. Collection type "2" refers to Hypercert transfer functions. Collection type "3" refers to Hyperboard transfer functions. + +_"Safe" transfer functions for ERC721 are not implemented since they come with added gas costs to verify if the recipient is a contract as it requires verifying the receiver interface is valid._ + +## Methods + +### allowOperator + +```solidity +function allowOperator(address operator) external nonpayable +``` + +This function allows an operator to be added for the shared transfer system. Once the operator is allowed, users can grant NFT approvals to this operator. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ------------------------- | +| operator | address | Operator address to allow | + +### cancelOwnershipTransfer + +```solidity +function cancelOwnershipTransfer() external nonpayable +``` + +This function is used to cancel the ownership transfer. + +_This function can be used for both cancelling a transfer to a new owner and cancelling the renouncement of the ownership._ + +### confirmOwnershipRenouncement + +```solidity +function confirmOwnershipRenouncement() external nonpayable +``` + +This function is used to confirm the ownership renouncement. + +### confirmOwnershipTransfer + +```solidity +function confirmOwnershipTransfer() external nonpayable +``` + +This function is used to confirm the ownership transfer. + +_This function can only be called by the current potential owner._ + +### grantApprovals + +```solidity +function grantApprovals(address[] operators) external nonpayable +``` + +This function allows a user to grant approvals for an array of operators. Users cannot grant approvals if the operator is not allowed by this contract's owner. + +_Each operator address must be globally allowed to be approved._ + +#### Parameters + +| Name | Type | Description | +| --------- | --------- | --------------------------- | +| operators | address[] | Array of operator addresses | + +### hasUserApprovedOperator + +```solidity +function hasUserApprovedOperator(address, address) external view returns (bool) +``` + +This returns whether the user has approved the operator address. The first address is the user and the second address is the operator (e.g. LooksRareProtocol). + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | +| \_1 | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### initiateOwnershipRenouncement + +```solidity +function initiateOwnershipRenouncement() external nonpayable +``` + +This function is used to initiate the ownership renouncement. + +### initiateOwnershipTransfer + +```solidity +function initiateOwnershipTransfer(address newPotentialOwner) external nonpayable +``` + +This function is used to initiate the transfer of ownership to a new owner. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | --------------------------- | +| newPotentialOwner | address | New potential owner address | + +### isOperatorAllowed + +```solidity +function isOperatorAllowed(address) external view returns (bool) +``` + +This returns whether the operator address is allowed by this contract's owner. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +Address of the current owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### ownershipStatus + +```solidity +function ownershipStatus() external view returns (enum IOwnableTwoSteps.Status) +``` + +Ownership status. + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------------- | ----------- | +| \_0 | enum IOwnableTwoSteps.Status | undefined | + +### potentialOwner + +```solidity +function potentialOwner() external view returns (address) +``` + +Address of the potential owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### removeOperator + +```solidity +function removeOperator(address operator) external nonpayable +``` + +This function allows the user to remove an operator for the shared transfer system. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | -------------------------- | +| operator | address | Operator address to remove | + +### revokeApprovals + +```solidity +function revokeApprovals(address[] operators) external nonpayable +``` + +This function allows a user to revoke existing approvals for an array of operators. + +_Each operator address must be approved at the user level to be revoked._ + +#### Parameters + +| Name | Type | Description | +| --------- | --------- | --------------------------- | +| operators | address[] | Array of operator addresses | + +### transferBatchItemsAcrossCollections + +```solidity +function transferBatchItemsAcrossCollections(ITransferManager.BatchTransferItem[] items, address from, address to) external nonpayable +``` + +#### Parameters + +| Name | Type | Description | +| ----- | ------------------------------------ | ----------- | +| items | ITransferManager.BatchTransferItem[] | undefined | +| from | address | undefined | +| to | address | undefined | + +### transferItemsERC1155 + +```solidity +function transferItemsERC1155(address collection, address from, address to, uint256[] itemIds, uint256[] amounts) external nonpayable +``` + +This function transfers items for a single ERC1155 collection. + +_It does not allow batch transferring if from = msg.sender since native function should be used._ + +#### Parameters + +| Name | Type | Description | +| ---------- | --------- | ------------------ | +| collection | address | Collection address | +| from | address | Sender address | +| to | address | Recipient address | +| itemIds | uint256[] | Array of itemIds | +| amounts | uint256[] | Array of amounts | + +### transferItemsERC721 + +```solidity +function transferItemsERC721(address collection, address from, address to, uint256[] itemIds, uint256[] amounts) external nonpayable +``` + +This function transfers items for a single ERC721 collection. + +#### Parameters + +| Name | Type | Description | +| ---------- | --------- | ------------------ | +| collection | address | Collection address | +| from | address | Sender address | +| to | address | Recipient address | +| itemIds | uint256[] | Array of itemIds | +| amounts | uint256[] | Array of amounts | + +### transferItemsHyperboard + +```solidity +function transferItemsHyperboard(address collection, address from, address to, uint256[] itemIds, uint256[] amounts) external nonpayable +``` + +This function transfers items for a single Hyperboard. + +_It does not allow batch transferring if from = msg.sender since native function should be used._ + +#### Parameters + +| Name | Type | Description | +| ---------- | --------- | ------------------ | +| collection | address | Collection address | +| from | address | Sender address | +| to | address | Recipient address | +| itemIds | uint256[] | Array of itemIds | +| amounts | uint256[] | Array of amounts | + +### transferItemsHypercert + +```solidity +function transferItemsHypercert(address collection, address from, address to, uint256[] itemIds, uint256[] amounts) external nonpayable +``` + +This function transfers items for a single Hypercert. + +_It does not allow batch transferring if from = msg.sender since native function should be used._ + +#### Parameters + +| Name | Type | Description | +| ---------- | --------- | ------------------ | +| collection | address | Collection address | +| from | address | Sender address | +| to | address | Recipient address | +| itemIds | uint256[] | Array of itemIds | +| amounts | uint256[] | Array of amounts | + +## Events + +### ApprovalsGranted + +```solidity +event ApprovalsGranted(address user, address[] operators) +``` + +It is emitted if operators' approvals to transfer NFTs are granted by a user. + +#### Parameters + +| Name | Type | Description | +| --------- | --------- | ----------- | +| user | address | undefined | +| operators | address[] | undefined | + +### ApprovalsRemoved + +```solidity +event ApprovalsRemoved(address user, address[] operators) +``` + +It is emitted if operators' approvals to transfer NFTs are revoked by a user. + +#### Parameters + +| Name | Type | Description | +| --------- | --------- | ----------- | +| user | address | undefined | +| operators | address[] | undefined | + +### CancelOwnershipTransfer + +```solidity +event CancelOwnershipTransfer() +``` + +This is emitted if the ownership transfer is cancelled. + +### InitiateOwnershipRenouncement + +```solidity +event InitiateOwnershipRenouncement() +``` + +This is emitted if the ownership renouncement is initiated. + +### InitiateOwnershipTransfer + +```solidity +event InitiateOwnershipTransfer(address previousOwner, address potentialOwner) +``` + +This is emitted if the ownership transfer is initiated. + +#### Parameters + +| Name | Type | Description | +| -------------- | ------- | ----------- | +| previousOwner | address | undefined | +| potentialOwner | address | undefined | + +### NewOwner + +```solidity +event NewOwner(address newOwner) +``` + +This is emitted when there is a new owner. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +### OperatorAllowed + +```solidity +event OperatorAllowed(address operator) +``` + +It is emitted if a new operator is added to the global allowlist. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| operator | address | undefined | + +### OperatorRemoved + +```solidity +event OperatorRemoved(address operator) +``` + +It is emitted if an operator is removed from the global allowlist. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| operator | address | undefined | + +## Errors + +### AmountInvalid + +```solidity +error AmountInvalid() +``` + +It is returned if the amount is invalid. For ERC721, any number that is not 1. For ERC1155, if amount is 0. + +### ERC1155SafeBatchTransferFromFail + +```solidity +error ERC1155SafeBatchTransferFromFail() +``` + +It is emitted if the ERC1155 safeBatchTransferFrom fails. + +### ERC1155SafeTransferFromFail + +```solidity +error ERC1155SafeTransferFromFail() +``` + +It is emitted if the ERC1155 safeTransferFrom fails. + +### ERC721TransferFromFail + +```solidity +error ERC721TransferFromFail() +``` + +It is emitted if the ERC721 transferFrom fails. + +### LengthsInvalid + +```solidity +error LengthsInvalid() +``` + +It is returned if there is either a mismatch or an error in the length of the array(s). + +### NoOngoingTransferInProgress + +```solidity +error NoOngoingTransferInProgress() +``` + +This is returned when there is no transfer of ownership in progress. + +### NotAContract + +```solidity +error NotAContract() +``` + +It is emitted if the call recipient is not a contract. + +### NotOwner + +```solidity +error NotOwner() +``` + +This is returned when the caller is not the owner. + +### OperatorAlreadyAllowed + +```solidity +error OperatorAlreadyAllowed() +``` + +It is returned if the transfer caller is already allowed by the owner. + +_This error can only be returned for owner operations._ + +### OperatorAlreadyApprovedByUser + +```solidity +error OperatorAlreadyApprovedByUser() +``` + +It is returned if the operator to approve has already been approved by the user. + +### OperatorNotAllowed + +```solidity +error OperatorNotAllowed() +``` + +It is returned if the operator to approve is not in the global allowlist defined by the owner. + +_This error can be returned if the user tries to grant approval to an operator address not in the allowlist or if the owner tries to remove the operator from the global allowlist._ + +### OperatorNotApprovedByUser + +```solidity +error OperatorNotApprovedByUser() +``` + +It is returned if the operator to revoke has not been previously approved by the user. + +### RenouncementNotInProgress + +```solidity +error RenouncementNotInProgress() +``` + +This is returned when there is no renouncement in progress but the owner tries to validate the ownership renouncement. + +### TransferAlreadyInProgress + +```solidity +error TransferAlreadyInProgress() +``` + +This is returned when the transfer is already in progress but the owner tries initiate a new ownership transfer. + +### TransferCallerInvalid + +```solidity +error TransferCallerInvalid() +``` + +It is returned if the transfer caller is invalid. For a transfer called to be valid, the operator must be in the global allowlist and approved by the 'from' user. + +### TransferNotInProgress + +```solidity +error TransferNotInProgress() +``` + +This is returned when there is no ownership transfer in progress but the ownership change tries to be approved. + +### WrongPotentialOwner + +```solidity +error WrongPotentialOwner() +``` + +This is returned when the ownership transfer is attempted to be validated by the a caller that is not the potential owner. diff --git a/docs/docs/developer/api/contracts/marketplace/TransferSelectorNFT.md b/docs/docs/developer/api/contracts/marketplace/TransferSelectorNFT.md new file mode 100644 index 00000000..2e428566 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/TransferSelectorNFT.md @@ -0,0 +1,779 @@ +# TransferSelectorNFT + +_LooksRare protocol team (👀,💎)_ + +> TransferSelectorNFT + +This contract handles the logic for transferring non-fungible items. + +## Methods + +### MAGIC_VALUE_ORDER_NONCE_EXECUTED + +```solidity +function MAGIC_VALUE_ORDER_NONCE_EXECUTED() external view returns (bytes32) +``` + +Magic value nonce returned if executed (or cancelled). + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### addStrategy + +```solidity +function addStrategy(uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) external nonpayable +``` + +This function allows the owner to add a new execution strategy to the protocol. + +_Strategies have an id that is incremental. Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ---------------------------------------------- | +| standardProtocolFeeBp | uint16 | Standard protocol fee (in basis point) | +| minTotalFeeBp | uint16 | Minimum total fee (in basis point) | +| maxProtocolFeeBp | uint16 | Maximum protocol fee (in basis point) | +| selector | bytes4 | Function selector for the strategy | +| isMakerBid | bool | Whether the function selector is for maker bid | +| implementation | address | Implementation address | + +### cancelOrderNonces + +```solidity +function cancelOrderNonces(uint256[] orderNonces) external nonpayable +``` + +This function allows a user to cancel an array of order nonces. + +_It does not check the status of the nonces to save gas and to prevent revertion if one of the orders is filled in the same block._ + +#### Parameters + +| Name | Type | Description | +| ----------- | --------- | --------------------- | +| orderNonces | uint256[] | Array of order nonces | + +### cancelOwnershipTransfer + +```solidity +function cancelOwnershipTransfer() external nonpayable +``` + +This function is used to cancel the ownership transfer. + +_This function can be used for both cancelling a transfer to a new owner and cancelling the renouncement of the ownership._ + +### cancelSubsetNonces + +```solidity +function cancelSubsetNonces(uint256[] subsetNonces) external nonpayable +``` + +This function allows a user to cancel an array of subset nonces. + +_It does not check the status of the nonces to save gas._ + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | ---------------------- | +| subsetNonces | uint256[] | Array of subset nonces | + +### confirmOwnershipRenouncement + +```solidity +function confirmOwnershipRenouncement() external nonpayable +``` + +This function is used to confirm the ownership renouncement. + +### confirmOwnershipTransfer + +```solidity +function confirmOwnershipTransfer() external nonpayable +``` + +This function is used to confirm the ownership transfer. + +_This function can only be called by the current potential owner._ + +### creatorFeeManager + +```solidity +function creatorFeeManager() external view returns (contract ICreatorFeeManager) +``` + +Creator fee manager. + +#### Returns + +| Name | Type | Description | +| ---- | --------------------------- | ----------- | +| \_0 | contract ICreatorFeeManager | undefined | + +### incrementBidAskNonces + +```solidity +function incrementBidAskNonces(bool bid, bool ask) external nonpayable +``` + +This function increments a user's bid/ask nonces. + +_The logic for computing the quasi-random number is inspired by Seaport v1.2. The pseudo-randomness allows non-deterministic computation of the next ask/bid nonce. A deterministic increment would make the cancel-all process non-effective in certain cases (orders signed with a greater ask/bid nonce). The same quasi-random number is used for incrementing both the bid and ask nonces if both values are incremented in the same transaction. If this function is used twice in the same block, it will return the same quasiRandomNumber but this will not impact the overall business logic._ + +#### Parameters + +| Name | Type | Description | +| ---- | ---- | --------------------------------------- | +| bid | bool | Whether to increment the user bid nonce | +| ask | bool | Whether to increment the user ask nonce | + +### initiateOwnershipRenouncement + +```solidity +function initiateOwnershipRenouncement() external nonpayable +``` + +This function is used to initiate the ownership renouncement. + +### initiateOwnershipTransfer + +```solidity +function initiateOwnershipTransfer(address newPotentialOwner) external nonpayable +``` + +This function is used to initiate the transfer of ownership to a new owner. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | --------------------------- | +| newPotentialOwner | address | New potential owner address | + +### isCurrencyAllowed + +```solidity +function isCurrencyAllowed(address) external view returns (bool) +``` + +It checks whether the currency is allowed for transacting. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### maxCreatorFeeBp + +```solidity +function maxCreatorFeeBp() external view returns (uint16) +``` + +Maximum creator fee (in basis point). + +#### Returns + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | uint16 | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +Address of the current owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### ownershipStatus + +```solidity +function ownershipStatus() external view returns (enum IOwnableTwoSteps.Status) +``` + +Ownership status. + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------------- | ----------- | +| \_0 | enum IOwnableTwoSteps.Status | undefined | + +### potentialOwner + +```solidity +function potentialOwner() external view returns (address) +``` + +Address of the potential owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### protocolFeeRecipient + +```solidity +function protocolFeeRecipient() external view returns (address) +``` + +Protocol fee recipient. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### strategyInfo + +```solidity +function strategyInfo(uint256) external view returns (bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) +``` + +This returns the strategy information for a strategy id. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| isActive | bool | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | +| maxProtocolFeeBp | uint16 | undefined | +| selector | bytes4 | undefined | +| isMakerBid | bool | undefined | +| implementation | address | undefined | + +### transferManager + +```solidity +function transferManager() external view returns (contract TransferManager) +``` + +Transfer manager for ERC721 and ERC1155. + +#### Returns + +| Name | Type | Description | +| ---- | ------------------------ | ----------- | +| \_0 | contract TransferManager | undefined | + +### updateCreatorFeeManager + +```solidity +function updateCreatorFeeManager(address newCreatorFeeManager) external nonpayable +``` + +This function allows the owner to update the creator fee manager address. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| -------------------- | ------- | ---------------------------------- | +| newCreatorFeeManager | address | Address of the creator fee manager | + +### updateCurrencyStatus + +```solidity +function updateCurrencyStatus(address currency, bool isAllowed) external nonpayable +``` + +This function allows the owner to update the status of a currency. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | -------------------------------------------------- | +| currency | address | Currency address (address(0) for ETH) | +| isAllowed | bool | Whether the currency should be allowed for trading | + +### updateMaxCreatorFeeBp + +```solidity +function updateMaxCreatorFeeBp(uint16 newMaxCreatorFeeBp) external nonpayable +``` + +This function allows the owner to update the maximum creator fee (in basis point). + +_The maximum value that can be set is 25%. Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ------------------ | ------ | ---------------------------------------- | +| newMaxCreatorFeeBp | uint16 | New maximum creator fee (in basis point) | + +### updateProtocolFeeRecipient + +```solidity +function updateProtocolFeeRecipient(address newProtocolFeeRecipient) external nonpayable +``` + +This function allows the owner to update the protocol fee recipient. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ----------------------- | ------- | ---------------------------------- | +| newProtocolFeeRecipient | address | New protocol fee recipient address | + +### updateStrategy + +```solidity +function updateStrategy(uint256 strategyId, bool isActive, uint16 newStandardProtocolFee, uint16 newMinTotalFee) external nonpayable +``` + +This function allows the owner to update parameters for an existing execution strategy. + +_Only callable by owner._ + +#### Parameters + +| Name | Type | Description | +| ---------------------- | ------- | ------------------------------------------ | +| strategyId | uint256 | Strategy id | +| isActive | bool | Whether the strategy must be active | +| newStandardProtocolFee | uint16 | New standard protocol fee (in basis point) | +| newMinTotalFee | uint16 | New minimum total fee (in basis point) | + +### userBidAskNonces + +```solidity +function userBidAskNonces(address) external view returns (uint256 bidNonce, uint256 askNonce) +``` + +This tracks the bid and ask nonces for a user address. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +#### Returns + +| Name | Type | Description | +| -------- | ------- | ----------- | +| bidNonce | uint256 | undefined | +| askNonce | uint256 | undefined | + +### userOrderNonce + +```solidity +function userOrderNonce(address, uint256) external view returns (bytes32) +``` + +This checks whether the order nonce for a user was executed or cancelled. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | +| \_1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### userSubsetNonce + +```solidity +function userSubsetNonce(address, uint256) external view returns (bool) +``` + +This checks whether the subset nonce for a user was cancelled. + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | +| \_1 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +## Events + +### CancelOwnershipTransfer + +```solidity +event CancelOwnershipTransfer() +``` + +This is emitted if the ownership transfer is cancelled. + +### CurrencyStatusUpdated + +```solidity +event CurrencyStatusUpdated(address currency, bool isAllowed) +``` + +It is emitted if the currency status in the allowlist is updated. + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | ----------- | +| currency | address | undefined | +| isAllowed | bool | undefined | + +### InitiateOwnershipRenouncement + +```solidity +event InitiateOwnershipRenouncement() +``` + +This is emitted if the ownership renouncement is initiated. + +### InitiateOwnershipTransfer + +```solidity +event InitiateOwnershipTransfer(address previousOwner, address potentialOwner) +``` + +This is emitted if the ownership transfer is initiated. + +#### Parameters + +| Name | Type | Description | +| -------------- | ------- | ----------- | +| previousOwner | address | undefined | +| potentialOwner | address | undefined | + +### NewBidAskNonces + +```solidity +event NewBidAskNonces(address user, uint256 bidNonce, uint256 askNonce) +``` + +It is emitted when there is an update of the global bid/ask nonces for a user. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| user | address | undefined | +| bidNonce | uint256 | undefined | +| askNonce | uint256 | undefined | + +### NewCreatorFeeManager + +```solidity +event NewCreatorFeeManager(address creatorFeeManager) +``` + +It is issued when there is a new creator fee manager. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| creatorFeeManager | address | undefined | + +### NewMaxCreatorFeeBp + +```solidity +event NewMaxCreatorFeeBp(uint256 maxCreatorFeeBp) +``` + +It is issued when there is a new maximum creator fee (in basis point). + +#### Parameters + +| Name | Type | Description | +| --------------- | ------- | ----------- | +| maxCreatorFeeBp | uint256 | undefined | + +### NewOwner + +```solidity +event NewOwner(address newOwner) +``` + +This is emitted when there is a new owner. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +### NewProtocolFeeRecipient + +```solidity +event NewProtocolFeeRecipient(address protocolFeeRecipient) +``` + +It is issued when there is a new protocol fee recipient address. + +#### Parameters + +| Name | Type | Description | +| -------------------- | ------- | ----------- | +| protocolFeeRecipient | address | undefined | + +### NewStrategy + +```solidity +event NewStrategy(uint256 strategyId, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) +``` + +It is emitted when a new strategy is added. + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| strategyId | uint256 | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | +| maxProtocolFeeBp | uint16 | undefined | +| selector | bytes4 | undefined | +| isMakerBid | bool | undefined | +| implementation | address | undefined | + +### OrderNoncesCancelled + +```solidity +event OrderNoncesCancelled(address user, uint256[] orderNonces) +``` + +It is emitted when order nonces are cancelled for a user. + +#### Parameters + +| Name | Type | Description | +| ----------- | --------- | ----------- | +| user | address | undefined | +| orderNonces | uint256[] | undefined | + +### StrategyUpdated + +```solidity +event StrategyUpdated(uint256 strategyId, bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp) +``` + +It is emitted when an existing strategy is updated. + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ----------- | +| strategyId | uint256 | undefined | +| isActive | bool | undefined | +| standardProtocolFeeBp | uint16 | undefined | +| minTotalFeeBp | uint16 | undefined | + +### SubsetNoncesCancelled + +```solidity +event SubsetNoncesCancelled(address user, uint256[] subsetNonces) +``` + +It is emitted when subset nonces are cancelled for a user. + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | ----------- | +| user | address | undefined | +| subsetNonces | uint256[] | undefined | + +## Errors + +### CreatorFeeBpTooHigh + +```solidity +error CreatorFeeBpTooHigh() +``` + +It is returned if the creator fee (in basis point) is too high. + +### LengthsInvalid + +```solidity +error LengthsInvalid() +``` + +It is returned if there is either a mismatch or an error in the length of the array(s). + +### NewProtocolFeeRecipientCannotBeNullAddress + +```solidity +error NewProtocolFeeRecipientCannotBeNullAddress() +``` + +It is returned if the new protocol fee recipient is set to address(0). + +### NoOngoingTransferInProgress + +```solidity +error NoOngoingTransferInProgress() +``` + +This is returned when there is no transfer of ownership in progress. + +### NoSelectorForStrategy + +```solidity +error NoSelectorForStrategy() +``` + +It is returned if there is no selector for maker ask/bid for a given strategyId, depending on the quote type. + +### NotOwner + +```solidity +error NotOwner() +``` + +This is returned when the caller is not the owner. + +### NotV2Strategy + +```solidity +error NotV2Strategy() +``` + +If the strategy has not set properly its implementation contract. + +_It can only be returned for owner operations._ + +### OutsideOfTimeRange + +```solidity +error OutsideOfTimeRange() +``` + +It is returned if the current block timestamp is not between start and end times in the maker order. + +### ReentrancyFail + +```solidity +error ReentrancyFail() +``` + +This is returned when there is a reentrant call. + +### RenouncementNotInProgress + +```solidity +error RenouncementNotInProgress() +``` + +This is returned when there is no renouncement in progress but the owner tries to validate the ownership renouncement. + +### StrategyHasNoSelector + +```solidity +error StrategyHasNoSelector() +``` + +It is returned if the strategy has no selector. + +_It can only be returned for owner operations._ + +### StrategyNotAvailable + +```solidity +error StrategyNotAvailable(uint256 strategyId) +``` + +It is returned if the strategy id has no implementation. + +_It is returned if there is no implementation address and the strategyId is strictly greater than 0._ + +#### Parameters + +| Name | Type | Description | +| ---------- | ------- | ----------- | +| strategyId | uint256 | undefined | + +### StrategyNotUsed + +```solidity +error StrategyNotUsed() +``` + +It is returned if the strategyId is invalid. + +### StrategyProtocolFeeTooHigh + +```solidity +error StrategyProtocolFeeTooHigh() +``` + +It is returned if the strategy's protocol fee is too high. + +_It can only be returned for owner operations._ + +### TransferAlreadyInProgress + +```solidity +error TransferAlreadyInProgress() +``` + +This is returned when the transfer is already in progress but the owner tries initiate a new ownership transfer. + +### TransferNotInProgress + +```solidity +error TransferNotInProgress() +``` + +This is returned when there is no ownership transfer in progress but the ownership change tries to be approved. + +### UnsupportedCollectionType + +```solidity +error UnsupportedCollectionType() +``` + +### WrongPotentialOwner + +```solidity +error WrongPotentialOwner() +``` + +This is returned when the ownership transfer is attempted to be validated by the a caller that is not the potential owner. diff --git a/docs/docs/developer/api/contracts/marketplace/executionStrategies/BaseStrategy.md b/docs/docs/developer/api/contracts/marketplace/executionStrategies/BaseStrategy.md new file mode 100644 index 00000000..37866658 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/executionStrategies/BaseStrategy.md @@ -0,0 +1,41 @@ +# BaseStrategy + +_LooksRare protocol team (👀,💎)_ + +> BaseStrategy + +## Methods + +### isLooksRareV2Strategy + +```solidity +function isLooksRareV2Strategy() external pure returns (bool) +``` + +This function acts as a safety check for the protocol's owner when adding new execution strategies. + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ---------------------------------------------- | +| \_0 | bool | Whether it is a LooksRare V2 protocol strategy | + +### isMakerOrderValid + +```solidity +function isMakerOrderValid(OrderStructs.Maker makerOrder, bytes4 functionSelector) external view returns (bool isValid, bytes4 errorSelector) +``` + +#### Parameters + +| Name | Type | Description | +| ---------------- | ------------------ | ----------- | +| makerOrder | OrderStructs.Maker | undefined | +| functionSelector | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +| ------------- | ------ | ----------- | +| isValid | bool | undefined | +| errorSelector | bytes4 | undefined | diff --git a/docs/docs/developer/api/contracts/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.md b/docs/docs/developer/api/contracts/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.md new file mode 100644 index 00000000..c9503939 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/executionStrategies/Chainlink/BaseStrategyChainlinkPriceLatency.md @@ -0,0 +1,212 @@ +# BaseStrategyChainlinkPriceLatency + +_LooksRare protocol team (👀,💎)_ + +> BaseStrategyChainlinkPriceLatency + +This contract allows the owner to define the maximum acceptable Chainlink price latency. + +## Methods + +### cancelOwnershipTransfer + +```solidity +function cancelOwnershipTransfer() external nonpayable +``` + +This function is used to cancel the ownership transfer. + +_This function can be used for both cancelling a transfer to a new owner and cancelling the renouncement of the ownership._ + +### confirmOwnershipRenouncement + +```solidity +function confirmOwnershipRenouncement() external nonpayable +``` + +This function is used to confirm the ownership renouncement. + +### confirmOwnershipTransfer + +```solidity +function confirmOwnershipTransfer() external nonpayable +``` + +This function is used to confirm the ownership transfer. + +_This function can only be called by the current potential owner._ + +### initiateOwnershipRenouncement + +```solidity +function initiateOwnershipRenouncement() external nonpayable +``` + +This function is used to initiate the ownership renouncement. + +### initiateOwnershipTransfer + +```solidity +function initiateOwnershipTransfer(address newPotentialOwner) external nonpayable +``` + +This function is used to initiate the transfer of ownership to a new owner. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | --------------------------- | +| newPotentialOwner | address | New potential owner address | + +### maxLatency + +```solidity +function maxLatency() external view returns (uint256) +``` + +Maximum latency accepted after which the execution strategy rejects the retrieved price. For ETH, it cannot be higher than 3,600 as Chainlink will at least update the price every 3,600 seconds, provided ETH's price does not deviate more than 0.5%. For NFTs, it cannot be higher than 86,400 as Chainlink will at least update the price every 86,400 seconds, provided ETH's price does not deviate more than 2%. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +Address of the current owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### ownershipStatus + +```solidity +function ownershipStatus() external view returns (enum IOwnableTwoSteps.Status) +``` + +Ownership status. + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------------- | ----------- | +| \_0 | enum IOwnableTwoSteps.Status | undefined | + +### potentialOwner + +```solidity +function potentialOwner() external view returns (address) +``` + +Address of the potential owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +## Events + +### CancelOwnershipTransfer + +```solidity +event CancelOwnershipTransfer() +``` + +This is emitted if the ownership transfer is cancelled. + +### InitiateOwnershipRenouncement + +```solidity +event InitiateOwnershipRenouncement() +``` + +This is emitted if the ownership renouncement is initiated. + +### InitiateOwnershipTransfer + +```solidity +event InitiateOwnershipTransfer(address previousOwner, address potentialOwner) +``` + +This is emitted if the ownership transfer is initiated. + +#### Parameters + +| Name | Type | Description | +| -------------- | ------- | ----------- | +| previousOwner | address | undefined | +| potentialOwner | address | undefined | + +### NewOwner + +```solidity +event NewOwner(address newOwner) +``` + +This is emitted when there is a new owner. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +## Errors + +### NoOngoingTransferInProgress + +```solidity +error NoOngoingTransferInProgress() +``` + +This is returned when there is no transfer of ownership in progress. + +### NotOwner + +```solidity +error NotOwner() +``` + +This is returned when the caller is not the owner. + +### RenouncementNotInProgress + +```solidity +error RenouncementNotInProgress() +``` + +This is returned when there is no renouncement in progress but the owner tries to validate the ownership renouncement. + +### TransferAlreadyInProgress + +```solidity +error TransferAlreadyInProgress() +``` + +This is returned when the transfer is already in progress but the owner tries initiate a new ownership transfer. + +### TransferNotInProgress + +```solidity +error TransferNotInProgress() +``` + +This is returned when there is no ownership transfer in progress but the ownership change tries to be approved. + +### WrongPotentialOwner + +```solidity +error WrongPotentialOwner() +``` + +This is returned when the ownership transfer is attempted to be validated by the a caller that is not the potential owner. diff --git a/docs/docs/developer/api/contracts/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.md b/docs/docs/developer/api/contracts/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.md new file mode 100644 index 00000000..e2d77dd3 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/executionStrategies/Chainlink/StrategyChainlinkUSDDynamicAsk.md @@ -0,0 +1,342 @@ +# StrategyChainlinkUSDDynamicAsk + +_LooksRare protocol team (👀,💎)_ + +> StrategyChainlinkUSDDynamicAsk + +This contract allows a seller to sell an NFT priced in USD and the receivable amount to be in ETH. + +## Methods + +### ETH_USD_PRICE_FEED_DECIMALS + +```solidity +function ETH_USD_PRICE_FEED_DECIMALS() external view returns (uint256) +``` + +_It is possible to call priceFeed.decimals() to get the decimals, but to save gas, it is hard coded instead._ + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +### WETH + +```solidity +function WETH() external view returns (address) +``` + +Wrapped ether (WETH) address. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### cancelOwnershipTransfer + +```solidity +function cancelOwnershipTransfer() external nonpayable +``` + +This function is used to cancel the ownership transfer. + +_This function can be used for both cancelling a transfer to a new owner and cancelling the renouncement of the ownership._ + +### confirmOwnershipRenouncement + +```solidity +function confirmOwnershipRenouncement() external nonpayable +``` + +This function is used to confirm the ownership renouncement. + +### confirmOwnershipTransfer + +```solidity +function confirmOwnershipTransfer() external nonpayable +``` + +This function is used to confirm the ownership transfer. + +_This function can only be called by the current potential owner._ + +### executeStrategyWithTakerBid + +```solidity +function executeStrategyWithTakerBid(OrderStructs.Taker takerBid, OrderStructs.Maker makerAsk) external view returns (uint256 price, uint256[] itemIds, uint256[] amounts, bool isNonceInvalidated) +``` + +#### Parameters + +| Name | Type | Description | +| -------- | ------------------ | ----------- | +| takerBid | OrderStructs.Taker | undefined | +| makerAsk | OrderStructs.Maker | undefined | + +#### Returns + +| Name | Type | Description | +| ------------------ | --------- | ----------- | +| price | uint256 | undefined | +| itemIds | uint256[] | undefined | +| amounts | uint256[] | undefined | +| isNonceInvalidated | bool | undefined | + +### initiateOwnershipRenouncement + +```solidity +function initiateOwnershipRenouncement() external nonpayable +``` + +This function is used to initiate the ownership renouncement. + +### initiateOwnershipTransfer + +```solidity +function initiateOwnershipTransfer(address newPotentialOwner) external nonpayable +``` + +This function is used to initiate the transfer of ownership to a new owner. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | --------------------------- | +| newPotentialOwner | address | New potential owner address | + +### isLooksRareV2Strategy + +```solidity +function isLooksRareV2Strategy() external pure returns (bool) +``` + +This function acts as a safety check for the protocol's owner when adding new execution strategies. + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ---------------------------------------------- | +| \_0 | bool | Whether it is a LooksRare V2 protocol strategy | + +### isMakerOrderValid + +```solidity +function isMakerOrderValid(OrderStructs.Maker makerAsk, bytes4 functionSelector) external view returns (bool isValid, bytes4 errorSelector) +``` + +#### Parameters + +| Name | Type | Description | +| ---------------- | ------------------ | ----------- | +| makerAsk | OrderStructs.Maker | undefined | +| functionSelector | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +| ------------- | ------ | ----------- | +| isValid | bool | undefined | +| errorSelector | bytes4 | undefined | + +### maxLatency + +```solidity +function maxLatency() external view returns (uint256) +``` + +Maximum latency accepted after which the execution strategy rejects the retrieved price. For ETH, it cannot be higher than 3,600 as Chainlink will at least update the price every 3,600 seconds, provided ETH's price does not deviate more than 0.5%. For NFTs, it cannot be higher than 86,400 as Chainlink will at least update the price every 86,400 seconds, provided ETH's price does not deviate more than 2%. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +Address of the current owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### ownershipStatus + +```solidity +function ownershipStatus() external view returns (enum IOwnableTwoSteps.Status) +``` + +Ownership status. + +#### Returns + +| Name | Type | Description | +| ---- | ---------------------------- | ----------- | +| \_0 | enum IOwnableTwoSteps.Status | undefined | + +### potentialOwner + +```solidity +function potentialOwner() external view returns (address) +``` + +Address of the potential owner. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### priceFeed + +```solidity +function priceFeed() external view returns (contract AggregatorV3Interface) +``` + +ETH/USD Chainlink price feed + +#### Returns + +| Name | Type | Description | +| ---- | ------------------------------ | ----------- | +| \_0 | contract AggregatorV3Interface | undefined | + +## Events + +### CancelOwnershipTransfer + +```solidity +event CancelOwnershipTransfer() +``` + +This is emitted if the ownership transfer is cancelled. + +### InitiateOwnershipRenouncement + +```solidity +event InitiateOwnershipRenouncement() +``` + +This is emitted if the ownership renouncement is initiated. + +### InitiateOwnershipTransfer + +```solidity +event InitiateOwnershipTransfer(address previousOwner, address potentialOwner) +``` + +This is emitted if the ownership transfer is initiated. + +#### Parameters + +| Name | Type | Description | +| -------------- | ------- | ----------- | +| previousOwner | address | undefined | +| potentialOwner | address | undefined | + +### NewOwner + +```solidity +event NewOwner(address newOwner) +``` + +This is emitted when there is a new owner. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +## Errors + +### BidTooLow + +```solidity +error BidTooLow() +``` + +It is returned if the bid price is too low for the ask user. + +### ChainlinkPriceInvalid + +```solidity +error ChainlinkPriceInvalid() +``` + +It is returned if the Chainlink price is invalid (e.g. negative). + +### NoOngoingTransferInProgress + +```solidity +error NoOngoingTransferInProgress() +``` + +This is returned when there is no transfer of ownership in progress. + +### NotOwner + +```solidity +error NotOwner() +``` + +This is returned when the caller is not the owner. + +### OrderInvalid + +```solidity +error OrderInvalid() +``` + +It is returned if the order is permanently invalid. There may be an issue with the order formatting. + +### PriceNotRecentEnough + +```solidity +error PriceNotRecentEnough() +``` + +It is returned if the current block time relative to the latest price's update time is greater than the latency tolerance. + +### RenouncementNotInProgress + +```solidity +error RenouncementNotInProgress() +``` + +This is returned when there is no renouncement in progress but the owner tries to validate the ownership renouncement. + +### TransferAlreadyInProgress + +```solidity +error TransferAlreadyInProgress() +``` + +This is returned when the transfer is already in progress but the owner tries initiate a new ownership transfer. + +### TransferNotInProgress + +```solidity +error TransferNotInProgress() +``` + +This is returned when there is no ownership transfer in progress but the ownership change tries to be approved. + +### WrongPotentialOwner + +```solidity +error WrongPotentialOwner() +``` + +This is returned when the ownership transfer is attempted to be validated by the a caller that is not the potential owner. diff --git a/docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyCollectionOffer.md b/docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyCollectionOffer.md new file mode 100644 index 00000000..600967db --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyCollectionOffer.md @@ -0,0 +1,107 @@ +# StrategyCollectionOffer + +_LooksRare protocol team (👀,💎)_ + +> StrategyCollectionOffer + +This contract offers execution strategies for users to create maker bid offers for items in a collection. There are two available functions: 1. executeCollectionStrategyWithTakerAsk --> it applies to all itemIds in a collection 2. executeCollectionStrategyWithTakerAskWithProof --> it allows adding merkle proof criteria.The bidder can only bid on 1 item id at a time. 1. If ERC721, the amount must be 1. 2. If ERC1155, the amount can be greater than 1. + +_Use cases can include trait-based offers or rarity score offers._ + +## Methods + +### executeCollectionStrategyWithTakerAsk + +```solidity +function executeCollectionStrategyWithTakerAsk(OrderStructs.Taker takerAsk, OrderStructs.Maker makerBid) external pure returns (uint256 price, uint256[] itemIds, uint256[] amounts, bool isNonceInvalidated) +``` + +#### Parameters + +| Name | Type | Description | +| -------- | ------------------ | ----------- | +| takerAsk | OrderStructs.Taker | undefined | +| makerBid | OrderStructs.Maker | undefined | + +#### Returns + +| Name | Type | Description | +| ------------------ | --------- | ----------- | +| price | uint256 | undefined | +| itemIds | uint256[] | undefined | +| amounts | uint256[] | undefined | +| isNonceInvalidated | bool | undefined | + +### executeCollectionStrategyWithTakerAskWithProof + +```solidity +function executeCollectionStrategyWithTakerAskWithProof(OrderStructs.Taker takerAsk, OrderStructs.Maker makerBid) external pure returns (uint256 price, uint256[] itemIds, uint256[] amounts, bool isNonceInvalidated) +``` + +#### Parameters + +| Name | Type | Description | +| -------- | ------------------ | ----------- | +| takerAsk | OrderStructs.Taker | undefined | +| makerBid | OrderStructs.Maker | undefined | + +#### Returns + +| Name | Type | Description | +| ------------------ | --------- | ----------- | +| price | uint256 | undefined | +| itemIds | uint256[] | undefined | +| amounts | uint256[] | undefined | +| isNonceInvalidated | bool | undefined | + +### isLooksRareV2Strategy + +```solidity +function isLooksRareV2Strategy() external pure returns (bool) +``` + +This function acts as a safety check for the protocol's owner when adding new execution strategies. + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ---------------------------------------------- | +| \_0 | bool | Whether it is a LooksRare V2 protocol strategy | + +### isMakerOrderValid + +```solidity +function isMakerOrderValid(OrderStructs.Maker makerBid, bytes4 functionSelector) external pure returns (bool isValid, bytes4 errorSelector) +``` + +#### Parameters + +| Name | Type | Description | +| ---------------- | ------------------ | ----------- | +| makerBid | OrderStructs.Maker | undefined | +| functionSelector | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +| ------------- | ------ | ----------- | +| isValid | bool | undefined | +| errorSelector | bytes4 | undefined | + +## Errors + +### MerkleProofInvalid + +```solidity +error MerkleProofInvalid() +``` + +It is returned if the merkle proof provided is invalid. + +### OrderInvalid + +```solidity +error OrderInvalid() +``` + +It is returned if the order is permanently invalid. There may be an issue with the order formatting. diff --git a/docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyDutchAuction.md b/docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyDutchAuction.md new file mode 100644 index 00000000..1227878d --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyDutchAuction.md @@ -0,0 +1,83 @@ +# StrategyDutchAuction + +_LooksRare protocol team (👀,💎)_ + +> StrategyDutchAuction + +This contract offers a single execution strategy for users to create Dutch auctions. + +## Methods + +### executeStrategyWithTakerBid + +```solidity +function executeStrategyWithTakerBid(OrderStructs.Taker takerBid, OrderStructs.Maker makerAsk) external view returns (uint256 price, uint256[] itemIds, uint256[] amounts, bool isNonceInvalidated) +``` + +#### Parameters + +| Name | Type | Description | +| -------- | ------------------ | ----------- | +| takerBid | OrderStructs.Taker | undefined | +| makerAsk | OrderStructs.Maker | undefined | + +#### Returns + +| Name | Type | Description | +| ------------------ | --------- | ----------- | +| price | uint256 | undefined | +| itemIds | uint256[] | undefined | +| amounts | uint256[] | undefined | +| isNonceInvalidated | bool | undefined | + +### isLooksRareV2Strategy + +```solidity +function isLooksRareV2Strategy() external pure returns (bool) +``` + +This function acts as a safety check for the protocol's owner when adding new execution strategies. + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ---------------------------------------------- | +| \_0 | bool | Whether it is a LooksRare V2 protocol strategy | + +### isMakerOrderValid + +```solidity +function isMakerOrderValid(OrderStructs.Maker makerAsk, bytes4 functionSelector) external pure returns (bool isValid, bytes4 errorSelector) +``` + +#### Parameters + +| Name | Type | Description | +| ---------------- | ------------------ | ----------- | +| makerAsk | OrderStructs.Maker | undefined | +| functionSelector | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +| ------------- | ------ | ----------- | +| isValid | bool | undefined | +| errorSelector | bytes4 | undefined | + +## Errors + +### BidTooLow + +```solidity +error BidTooLow() +``` + +It is returned if the bid price is too low for the ask user. + +### OrderInvalid + +```solidity +error OrderInvalid() +``` + +It is returned if the order is permanently invalid. There may be an issue with the order formatting. diff --git a/docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyItemIdsRange.md b/docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyItemIdsRange.md new file mode 100644 index 00000000..6a1f0cd5 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/executionStrategies/StrategyItemIdsRange.md @@ -0,0 +1,75 @@ +# StrategyItemIdsRange + +_LooksRare protocol team (👀,💎)_ + +> StrategyItemIdsRange + +This contract offers a single execution strategy for users to bid on a specific amount of items in a range bounded by 2 item ids. + +## Methods + +### executeStrategyWithTakerAsk + +```solidity +function executeStrategyWithTakerAsk(OrderStructs.Taker takerAsk, OrderStructs.Maker makerBid) external pure returns (uint256 price, uint256[] itemIds, uint256[] amounts, bool isNonceInvalidated) +``` + +#### Parameters + +| Name | Type | Description | +| -------- | ------------------ | ----------- | +| takerAsk | OrderStructs.Taker | undefined | +| makerBid | OrderStructs.Maker | undefined | + +#### Returns + +| Name | Type | Description | +| ------------------ | --------- | ----------- | +| price | uint256 | undefined | +| itemIds | uint256[] | undefined | +| amounts | uint256[] | undefined | +| isNonceInvalidated | bool | undefined | + +### isLooksRareV2Strategy + +```solidity +function isLooksRareV2Strategy() external pure returns (bool) +``` + +This function acts as a safety check for the protocol's owner when adding new execution strategies. + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ---------------------------------------------- | +| \_0 | bool | Whether it is a LooksRare V2 protocol strategy | + +### isMakerOrderValid + +```solidity +function isMakerOrderValid(OrderStructs.Maker makerBid, bytes4 functionSelector) external pure returns (bool isValid, bytes4 errorSelector) +``` + +#### Parameters + +| Name | Type | Description | +| ---------------- | ------------------ | ----------- | +| makerBid | OrderStructs.Maker | undefined | +| functionSelector | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +| ------------- | ------ | ----------- | +| isValid | bool | undefined | +| errorSelector | bytes4 | undefined | + +## Errors + +### OrderInvalid + +```solidity +error OrderInvalid() +``` + +It is returned if the order is permanently invalid. There may be an issue with the order formatting. diff --git a/docs/docs/developer/api/contracts/marketplace/helpers/OrderValidatorV2A.md b/docs/docs/developer/api/contracts/marketplace/helpers/OrderValidatorV2A.md new file mode 100644 index 00000000..2d6342fd --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/helpers/OrderValidatorV2A.md @@ -0,0 +1,201 @@ +# OrderValidatorV2A + +_LooksRare protocol team (👀,💎)_ + +> OrderValidatorV2A + +This contract is used to check the validity of maker ask/bid orders in the LooksRareProtocol (v2). It performs checks for: 1. Protocol allowlist issues (i.e. currency or strategy not allowed) 2. Maker order-specific issues (e.g., order invalid due to format or other-strategy specific issues) 3. Nonce related issues (e.g., nonce executed or cancelled) 4. Signature related issues and merkle tree parameters 5. Timestamp related issues (e.g., order expired) 6. Asset-related issues for ERC20/ERC721/ERC1155 (approvals and balances) 7. Collection-type suggestions 8. Transfer manager related issues 9. Creator fee related issues (e.g., creator fee too high, ERC2981 bundles) + +_This version does not handle strategies with partial fills._ + +## Methods + +### CRITERIA_GROUPS + +```solidity +function CRITERIA_GROUPS() external view returns (uint256) +``` + +Number of distinct criteria groups checked to evaluate the validity of an order. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +### ERC1155_INTERFACE_ID + +```solidity +function ERC1155_INTERFACE_ID() external view returns (bytes4) +``` + +ERC1155 interfaceId. + +#### Returns + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | bytes4 | undefined | + +### ERC721_INTERFACE_ID_1 + +```solidity +function ERC721_INTERFACE_ID_1() external view returns (bytes4) +``` + +ERC721 potential interfaceId. + +#### Returns + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | bytes4 | undefined | + +### ERC721_INTERFACE_ID_2 + +```solidity +function ERC721_INTERFACE_ID_2() external view returns (bytes4) +``` + +ERC721 potential interfaceId. + +#### Returns + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | bytes4 | undefined | + +### MAGIC_VALUE_ORDER_NONCE_EXECUTED + +```solidity +function MAGIC_VALUE_ORDER_NONCE_EXECUTED() external view returns (bytes32) +``` + +Magic value nonce returned if executed (or cancelled). + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### checkMakerOrderValidity + +```solidity +function checkMakerOrderValidity(OrderStructs.Maker makerOrder, bytes signature, OrderStructs.MerkleTree merkleTree) external view returns (uint256[9] validationCodes) +``` + +#### Parameters + +| Name | Type | Description | +| ---------- | ----------------------- | ----------- | +| makerOrder | OrderStructs.Maker | undefined | +| signature | bytes | undefined | +| merkleTree | OrderStructs.MerkleTree | undefined | + +#### Returns + +| Name | Type | Description | +| --------------- | ---------- | ----------- | +| validationCodes | uint256[9] | undefined | + +### checkMultipleMakerOrderValidities + +```solidity +function checkMultipleMakerOrderValidities(OrderStructs.Maker[] makerOrders, bytes[] signatures, OrderStructs.MerkleTree[] merkleTrees) external view returns (uint256[9][] validationCodes) +``` + +#### Parameters + +| Name | Type | Description | +| ----------- | ------------------------- | ----------- | +| makerOrders | OrderStructs.Maker[] | undefined | +| signatures | bytes[] | undefined | +| merkleTrees | OrderStructs.MerkleTree[] | undefined | + +#### Returns + +| Name | Type | Description | +| --------------- | ------------ | ----------- | +| validationCodes | uint256[9][] | undefined | + +### creatorFeeManager + +```solidity +function creatorFeeManager() external view returns (contract ICreatorFeeManager) +``` + +CreatorFeeManager. + +#### Returns + +| Name | Type | Description | +| ---- | --------------------------- | ----------- | +| \_0 | contract ICreatorFeeManager | undefined | + +### deriveProtocolParameters + +```solidity +function deriveProtocolParameters() external nonpayable +``` + +Derive protocol parameters. Anyone can call this function. + +_It allows adjusting if the domain separator or creator fee manager address were to change._ + +### domainSeparator + +```solidity +function domainSeparator() external view returns (bytes32) +``` + +LooksRareProtocol domain separator. + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### looksRareProtocol + +```solidity +function looksRareProtocol() external view returns (contract LooksRareProtocol) +``` + +LooksRareProtocol. + +#### Returns + +| Name | Type | Description | +| ---- | -------------------------- | ----------- | +| \_0 | contract LooksRareProtocol | undefined | + +### maxCreatorFeeBp + +```solidity +function maxCreatorFeeBp() external view returns (uint256) +``` + +Maximum creator fee (in basis point). + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +### transferManager + +```solidity +function transferManager() external view returns (contract TransferManager) +``` + +TransferManager + +#### Returns + +| Name | Type | Description | +| ---- | ------------------------ | ----------- | +| \_0 | contract TransferManager | undefined | diff --git a/docs/docs/developer/api/contracts/marketplace/helpers/ProtocolHelpers.md b/docs/docs/developer/api/contracts/marketplace/helpers/ProtocolHelpers.md new file mode 100644 index 00000000..91be29a9 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/helpers/ProtocolHelpers.md @@ -0,0 +1,159 @@ +# ProtocolHelpers + +_LooksRare protocol team (👀,💎)_ + +> ProtocolHelpers + +This contract contains helper view functions for order creation. + +## Methods + +### computeDigestMerkleTree + +```solidity +function computeDigestMerkleTree(OrderStructs.MerkleTree merkleTree) external view returns (bytes32 digest) +``` + +#### Parameters + +| Name | Type | Description | +| ---------- | ----------------------- | ----------- | +| merkleTree | OrderStructs.MerkleTree | undefined | + +#### Returns + +| Name | Type | Description | +| ------ | ------- | ----------- | +| digest | bytes32 | undefined | + +### computeMakerDigest + +```solidity +function computeMakerDigest(OrderStructs.Maker maker) external view returns (bytes32 digest) +``` + +#### Parameters + +| Name | Type | Description | +| ----- | ------------------ | ----------- | +| maker | OrderStructs.Maker | undefined | + +#### Returns + +| Name | Type | Description | +| ------ | ------- | ----------- | +| digest | bytes32 | undefined | + +### looksRareProtocol + +```solidity +function looksRareProtocol() external view returns (contract LooksRareProtocol) +``` + +#### Returns + +| Name | Type | Description | +| ---- | -------------------------- | ----------- | +| \_0 | contract LooksRareProtocol | undefined | + +### verifyMakerSignature + +```solidity +function verifyMakerSignature(OrderStructs.Maker maker, bytes makerSignature, address signer) external view returns (bool) +``` + +#### Parameters + +| Name | Type | Description | +| -------------- | ------------------ | ----------- | +| maker | OrderStructs.Maker | undefined | +| makerSignature | bytes | undefined | +| signer | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### verifyMerkleTree + +```solidity +function verifyMerkleTree(OrderStructs.MerkleTree merkleTree, bytes makerSignature, address signer) external view returns (bool) +``` + +#### Parameters + +| Name | Type | Description | +| -------------- | ----------------------- | ----------- | +| merkleTree | OrderStructs.MerkleTree | undefined | +| makerSignature | bytes | undefined | +| signer | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +## Errors + +### NullSignerAddress + +```solidity +error NullSignerAddress() +``` + +It is emitted if the signer is null. + +### SignatureEOAInvalid + +```solidity +error SignatureEOAInvalid() +``` + +It is emitted if the signature is invalid for an EOA (the address recovered is not the expected one). + +### SignatureERC1271Invalid + +```solidity +error SignatureERC1271Invalid() +``` + +It is emitted if the signature is invalid for a ERC1271 contract signer. + +### SignatureLengthInvalid + +```solidity +error SignatureLengthInvalid(uint256 length) +``` + +It is emitted if the signature's length is neither 64 nor 65 bytes. + +#### Parameters + +| Name | Type | Description | +| ------ | ------- | ----------- | +| length | uint256 | undefined | + +### SignatureParameterSInvalid + +```solidity +error SignatureParameterSInvalid() +``` + +It is emitted if the signature is invalid due to S parameter. + +### SignatureParameterVInvalid + +```solidity +error SignatureParameterVInvalid(uint8 v) +``` + +It is emitted if the signature is invalid due to V parameter. + +#### Parameters + +| Name | Type | Description | +| ---- | ----- | ----------- | +| v | uint8 | undefined | diff --git a/docs/docs/developer/api/contracts/marketplace/interfaces/ICreatorFeeManager.md b/docs/docs/developer/api/contracts/marketplace/interfaces/ICreatorFeeManager.md new file mode 100644 index 00000000..b832744e --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/interfaces/ICreatorFeeManager.md @@ -0,0 +1,60 @@ +# ICreatorFeeManager + +_LooksRare protocol team (👀,💎)_ + +> ICreatorFeeManager + +## Methods + +### royaltyFeeRegistry + +```solidity +function royaltyFeeRegistry() external view returns (contract IRoyaltyFeeRegistry royaltyFeeRegistry) +``` + +It returns the royalty fee registry address/interface. + +#### Returns + +| Name | Type | Description | +| ------------------ | ---------------------------- | ------------------------------------- | +| royaltyFeeRegistry | contract IRoyaltyFeeRegistry | Interface of the royalty fee registry | + +### viewCreatorFeeInfo + +```solidity +function viewCreatorFeeInfo(address collection, uint256 price, uint256[] itemIds) external view returns (address creator, uint256 creatorFeeAmount) +``` + +This function returns the creator address and calculates the creator fee amount. + +#### Parameters + +| Name | Type | Description | +| ---------- | --------- | ------------------ | +| collection | address | Collection address | +| price | uint256 | Transaction price | +| itemIds | uint256[] | Array of item ids | + +#### Returns + +| Name | Type | Description | +| ---------------- | ------- | ------------------ | +| creator | address | Creator address | +| creatorFeeAmount | uint256 | Creator fee amount | + +## Errors + +### BundleEIP2981NotAllowed + +```solidity +error BundleEIP2981NotAllowed(address collection) +``` + +It is returned if the bundle contains multiple itemIds with different creator fee structure. + +#### Parameters + +| Name | Type | Description | +| ---------- | ------- | ----------- | +| collection | address | undefined | diff --git a/docs/docs/developer/api/contracts/marketplace/interfaces/ICurrencyManager.md b/docs/docs/developer/api/contracts/marketplace/interfaces/ICurrencyManager.md new file mode 100644 index 00000000..da683d8c --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/interfaces/ICurrencyManager.md @@ -0,0 +1,22 @@ +# ICurrencyManager + +_LooksRare protocol team (👀,💎)_ + +> ICurrencyManager + +## Events + +### CurrencyStatusUpdated + +```solidity +event CurrencyStatusUpdated(address currency, bool isAllowed) +``` + +It is emitted if the currency status in the allowlist is updated. + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | ----------------------------------- | +| currency | address | Currency address (address(0) = ETH) | +| isAllowed | bool | Whether the currency is allowed | diff --git a/docs/docs/developer/api/contracts/marketplace/interfaces/IExecutionManager.md b/docs/docs/developer/api/contracts/marketplace/interfaces/IExecutionManager.md new file mode 100644 index 00000000..0e86c75b --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/interfaces/IExecutionManager.md @@ -0,0 +1,99 @@ +# IExecutionManager + +_LooksRare protocol team (👀,💎)_ + +> IExecutionManager + +## Events + +### NewCreatorFeeManager + +```solidity +event NewCreatorFeeManager(address creatorFeeManager) +``` + +It is issued when there is a new creator fee manager. + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | -------------------------------------- | +| creatorFeeManager | address | Address of the new creator fee manager | + +### NewMaxCreatorFeeBp + +```solidity +event NewMaxCreatorFeeBp(uint256 maxCreatorFeeBp) +``` + +It is issued when there is a new maximum creator fee (in basis point). + +#### Parameters + +| Name | Type | Description | +| --------------- | ------- | ---------------------------------------- | +| maxCreatorFeeBp | uint256 | New maximum creator fee (in basis point) | + +### NewProtocolFeeRecipient + +```solidity +event NewProtocolFeeRecipient(address protocolFeeRecipient) +``` + +It is issued when there is a new protocol fee recipient address. + +#### Parameters + +| Name | Type | Description | +| -------------------- | ------- | ----------------------------------------- | +| protocolFeeRecipient | address | Address of the new protocol fee recipient | + +## Errors + +### CreatorFeeBpTooHigh + +```solidity +error CreatorFeeBpTooHigh() +``` + +It is returned if the creator fee (in basis point) is too high. + +### NewProtocolFeeRecipientCannotBeNullAddress + +```solidity +error NewProtocolFeeRecipientCannotBeNullAddress() +``` + +It is returned if the new protocol fee recipient is set to address(0). + +### NoSelectorForStrategy + +```solidity +error NoSelectorForStrategy() +``` + +It is returned if there is no selector for maker ask/bid for a given strategyId, depending on the quote type. + +### OutsideOfTimeRange + +```solidity +error OutsideOfTimeRange() +``` + +It is returned if the current block timestamp is not between start and end times in the maker order. + +### StrategyNotAvailable + +```solidity +error StrategyNotAvailable(uint256 strategyId) +``` + +It is returned if the strategy id has no implementation. + +_It is returned if there is no implementation address and the strategyId is strictly greater than 0._ + +#### Parameters + +| Name | Type | Description | +| ---------- | ------- | ----------- | +| strategyId | uint256 | undefined | diff --git a/docs/docs/developer/api/contracts/marketplace/interfaces/IImmutableCreate2Factory.md b/docs/docs/developer/api/contracts/marketplace/interfaces/IImmutableCreate2Factory.md new file mode 100644 index 00000000..86e79020 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/interfaces/IImmutableCreate2Factory.md @@ -0,0 +1,22 @@ +# IImmutableCreate2Factory + +## Methods + +### safeCreate2 + +```solidity +function safeCreate2(bytes32 salt, bytes initializationCode) external payable returns (address deploymentAddress) +``` + +#### Parameters + +| Name | Type | Description | +| ------------------ | ------- | ----------- | +| salt | bytes32 | undefined | +| initializationCode | bytes | undefined | + +#### Returns + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| deploymentAddress | address | undefined | diff --git a/docs/docs/developer/api/contracts/marketplace/interfaces/ILooksRareProtocol.md b/docs/docs/developer/api/contracts/marketplace/interfaces/ILooksRareProtocol.md new file mode 100644 index 00000000..e7414f54 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/interfaces/ILooksRareProtocol.md @@ -0,0 +1,157 @@ +# ILooksRareProtocol + +_LooksRare protocol team (👀,💎)_ + +> ILooksRareProtocol + +## Methods + +### executeMultipleTakerBids + +```solidity +function executeMultipleTakerBids(OrderStructs.Taker[] takerBids, OrderStructs.Maker[] makerAsks, bytes[] makerSignatures, OrderStructs.MerkleTree[] merkleTrees, bool isAtomic) external payable +``` + +#### Parameters + +| Name | Type | Description | +| --------------- | ------------------------- | ----------- | +| takerBids | OrderStructs.Taker[] | undefined | +| makerAsks | OrderStructs.Maker[] | undefined | +| makerSignatures | bytes[] | undefined | +| merkleTrees | OrderStructs.MerkleTree[] | undefined | +| isAtomic | bool | undefined | + +### executeTakerAsk + +```solidity +function executeTakerAsk(OrderStructs.Taker takerAsk, OrderStructs.Maker makerBid, bytes makerSignature, OrderStructs.MerkleTree merkleTree) external nonpayable +``` + +#### Parameters + +| Name | Type | Description | +| -------------- | ----------------------- | ----------- | +| takerAsk | OrderStructs.Taker | undefined | +| makerBid | OrderStructs.Maker | undefined | +| makerSignature | bytes | undefined | +| merkleTree | OrderStructs.MerkleTree | undefined | + +### executeTakerBid + +```solidity +function executeTakerBid(OrderStructs.Taker takerBid, OrderStructs.Maker makerAsk, bytes makerSignature, OrderStructs.MerkleTree merkleTree) external payable +``` + +#### Parameters + +| Name | Type | Description | +| -------------- | ----------------------- | ----------- | +| takerBid | OrderStructs.Taker | undefined | +| makerAsk | OrderStructs.Maker | undefined | +| makerSignature | bytes | undefined | +| merkleTree | OrderStructs.MerkleTree | undefined | + +## Events + +### NewDomainSeparator + +```solidity +event NewDomainSeparator() +``` + +It is emitted if there is a change in the domain separator. + +### NewGasLimitETHTransfer + +```solidity +event NewGasLimitETHTransfer(uint256 gasLimitETHTransfer) +``` + +It is emitted when there is a new gas limit for a ETH transfer (before it is wrapped to WETH). + +#### Parameters + +| Name | Type | Description | +| ------------------- | ------- | ----------------------------- | +| gasLimitETHTransfer | uint256 | Gas limit for an ETH transfer | + +### TakerAsk + +```solidity +event TakerAsk(ILooksRareProtocol.NonceInvalidationParameters nonceInvalidationParameters, address askUser, address bidUser, uint256 strategyId, address currency, address collection, uint256[] itemIds, uint256[] amounts, address[2] feeRecipients, uint256[3] feeAmounts) +``` + +It is emitted when a taker ask transaction is completed. + +#### Parameters + +| Name | Type | Description | +| --------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| nonceInvalidationParameters | ILooksRareProtocol.NonceInvalidationParameters | Struct about nonce invalidation parameters | +| askUser | address | Address of the ask user | +| bidUser | address | Address of the bid user | +| strategyId | uint256 | Id of the strategy | +| currency | address | Address of the currency | +| collection | address | Address of the collection | +| itemIds | uint256[] | Array of item ids | +| amounts | uint256[] | Array of amounts (for item ids) | +| feeRecipients | address[2] | Array of fee recipients feeRecipients[0] User who receives the proceeds of the sale (it can be the taker ask user or different) feeRecipients[1] Creator fee recipient (if none, address(0)) | +| feeAmounts | uint256[3] | Array of fee amounts feeAmounts[0] Fee amount for the user receiving sale proceeds feeAmounts[1] Creator fee amount feeAmounts[2] Protocol fee amount prior to adjustment for a potential affiliate payment | + +### TakerBid + +```solidity +event TakerBid(ILooksRareProtocol.NonceInvalidationParameters nonceInvalidationParameters, address bidUser, address bidRecipient, uint256 strategyId, address currency, address collection, uint256[] itemIds, uint256[] amounts, address[2] feeRecipients, uint256[3] feeAmounts) +``` + +It is emitted when a taker bid transaction is completed. + +#### Parameters + +| Name | Type | Description | +| --------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| nonceInvalidationParameters | ILooksRareProtocol.NonceInvalidationParameters | Struct about nonce invalidation parameters | +| bidUser | address | Address of the bid user | +| bidRecipient | address | Address of the recipient of the bid | +| strategyId | uint256 | Id of the strategy | +| currency | address | Address of the currency | +| collection | address | Address of the collection | +| itemIds | uint256[] | Array of item ids | +| amounts | uint256[] | Array of amounts (for item ids) | +| feeRecipients | address[2] | Array of fee recipients feeRecipients[0] User who receives the proceeds of the sale (it is the maker ask user) feeRecipients[1] Creator fee recipient (if none, address(0)) | +| feeAmounts | uint256[3] | Array of fee amounts feeAmounts[0] Fee amount for the user receiving sale proceeds feeAmounts[1] Creator fee amount feeAmounts[2] Protocol fee amount prior to adjustment for a potential affiliate payment | + +## Errors + +### ChainIdInvalid + +```solidity +error ChainIdInvalid() +``` + +It is returned if the domain separator should change. + +### NewGasLimitETHTransferTooLow + +```solidity +error NewGasLimitETHTransferTooLow() +``` + +It is returned if the gas limit for a standard ETH transfer is too low. + +### NoncesInvalid + +```solidity +error NoncesInvalid() +``` + +It is returned if the nonces are invalid. + +### SameDomainSeparator + +```solidity +error SameDomainSeparator() +``` + +It is returned if the domain separator cannot be updated (i.e. the chainId is the same). diff --git a/docs/docs/developer/api/contracts/marketplace/interfaces/INonceManager.md b/docs/docs/developer/api/contracts/marketplace/interfaces/INonceManager.md new file mode 100644 index 00000000..eaa3f977 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/interfaces/INonceManager.md @@ -0,0 +1,53 @@ +# INonceManager + +_LooksRare protocol team (👀,💎)_ + +> INonceManager + +## Events + +### NewBidAskNonces + +```solidity +event NewBidAskNonces(address user, uint256 bidNonce, uint256 askNonce) +``` + +It is emitted when there is an update of the global bid/ask nonces for a user. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ------------------- | +| user | address | Address of the user | +| bidNonce | uint256 | New bid nonce | +| askNonce | uint256 | New ask nonce | + +### OrderNoncesCancelled + +```solidity +event OrderNoncesCancelled(address user, uint256[] orderNonces) +``` + +It is emitted when order nonces are cancelled for a user. + +#### Parameters + +| Name | Type | Description | +| ----------- | --------- | ------------------------------- | +| user | address | Address of the user | +| orderNonces | uint256[] | Array of order nonces cancelled | + +### SubsetNoncesCancelled + +```solidity +event SubsetNoncesCancelled(address user, uint256[] subsetNonces) +``` + +It is emitted when subset nonces are cancelled for a user. + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | -------------------------------- | +| user | address | Address of the user | +| subsetNonces | uint256[] | Array of subset nonces cancelled | diff --git a/docs/docs/developer/api/contracts/marketplace/interfaces/IRoyaltyFeeRegistry.md b/docs/docs/developer/api/contracts/marketplace/interfaces/IRoyaltyFeeRegistry.md new file mode 100644 index 00000000..5ed0ef6c --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/interfaces/IRoyaltyFeeRegistry.md @@ -0,0 +1,29 @@ +# IRoyaltyFeeRegistry + +_LooksRare protocol team (👀,💎)_ + +> IRoyaltyFeeRegistry + +## Methods + +### royaltyInfo + +```solidity +function royaltyInfo(address collection, uint256 price) external view returns (address receiver, uint256 royaltyFee) +``` + +This function returns the royalty information for a collection at a given transaction price. + +#### Parameters + +| Name | Type | Description | +| ---------- | ------- | ------------------ | +| collection | address | Collection address | +| price | uint256 | Transaction price | + +#### Returns + +| Name | Type | Description | +| ---------- | ------- | ------------------ | +| receiver | address | Receiver address | +| royaltyFee | uint256 | Royalty fee amount | diff --git a/docs/docs/developer/api/contracts/marketplace/interfaces/IStrategy.md b/docs/docs/developer/api/contracts/marketplace/interfaces/IStrategy.md new file mode 100644 index 00000000..2b4a45bc --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/interfaces/IStrategy.md @@ -0,0 +1,41 @@ +# IStrategy + +_LooksRare protocol team (👀,💎)_ + +> IStrategy + +## Methods + +### isLooksRareV2Strategy + +```solidity +function isLooksRareV2Strategy() external pure returns (bool isStrategy) +``` + +This function acts as a safety check for the protocol's owner when adding new execution strategies. + +#### Returns + +| Name | Type | Description | +| ---------- | ---- | ---------------------------------------------- | +| isStrategy | bool | Whether it is a LooksRare V2 protocol strategy | + +### isMakerOrderValid + +```solidity +function isMakerOrderValid(OrderStructs.Maker makerOrder, bytes4 functionSelector) external view returns (bool isValid, bytes4 errorSelector) +``` + +#### Parameters + +| Name | Type | Description | +| ---------------- | ------------------ | ----------- | +| makerOrder | OrderStructs.Maker | undefined | +| functionSelector | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +| ------------- | ------ | ----------- | +| isValid | bool | undefined | +| errorSelector | bytes4 | undefined | diff --git a/docs/docs/developer/api/contracts/marketplace/interfaces/IStrategyManager.md b/docs/docs/developer/api/contracts/marketplace/interfaces/IStrategyManager.md new file mode 100644 index 00000000..ae6ea7b1 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/interfaces/IStrategyManager.md @@ -0,0 +1,84 @@ +# IStrategyManager + +_LooksRare protocol team (👀,💎)_ + +> IStrategyManager + +## Events + +### NewStrategy + +```solidity +event NewStrategy(uint256 strategyId, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp, uint16 maxProtocolFeeBp, bytes4 selector, bool isMakerBid, address implementation) +``` + +It is emitted when a new strategy is added. + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | ---------------------------------------------------- | +| strategyId | uint256 | Id of the new strategy | +| standardProtocolFeeBp | uint16 | Standard protocol fee (in basis point) | +| minTotalFeeBp | uint16 | Minimum total fee (in basis point) | +| maxProtocolFeeBp | uint16 | Maximum protocol fee (in basis point) | +| selector | bytes4 | Function selector for the transaction to be executed | +| isMakerBid | bool | Whether the strategyId is for maker bid | +| implementation | address | Address of the implementation of the strategy | + +### StrategyUpdated + +```solidity +event StrategyUpdated(uint256 strategyId, bool isActive, uint16 standardProtocolFeeBp, uint16 minTotalFeeBp) +``` + +It is emitted when an existing strategy is updated. + +#### Parameters + +| Name | Type | Description | +| --------------------- | ------- | -------------------------------------------------------- | +| strategyId | uint256 | Id of the strategy | +| isActive | bool | Whether the strategy is active (or not) after the update | +| standardProtocolFeeBp | uint16 | Standard protocol fee (in basis point) | +| minTotalFeeBp | uint16 | Minimum total fee (in basis point) | + +## Errors + +### NotV2Strategy + +```solidity +error NotV2Strategy() +``` + +If the strategy has not set properly its implementation contract. + +_It can only be returned for owner operations._ + +### StrategyHasNoSelector + +```solidity +error StrategyHasNoSelector() +``` + +It is returned if the strategy has no selector. + +_It can only be returned for owner operations._ + +### StrategyNotUsed + +```solidity +error StrategyNotUsed() +``` + +It is returned if the strategyId is invalid. + +### StrategyProtocolFeeTooHigh + +```solidity +error StrategyProtocolFeeTooHigh() +``` + +It is returned if the strategy's protocol fee is too high. + +_It can only be returned for owner operations._ diff --git a/docs/docs/developer/api/contracts/marketplace/interfaces/ITransferManager.md b/docs/docs/developer/api/contracts/marketplace/interfaces/ITransferManager.md new file mode 100644 index 00000000..3ba8ca81 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/interfaces/ITransferManager.md @@ -0,0 +1,111 @@ +# ITransferManager + +_LooksRare protocol team (👀,💎)_ + +> ITransferManager + +## Events + +### ApprovalsGranted + +```solidity +event ApprovalsGranted(address user, address[] operators) +``` + +It is emitted if operators' approvals to transfer NFTs are granted by a user. + +#### Parameters + +| Name | Type | Description | +| --------- | --------- | --------------------------- | +| user | address | Address of the user | +| operators | address[] | Array of operator addresses | + +### ApprovalsRemoved + +```solidity +event ApprovalsRemoved(address user, address[] operators) +``` + +It is emitted if operators' approvals to transfer NFTs are revoked by a user. + +#### Parameters + +| Name | Type | Description | +| --------- | --------- | --------------------------- | +| user | address | Address of the user | +| operators | address[] | Array of operator addresses | + +### OperatorAllowed + +```solidity +event OperatorAllowed(address operator) +``` + +It is emitted if a new operator is added to the global allowlist. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ---------------- | +| operator | address | Operator address | + +### OperatorRemoved + +```solidity +event OperatorRemoved(address operator) +``` + +It is emitted if an operator is removed from the global allowlist. + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ---------------- | +| operator | address | Operator address | + +## Errors + +### OperatorAlreadyAllowed + +```solidity +error OperatorAlreadyAllowed() +``` + +It is returned if the transfer caller is already allowed by the owner. + +_This error can only be returned for owner operations._ + +### OperatorAlreadyApprovedByUser + +```solidity +error OperatorAlreadyApprovedByUser() +``` + +It is returned if the operator to approve has already been approved by the user. + +### OperatorNotAllowed + +```solidity +error OperatorNotAllowed() +``` + +It is returned if the operator to approve is not in the global allowlist defined by the owner. + +_This error can be returned if the user tries to grant approval to an operator address not in the allowlist or if the owner tries to remove the operator from the global allowlist._ + +### OperatorNotApprovedByUser + +```solidity +error OperatorNotApprovedByUser() +``` + +It is returned if the operator to revoke has not been previously approved by the user. + +### TransferCallerInvalid + +```solidity +error TransferCallerInvalid() +``` + +It is returned if the transfer caller is invalid. For a transfer called to be valid, the operator must be in the global allowlist and approved by the 'from' user. diff --git a/docs/docs/developer/api/contracts/marketplace/libraries/CurrencyValidator.md b/docs/docs/developer/api/contracts/marketplace/libraries/CurrencyValidator.md new file mode 100644 index 00000000..1b1f41a2 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/libraries/CurrencyValidator.md @@ -0,0 +1,7 @@ +# CurrencyValidator + +_LooksRare protocol team (👀,💎)_ + +> CurrencyValidator + +This library validates the order currency to be the chain's native currency or the specified ERC20 token. diff --git a/docs/docs/developer/api/contracts/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.md b/docs/docs/developer/api/contracts/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.md new file mode 100644 index 00000000..943a54cd --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/libraries/OpenZeppelin/MerkleProofCalldataWithNodes.md @@ -0,0 +1,7 @@ +# MerkleProofCalldataWithNodes + +_OpenZeppelin (adjusted by LooksRare)_ + +> MerkleProofCalldataWithNodes + +This library is adjusted from the work of OpenZeppelin. It is based on the 4.7.0 (utils/cryptography/MerkleProof.sol). diff --git a/docs/docs/developer/api/contracts/marketplace/libraries/OpenZeppelin/MerkleProofMemory.md b/docs/docs/developer/api/contracts/marketplace/libraries/OpenZeppelin/MerkleProofMemory.md new file mode 100644 index 00000000..37529181 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/libraries/OpenZeppelin/MerkleProofMemory.md @@ -0,0 +1,7 @@ +# MerkleProofMemory + +_OpenZeppelin (adjusted by LooksRare)_ + +> MerkleProofMemory + +This library is adjusted from the work of OpenZeppelin. It is based on the 4.7.0 (utils/cryptography/MerkleProof.sol). diff --git a/docs/docs/developer/api/contracts/marketplace/libraries/OrderStructs.md b/docs/docs/developer/api/contracts/marketplace/libraries/OrderStructs.md new file mode 100644 index 00000000..3c166bb7 --- /dev/null +++ b/docs/docs/developer/api/contracts/marketplace/libraries/OrderStructs.md @@ -0,0 +1,7 @@ +# OrderStructs + +_LooksRare protocol team (👀,💎)_ + +> OrderStructs + +This library contains all order struct types for the LooksRare protocol (v2). diff --git a/docs/docs/developer/api/contracts/protocol/AllowlistMinter.md b/docs/docs/developer/api/contracts/protocol/AllowlistMinter.md new file mode 100644 index 00000000..4684053c --- /dev/null +++ b/docs/docs/developer/api/contracts/protocol/AllowlistMinter.md @@ -0,0 +1,84 @@ +# AllowlistMinter + +_bitbeckers_ + +> Interface for hypercert token interactions + +This interface declares the required functionality for a hypercert tokenThis interface does not specify the underlying token type (e.g. 721 or 1155) + +## Methods + +### hasBeenClaimed + +```solidity +function hasBeenClaimed(uint256, bytes32) external view returns (bool) +``` + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | +| \_1 | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### isAllowedToClaim + +```solidity +function isAllowedToClaim(bytes32[] proof, uint256 claimID, bytes32 leaf) external view returns (bool isAllowed) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | --------- | ----------- | +| proof | bytes32[] | undefined | +| claimID | uint256 | undefined | +| leaf | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +| --------- | ---- | ----------- | +| isAllowed | bool | undefined | + +## Events + +### AllowlistCreated + +```solidity +event AllowlistCreated(uint256 tokenID, bytes32 root) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| tokenID | uint256 | undefined | +| root | bytes32 | undefined | + +### LeafClaimed + +```solidity +event LeafClaimed(uint256 tokenID, bytes32 leaf) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| tokenID | uint256 | undefined | +| leaf | bytes32 | undefined | + +## Errors + +### DoesNotExist + +```solidity +error DoesNotExist() +``` diff --git a/docs/docs/developer/api/contracts/protocol/HypercertMinter.md b/docs/docs/developer/api/contracts/protocol/HypercertMinter.md new file mode 100644 index 00000000..518efa42 --- /dev/null +++ b/docs/docs/developer/api/contracts/protocol/HypercertMinter.md @@ -0,0 +1,895 @@ +# HypercertMinter + +_bitbeckers_ + +> Contract for managing hypercert claims and whitelists + +Implementation of the HypercertTokenInterface using { SemiFungible1155 } as underlying token.This contract supports whitelisted minting via { AllowlistMinter }. + +_Wrapper contract to expose and chain functions._ + +## Methods + +### \_\_SemiFungible1155_init + +```solidity +function __SemiFungible1155_init() external nonpayable +``` + +_see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol }_ + +### balanceOf + +```solidity +function balanceOf(address account, uint256 id) external view returns (uint256) +``` + +_See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address._ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | +| id | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +### balanceOfBatch + +```solidity +function balanceOfBatch(address[] accounts, uint256[] ids) external view returns (uint256[]) +``` + +_See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length._ + +#### Parameters + +| Name | Type | Description | +| -------- | --------- | ----------- | +| accounts | address[] | undefined | +| ids | uint256[] | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | --------- | ----------- | +| \_0 | uint256[] | undefined | + +### batchBurnFraction + +```solidity +function batchBurnFraction(address _account, uint256[] _tokenIDs) external nonpayable +``` + +Burn a claimtoken + +_see {IHypercertToken}_ + +#### Parameters + +| Name | Type | Description | +| ---------- | --------- | ----------- | +| \_account | address | undefined | +| \_tokenIDs | uint256[] | undefined | + +### batchMintClaimsFromAllowlists + +```solidity +function batchMintClaimsFromAllowlists(address account, bytes32[][] proofs, uint256[] claimIDs, uint256[] units) external nonpayable +``` + +Mint semi-fungible tokens representing a fraction of the claims in `claimIDs` + +_Calls AllowlistMinter to verify `proofs`.Mints the `amount` of units for the hypercert stored under `claimIDs`_ + +#### Parameters + +| Name | Type | Description | +| -------- | ----------- | ----------- | +| account | address | undefined | +| proofs | bytes32[][] | undefined | +| claimIDs | uint256[] | undefined | +| units | uint256[] | undefined | + +### burn + +```solidity +function burn(address account, uint256 id, uint256) external nonpayable +``` + +Burn a claimtoken; override is needed to update units/values + +_see {ERC1155Burnable}_ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | +| id | uint256 | undefined | +| \_2 | uint256 | undefined | + +### burnBatch + +```solidity +function burnBatch(address account, uint256[] ids, uint256[]) external nonpayable +``` + +Batch burn claimtokens; override is needed to update units/values + +_see {ERC1155Burnable}_ + +#### Parameters + +| Name | Type | Description | +| ------- | --------- | ----------- | +| account | address | undefined | +| ids | uint256[] | undefined | +| \_2 | uint256[] | undefined | + +### burnFraction + +```solidity +function burnFraction(address _account, uint256 _tokenID) external nonpayable +``` + +Burn a claimtoken + +_see {IHypercertToken}_ + +#### Parameters + +| Name | Type | Description | +| --------- | ------- | ----------- | +| \_account | address | undefined | +| \_tokenID | uint256 | undefined | + +### createAllowlist + +```solidity +function createAllowlist(address account, uint256 units, bytes32 merkleRoot, string _uri, enum IHypercertToken.TransferRestrictions restrictions) external nonpayable +``` + +Register a claim and the whitelist for minting token(s) belonging to that claim + +_Calls SemiFungible1155 to store the claim referenced in `uri` with amount of `units`Calls AllowlistMinter to store the `merkleRoot` as proof to authorize claims_ + +#### Parameters + +| Name | Type | Description | +| ------------ | ----------------------------------------- | ----------- | +| account | address | undefined | +| units | uint256 | undefined | +| merkleRoot | bytes32 | undefined | +| \_uri | string | undefined | +| restrictions | enum IHypercertToken.TransferRestrictions | undefined | + +### hasBeenClaimed + +```solidity +function hasBeenClaimed(uint256, bytes32) external view returns (bool) +``` + +#### Parameters + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | +| \_1 | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### initialize + +```solidity +function initialize() external nonpayable +``` + +_see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol }_ + +### isAllowedToClaim + +```solidity +function isAllowedToClaim(bytes32[] proof, uint256 claimID, bytes32 leaf) external view returns (bool isAllowed) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | --------- | ----------- | +| proof | bytes32[] | undefined | +| claimID | uint256 | undefined | +| leaf | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +| --------- | ---- | ----------- | +| isAllowed | bool | undefined | + +### isApprovedForAll + +```solidity +function isApprovedForAll(address account, address operator) external view returns (bool) +``` + +_See {IERC1155-isApprovedForAll}._ + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| account | address | undefined | +| operator | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### mergeFractions + +```solidity +function mergeFractions(address _account, uint256[] _fractionIDs) external nonpayable +``` + +Merge the value of tokens belonging to the same claim + +_see {IHypercertToken}_ + +#### Parameters + +| Name | Type | Description | +| ------------- | --------- | ----------- | +| \_account | address | undefined | +| \_fractionIDs | uint256[] | undefined | + +### mintClaim + +```solidity +function mintClaim(address account, uint256 units, string _uri, enum IHypercertToken.TransferRestrictions restrictions) external nonpayable +``` + +Mint a semi-fungible token for the impact claim referenced via `uri` + +_see {IHypercertToken}_ + +#### Parameters + +| Name | Type | Description | +| ------------ | ----------------------------------------- | ----------- | +| account | address | undefined | +| units | uint256 | undefined | +| \_uri | string | undefined | +| restrictions | enum IHypercertToken.TransferRestrictions | undefined | + +### mintClaimFromAllowlist + +```solidity +function mintClaimFromAllowlist(address account, bytes32[] proof, uint256 claimID, uint256 units) external nonpayable +``` + +Mint a semi-fungible token representing a fraction of the claim + +_Calls AllowlistMinter to verify `proof`.Mints the `amount` of units for the hypercert stored under `claimID`_ + +#### Parameters + +| Name | Type | Description | +| ------- | --------- | ----------- | +| account | address | undefined | +| proof | bytes32[] | undefined | +| claimID | uint256 | undefined | +| units | uint256 | undefined | + +### mintClaimWithFractions + +```solidity +function mintClaimWithFractions(address account, uint256 units, uint256[] fractions, string _uri, enum IHypercertToken.TransferRestrictions restrictions) external nonpayable +``` + +Mint semi-fungible tokens for the impact claim referenced via `uri` + +_see {IHypercertToken}_ + +#### Parameters + +| Name | Type | Description | +| ------------ | ----------------------------------------- | ----------- | +| account | address | undefined | +| units | uint256 | undefined | +| fractions | uint256[] | undefined | +| \_uri | string | undefined | +| restrictions | enum IHypercertToken.TransferRestrictions | undefined | + +### name + +```solidity +function name() external view returns (string) +``` + +#### Returns + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | string | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +_Returns the address of the current owner._ + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### ownerOf + +```solidity +function ownerOf(uint256 tokenID) external view returns (address _owner) +``` + +_Returns the owner of a given token ID._ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------------------------- | +| tokenID | uint256 | The ID of the token to query. | + +#### Returns + +| Name | Type | Description | +| ------- | ------- | -------------------------------------- | +| \_owner | address | The address of the owner of the token. | + +### pause + +```solidity +function pause() external nonpayable +``` + +PAUSABLE + +### paused + +```solidity +function paused() external view returns (bool) +``` + +_Returns true if the contract is paused, and false otherwise._ + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### proxiableUUID + +```solidity +function proxiableUUID() external view returns (bytes32) +``` + +_Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier._ + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### readTransferRestriction + +```solidity +function readTransferRestriction(uint256 tokenID) external view returns (string) +``` + +TRANSFER RESTRICTIONS + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| tokenID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ------ | ----------- | +| \_0 | string | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + +_Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner._ + +### safeBatchTransferFrom + +```solidity +function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] amounts, bytes data) external nonpayable +``` + +_See {IERC1155-safeBatchTransferFrom}._ + +#### Parameters + +| Name | Type | Description | +| ------- | --------- | ----------- | +| from | address | undefined | +| to | address | undefined | +| ids | uint256[] | undefined | +| amounts | uint256[] | undefined | +| data | bytes | undefined | + +### safeTransferFrom + +```solidity +function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes data) external nonpayable +``` + +_See {IERC1155-safeTransferFrom}._ + +#### Parameters + +| Name | Type | Description | +| ------ | ------- | ----------- | +| from | address | undefined | +| to | address | undefined | +| id | uint256 | undefined | +| amount | uint256 | undefined | +| data | bytes | undefined | + +### setApprovalForAll + +```solidity +function setApprovalForAll(address operator, bool approved) external nonpayable +``` + +_See {IERC1155-setApprovalForAll}._ + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| operator | address | undefined | +| approved | bool | undefined | + +### splitFraction + +```solidity +function splitFraction(address _account, uint256 _tokenID, uint256[] _newFractions) external nonpayable +``` + +Split a claimtokens value into parts with summed value equal to the original + +_see {IHypercertToken}_ + +#### Parameters + +| Name | Type | Description | +| -------------- | --------- | ----------- | +| \_account | address | undefined | +| \_tokenID | uint256 | undefined | +| \_newFractions | uint256[] | undefined | + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + +_See {IERC165-supportsInterface}._ + +#### Parameters + +| Name | Type | Description | +| ----------- | ------ | ----------- | +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + +_Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner._ + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +### unitsOf + +```solidity +function unitsOf(address account, uint256 tokenID) external view returns (uint256 units) +``` + +_see {IHypercertToken}_ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | +| tokenID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ----- | ------- | ----------- | +| units | uint256 | undefined | + +### unitsOf + +```solidity +function unitsOf(uint256 tokenID) external view returns (uint256 units) +``` + +_see {IHypercertToken}_ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| tokenID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ----- | ------- | ----------- | +| units | uint256 | undefined | + +### unpause + +```solidity +function unpause() external nonpayable +``` + +### upgradeTo + +```solidity +function upgradeTo(address newImplementation) external nonpayable +``` + +_Upgrade the implementation of the proxy to `newImplementation`. Calls {\_authorizeUpgrade}. Emits an {Upgraded} event._ + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| newImplementation | address | undefined | + +### upgradeToAndCall + +```solidity +function upgradeToAndCall(address newImplementation, bytes data) external payable +``` + +_Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {\_authorizeUpgrade}. Emits an {Upgraded} event._ + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| newImplementation | address | undefined | +| data | bytes | undefined | + +### uri + +```solidity +function uri(uint256 tokenID) external view returns (string _uri) +``` + +_see { IHypercertMetadata}_ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| tokenID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ----- | ------ | ----------- | +| \_uri | string | undefined | + +## Events + +### AdminChanged + +```solidity +event AdminChanged(address previousAdmin, address newAdmin) +``` + +#### Parameters + +| Name | Type | Description | +| ------------- | ------- | ----------- | +| previousAdmin | address | undefined | +| newAdmin | address | undefined | + +### AllowlistCreated + +```solidity +event AllowlistCreated(uint256 tokenID, bytes32 root) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| tokenID | uint256 | undefined | +| root | bytes32 | undefined | + +### ApprovalForAll + +```solidity +event ApprovalForAll(address indexed account, address indexed operator, bool approved) +``` + +#### Parameters + +| Name | Type | Description | +| ------------------ | ------- | ----------- | +| account `indexed` | address | undefined | +| operator `indexed` | address | undefined | +| approved | bool | undefined | + +### BatchValueTransfer + +```solidity +event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values) +``` + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | ----------- | +| claimIDs | uint256[] | undefined | +| fromTokenIDs | uint256[] | undefined | +| toTokenIDs | uint256[] | undefined | +| values | uint256[] | undefined | + +### BeaconUpgraded + +```solidity +event BeaconUpgraded(address indexed beacon) +``` + +#### Parameters + +| Name | Type | Description | +| ---------------- | ------- | ----------- | +| beacon `indexed` | address | undefined | + +### ClaimStored + +```solidity +event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits) +``` + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| claimID `indexed` | uint256 | undefined | +| uri | string | undefined | +| totalUnits | uint256 | undefined | + +### Initialized + +```solidity +event Initialized(uint8 version) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ----- | ----------- | +| version | uint8 | undefined | + +### LeafClaimed + +```solidity +event LeafClaimed(uint256 tokenID, bytes32 leaf) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| tokenID | uint256 | undefined | +| leaf | bytes32 | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + +#### Parameters + +| Name | Type | Description | +| ----------------------- | ------- | ----------- | +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + +### Paused + +```solidity +event Paused(address account) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | + +### TransferBatch + +```solidity +event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values) +``` + +#### Parameters + +| Name | Type | Description | +| ------------------ | --------- | ----------- | +| operator `indexed` | address | undefined | +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| ids | uint256[] | undefined | +| values | uint256[] | undefined | + +### TransferSingle + +```solidity +event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) +``` + +#### Parameters + +| Name | Type | Description | +| ------------------ | ------- | ----------- | +| operator `indexed` | address | undefined | +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| id | uint256 | undefined | +| value | uint256 | undefined | + +### URI + +```solidity +event URI(string value, uint256 indexed id) +``` + +#### Parameters + +| Name | Type | Description | +| ------------ | ------- | ----------- | +| value | string | undefined | +| id `indexed` | uint256 | undefined | + +### Unpaused + +```solidity +event Unpaused(address account) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | + +### Upgraded + +```solidity +event Upgraded(address indexed implementation) +``` + +#### Parameters + +| Name | Type | Description | +| ------------------------ | ------- | ----------- | +| implementation `indexed` | address | undefined | + +### ValueTransfer + +```solidity +event ValueTransfer(uint256 claimID, uint256 fromTokenID, uint256 toTokenID, uint256 value) +``` + +#### Parameters + +| Name | Type | Description | +| ----------- | ------- | ----------- | +| claimID | uint256 | undefined | +| fromTokenID | uint256 | undefined | +| toTokenID | uint256 | undefined | +| value | uint256 | undefined | + +## Errors + +### AlreadyClaimed + +```solidity +error AlreadyClaimed() +``` + +### ArraySize + +```solidity +error ArraySize() +``` + +### DoesNotExist + +```solidity +error DoesNotExist() +``` + +### DuplicateEntry + +```solidity +error DuplicateEntry() +``` + +### Invalid + +```solidity +error Invalid() +``` + +### NotAllowed + +```solidity +error NotAllowed() +``` + +### NotApprovedOrOwner + +```solidity +error NotApprovedOrOwner() +``` + +### TransfersNotAllowed + +```solidity +error TransfersNotAllowed() +``` + +### TypeMismatch + +```solidity +error TypeMismatch() +``` diff --git a/docs/docs/developer/api/contracts/protocol/SemiFungible1155.md b/docs/docs/developer/api/contracts/protocol/SemiFungible1155.md new file mode 100644 index 00000000..a4086e37 --- /dev/null +++ b/docs/docs/developer/api/contracts/protocol/SemiFungible1155.md @@ -0,0 +1,457 @@ +# SemiFungible1155 + +_bitbeckers_ + +> Contract for minting semi-fungible EIP1155 tokens + +Extends { Upgradeable1155 } token with semi-fungible properties and the concept of `units` + +_Adds split bit strategy as described in [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155#non-fungible-tokens)_ + +## Methods + +### \_\_SemiFungible1155_init + +```solidity +function __SemiFungible1155_init() external nonpayable +``` + +_see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol }_ + +### balanceOf + +```solidity +function balanceOf(address account, uint256 id) external view returns (uint256) +``` + +_See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address._ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | +| id | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | uint256 | undefined | + +### balanceOfBatch + +```solidity +function balanceOfBatch(address[] accounts, uint256[] ids) external view returns (uint256[]) +``` + +_See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length._ + +#### Parameters + +| Name | Type | Description | +| -------- | --------- | ----------- | +| accounts | address[] | undefined | +| ids | uint256[] | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | --------- | ----------- | +| \_0 | uint256[] | undefined | + +### burn + +```solidity +function burn(address account, uint256 id, uint256 value) external nonpayable +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | +| id | uint256 | undefined | +| value | uint256 | undefined | + +### burnBatch + +```solidity +function burnBatch(address account, uint256[] ids, uint256[] values) external nonpayable +``` + +#### Parameters + +| Name | Type | Description | +| ------- | --------- | ----------- | +| account | address | undefined | +| ids | uint256[] | undefined | +| values | uint256[] | undefined | + +### isApprovedForAll + +```solidity +function isApprovedForAll(address account, address operator) external view returns (bool) +``` + +_See {IERC1155-isApprovedForAll}._ + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| account | address | undefined | +| operator | address | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### owner + +```solidity +function owner() external view returns (address) +``` + +_Returns the address of the current owner._ + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | address | undefined | + +### ownerOf + +```solidity +function ownerOf(uint256 tokenID) external view returns (address _owner) +``` + +_Returns the owner of a given token ID._ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------------------------- | +| tokenID | uint256 | The ID of the token to query. | + +#### Returns + +| Name | Type | Description | +| ------- | ------- | -------------------------------------- | +| \_owner | address | The address of the owner of the token. | + +### proxiableUUID + +```solidity +function proxiableUUID() external view returns (bytes32) +``` + +_Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier._ + +#### Returns + +| Name | Type | Description | +| ---- | ------- | ----------- | +| \_0 | bytes32 | undefined | + +### renounceOwnership + +```solidity +function renounceOwnership() external nonpayable +``` + +_Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner._ + +### safeBatchTransferFrom + +```solidity +function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] amounts, bytes data) external nonpayable +``` + +_See {IERC1155-safeBatchTransferFrom}._ + +#### Parameters + +| Name | Type | Description | +| ------- | --------- | ----------- | +| from | address | undefined | +| to | address | undefined | +| ids | uint256[] | undefined | +| amounts | uint256[] | undefined | +| data | bytes | undefined | + +### safeTransferFrom + +```solidity +function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes data) external nonpayable +``` + +_See {IERC1155-safeTransferFrom}._ + +#### Parameters + +| Name | Type | Description | +| ------ | ------- | ----------- | +| from | address | undefined | +| to | address | undefined | +| id | uint256 | undefined | +| amount | uint256 | undefined | +| data | bytes | undefined | + +### setApprovalForAll + +```solidity +function setApprovalForAll(address operator, bool approved) external nonpayable +``` + +_See {IERC1155-setApprovalForAll}._ + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| operator | address | undefined | +| approved | bool | undefined | + +### supportsInterface + +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool) +``` + +_See {IERC165-supportsInterface}._ + +#### Parameters + +| Name | Type | Description | +| ----------- | ------ | ----------- | +| interfaceId | bytes4 | undefined | + +#### Returns + +| Name | Type | Description | +| ---- | ---- | ----------- | +| \_0 | bool | undefined | + +### transferOwnership + +```solidity +function transferOwnership(address newOwner) external nonpayable +``` + +_Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner._ + +#### Parameters + +| Name | Type | Description | +| -------- | ------- | ----------- | +| newOwner | address | undefined | + +### upgradeTo + +```solidity +function upgradeTo(address newImplementation) external nonpayable +``` + +_Upgrade the implementation of the proxy to `newImplementation`. Calls {\_authorizeUpgrade}. Emits an {Upgraded} event._ + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| newImplementation | address | undefined | + +### upgradeToAndCall + +```solidity +function upgradeToAndCall(address newImplementation, bytes data) external payable +``` + +_Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {\_authorizeUpgrade}. Emits an {Upgraded} event._ + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| newImplementation | address | undefined | +| data | bytes | undefined | + +### uri + +```solidity +function uri(uint256 tokenID) external view returns (string _uri) +``` + +_Returns the metadata URI for a given token ID.This function retrieves the metadata URI for the specified token ID by calling the `uri` function of the `ERC1155URIStorageUpgradeable` contract.The metadata URI is a string that points to a JSON file containing information about the token, such as its name, symbol, and image.This function always returns the URI for the basetype so that it's managed in one place._ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------------------------------------------------- | +| tokenID | uint256 | The ID of the token to retrieve the metadata URI for. | + +#### Returns + +| Name | Type | Description | +| ----- | ------ | -------------------------------------------- | +| \_uri | string | The metadata URI for the specified token ID. | + +## Events + +### AdminChanged + +```solidity +event AdminChanged(address previousAdmin, address newAdmin) +``` + +#### Parameters + +| Name | Type | Description | +| ------------- | ------- | ----------- | +| previousAdmin | address | undefined | +| newAdmin | address | undefined | + +### ApprovalForAll + +```solidity +event ApprovalForAll(address indexed account, address indexed operator, bool approved) +``` + +#### Parameters + +| Name | Type | Description | +| ------------------ | ------- | ----------- | +| account `indexed` | address | undefined | +| operator `indexed` | address | undefined | +| approved | bool | undefined | + +### BatchValueTransfer + +```solidity +event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values) +``` + +_Emitted on transfer of `values` between `fromTokenIDs` to `toTokenIDs` of `claimIDs`_ + +#### Parameters + +| Name | Type | Description | +| ------------ | --------- | ----------- | +| claimIDs | uint256[] | undefined | +| fromTokenIDs | uint256[] | undefined | +| toTokenIDs | uint256[] | undefined | +| values | uint256[] | undefined | + +### BeaconUpgraded + +```solidity +event BeaconUpgraded(address indexed beacon) +``` + +#### Parameters + +| Name | Type | Description | +| ---------------- | ------- | ----------- | +| beacon `indexed` | address | undefined | + +### Initialized + +```solidity +event Initialized(uint8 version) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | ----- | ----------- | +| version | uint8 | undefined | + +### OwnershipTransferred + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +``` + +#### Parameters + +| Name | Type | Description | +| ----------------------- | ------- | ----------- | +| previousOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | + +### TransferBatch + +```solidity +event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values) +``` + +#### Parameters + +| Name | Type | Description | +| ------------------ | --------- | ----------- | +| operator `indexed` | address | undefined | +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| ids | uint256[] | undefined | +| values | uint256[] | undefined | + +### TransferSingle + +```solidity +event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) +``` + +#### Parameters + +| Name | Type | Description | +| ------------------ | ------- | ----------- | +| operator `indexed` | address | undefined | +| from `indexed` | address | undefined | +| to `indexed` | address | undefined | +| id | uint256 | undefined | +| value | uint256 | undefined | + +### URI + +```solidity +event URI(string value, uint256 indexed id) +``` + +#### Parameters + +| Name | Type | Description | +| ------------ | ------- | ----------- | +| value | string | undefined | +| id `indexed` | uint256 | undefined | + +### Upgraded + +```solidity +event Upgraded(address indexed implementation) +``` + +#### Parameters + +| Name | Type | Description | +| ------------------------ | ------- | ----------- | +| implementation `indexed` | address | undefined | + +### ValueTransfer + +```solidity +event ValueTransfer(uint256 claimID, uint256 fromTokenID, uint256 toTokenID, uint256 value) +``` + +_Emitted on transfer of `value` between `fromTokenID` to `toTokenID` of the same `claimID`_ + +#### Parameters + +| Name | Type | Description | +| ----------- | ------- | ----------- | +| claimID | uint256 | undefined | +| fromTokenID | uint256 | undefined | +| toTokenID | uint256 | undefined | +| value | uint256 | undefined | diff --git a/docs/docs/developer/api/contracts/protocol/interfaces/IAllowlist.md b/docs/docs/developer/api/contracts/protocol/interfaces/IAllowlist.md new file mode 100644 index 00000000..72455b43 --- /dev/null +++ b/docs/docs/developer/api/contracts/protocol/interfaces/IAllowlist.md @@ -0,0 +1,29 @@ +# IAllowlist + +_bitbeckers_ + +> Interface for allowlist + +This interface declares the required functionality for a hypercert tokenThis interface does not specify the underlying token type (e.g. 721 or 1155) + +## Methods + +### isAllowedToClaim + +```solidity +function isAllowedToClaim(bytes32[] proof, uint256 tokenID, bytes32 leaf) external view returns (bool isAllowed) +``` + +#### Parameters + +| Name | Type | Description | +| ------- | --------- | ----------- | +| proof | bytes32[] | undefined | +| tokenID | uint256 | undefined | +| leaf | bytes32 | undefined | + +#### Returns + +| Name | Type | Description | +| --------- | ---- | ----------- | +| isAllowed | bool | undefined | diff --git a/docs/docs/developer/api/contracts/protocol/interfaces/IHypercertToken.md b/docs/docs/developer/api/contracts/protocol/interfaces/IHypercertToken.md new file mode 100644 index 00000000..30ed6f95 --- /dev/null +++ b/docs/docs/developer/api/contracts/protocol/interfaces/IHypercertToken.md @@ -0,0 +1,192 @@ +# IHypercertToken + +_bitbeckers_ + +> Interface for hypercert token interactions + +This interface declares the required functionality for a hypercert tokenThis interface does not specify the underlying token type (e.g. 721 or 1155) + +## Methods + +### batchBurnFraction + +```solidity +function batchBurnFraction(address account, uint256[] tokenIDs) external nonpayable +``` + +Operator must be allowed by `creator` and the tokens must represent the total amount of available units. + +_Function to burn the tokens at `tokenIDs` for `account`_ + +#### Parameters + +| Name | Type | Description | +| -------- | --------- | ----------- | +| account | address | undefined | +| tokenIDs | uint256[] | undefined | + +### burnFraction + +```solidity +function burnFraction(address account, uint256 tokenID) external nonpayable +``` + +Operator must be allowed by `creator` and the token must represent the total amount of available units. + +_Function to burn the token at `tokenID` for `account`_ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | +| tokenID | uint256 | undefined | + +### mergeFractions + +```solidity +function mergeFractions(address account, uint256[] tokenIDs) external nonpayable +``` + +Tokens that have been merged are burned. + +_Function called to merge tokens within `tokenIDs`._ + +#### Parameters + +| Name | Type | Description | +| -------- | --------- | ----------- | +| account | address | undefined | +| tokenIDs | uint256[] | undefined | + +### mintClaim + +```solidity +function mintClaim(address account, uint256 units, string uri, enum IHypercertToken.TransferRestrictions restrictions) external nonpayable +``` + +_Function called to store a claim referenced via `uri` with a maximum number of fractions `units`._ + +#### Parameters + +| Name | Type | Description | +| ------------ | ----------------------------------------- | ----------- | +| account | address | undefined | +| units | uint256 | undefined | +| uri | string | undefined | +| restrictions | enum IHypercertToken.TransferRestrictions | undefined | + +### mintClaimWithFractions + +```solidity +function mintClaimWithFractions(address account, uint256 units, uint256[] fractions, string uri, enum IHypercertToken.TransferRestrictions restrictions) external nonpayable +``` + +_Function called to store a claim referenced via `uri` with a set of `fractions`.Fractions are internally summed to total units._ + +#### Parameters + +| Name | Type | Description | +| ------------ | ----------------------------------------- | ----------- | +| account | address | undefined | +| units | uint256 | undefined | +| fractions | uint256[] | undefined | +| uri | string | undefined | +| restrictions | enum IHypercertToken.TransferRestrictions | undefined | + +### splitFraction + +```solidity +function splitFraction(address account, uint256 tokenID, uint256[] _values) external nonpayable +``` + +The sum of `values` must equal the current value of `_tokenID`. + +_Function called to split `tokenID` owned by `account` into units declared in `values`._ + +#### Parameters + +| Name | Type | Description | +| -------- | --------- | ----------- | +| account | address | undefined | +| tokenID | uint256 | undefined | +| \_values | uint256[] | undefined | + +### unitsOf + +```solidity +function unitsOf(address account, uint256 tokenID) external view returns (uint256 units) +``` + +_Returns the `units` held by `account` of a (fractional) token at `claimID`If `tokenID` is a base type, the total amount of `units` held by `account` for the claim is returned.If `tokenID` is a fractional token, the `units` held by `account` the token is returned_ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| account | address | undefined | +| tokenID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ----- | ------- | ----------- | +| units | uint256 | undefined | + +### unitsOf + +```solidity +function unitsOf(uint256 tokenID) external view returns (uint256 units) +``` + +_Returns the `units` held by a (fractional) token at `claimID`If `tokenID` is a base type, the total amount of `units` for the claim is returned.If `tokenID` is a fractional token, the `units` held by the token is returned_ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| tokenID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| ----- | ------- | ----------- | +| units | uint256 | undefined | + +### uri + +```solidity +function uri(uint256 tokenID) external view returns (string metadata) +``` + +_Returns the `uri` for metadata of the claim represented by `tokenID`Metadata must conform to { Hypercert Metadata } spec (based on ERC1155 Metadata)_ + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------- | +| tokenID | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +| -------- | ------ | ----------- | +| metadata | string | undefined | + +## Events + +### ClaimStored + +```solidity +event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits) +``` + +_Emitted when token with tokenID `claimID` is stored, with external data reference via `uri`._ + +#### Parameters + +| Name | Type | Description | +| ----------------- | ------- | ----------- | +| claimID `indexed` | uint256 | undefined | +| uri | string | undefined | +| totalUnits | uint256 | undefined | diff --git a/docs/docs/developer/api/contracts/protocol/libs/Errors.md b/docs/docs/developer/api/contracts/protocol/libs/Errors.md new file mode 100644 index 00000000..93fe0124 --- /dev/null +++ b/docs/docs/developer/api/contracts/protocol/libs/Errors.md @@ -0,0 +1,59 @@ +# Errors + +_bitbeckers_ + +## Errors + +### AlreadyClaimed + +```solidity +error AlreadyClaimed() +``` + +### ArraySize + +```solidity +error ArraySize() +``` + +### DoesNotExist + +```solidity +error DoesNotExist() +``` + +### DuplicateEntry + +```solidity +error DuplicateEntry() +``` + +### Invalid + +```solidity +error Invalid() +``` + +### NotAllowed + +```solidity +error NotAllowed() +``` + +### NotApprovedOrOwner + +```solidity +error NotApprovedOrOwner() +``` + +### TransfersNotAllowed + +```solidity +error TransfersNotAllowed() +``` + +### TypeMismatch + +```solidity +error TypeMismatch() +``` diff --git a/frontend/lib/parse-blockchain-error.ts b/frontend/lib/parse-blockchain-error.ts index 1f28a411..8c169066 100644 --- a/frontend/lib/parse-blockchain-error.ts +++ b/frontend/lib/parse-blockchain-error.ts @@ -1,19 +1,20 @@ import { errorMessages } from "../content/readable-errors"; -import { useHypercertClient } from "../hooks/hypercerts-client"; +import { decodeErrorResult } from "viem"; +import { HypercertMinterAbi } from "@hypercerts-org/contracts"; export const useParseBlockchainError = () => { - const { - client: { contract }, - } = useHypercertClient(); return (e: any, fallbackMessage: string) => { const unparsedErrorData = e?.error?.data?.originalError?.data; if (unparsedErrorData) { - const errorData = contract?.interface?.parseError(unparsedErrorData); + const errorData = decodeErrorResult({ + abi: HypercertMinterAbi, + data: unparsedErrorData, + }); if (errorData) { console.log("Blockchain error", errorData); - const errorName = errorData.errorFragment.name; + const errorName = errorData.errorName; return errorMessages[errorName] || errorName; } } diff --git a/graph/tests/.latest.json b/graph/tests/.latest.json index 9f77af1a..1c85d95b 100644 --- a/graph/tests/.latest.json +++ b/graph/tests/.latest.json @@ -1,4 +1,4 @@ { "version": "0.6.0", - "timestamp": 1698421837557 + "timestamp": 1698982104763 } diff --git a/package.json b/package.json index 38706568..19c7c402 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,13 @@ "type": "git", "url": "git+/~https://github.com/hypercerts-org/hypercerts.git" }, - "resolutions": { + "overrides": { "graphql": "^16.6.0", - "ethers": "^5.7.2" + "@hypercerts/contracts": { + "ethers": "6.8.0" + }, + "@hypercerts/frontend": { + "ethers": "5.7.2" + } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a353eed7..41300ef3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,10 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - graphql: ^16.6.0 - ethers: ^5.7.2 - importers: .: @@ -32,10 +28,14 @@ importers: version: 1.10.16 contracts: + dependencies: + hardhat: + specifier: ^2.18.3 + version: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) devDependencies: '@chainlink/contracts': specifier: ^0.8.0 - version: 0.8.0(ethers@5.7.2) + version: 0.8.0(ethers@6.8.0) '@commitlint/cli': specifier: ^17.1.2 version: 17.8.1 @@ -44,46 +44,22 @@ importers: version: 17.8.1 '@dlsl/hardhat-markup': specifier: ^1.0.0-rc.7 - version: 1.0.0-rc.14(hardhat@2.13.1)(prettier@2.8.8) - '@ethersproject/abi': - specifier: ^5.7.0 - version: 5.7.0 - '@ethersproject/bytes': - specifier: ^5.7.0 - version: 5.7.0 - '@ethersproject/providers': - specifier: ^5.7.2 - version: 5.7.2 + version: 1.0.0-rc.14(hardhat@2.18.3)(prettier@2.8.8) '@looksrare/contracts-libs': specifier: ^3.4.0 version: 3.4.0 - '@nomicfoundation/hardhat-chai-matchers': - specifier: ^1.0.5 - version: 1.0.6(@nomiclabs/hardhat-ethers@2.2.3)(chai@4.3.10)(ethers@5.7.2)(hardhat@2.13.1) - '@nomicfoundation/hardhat-network-helpers': - specifier: ^1.0.7 - version: 1.0.9(hardhat@2.13.1) '@nomicfoundation/hardhat-toolbox': - specifier: ^2.0.0 - version: 2.0.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-chai-matchers@1.0.6)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(@typechain/ethers-v5@11.1.2)(@typechain/hardhat@9.1.0)(@types/chai@4.3.9)(@types/mocha@9.1.0)(@types/node@18.18.7)(chai@4.3.10)(ethers@5.7.2)(hardhat-gas-reporter@1.0.9)(hardhat@2.13.1)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.2)(typescript@4.9.5) - '@nomiclabs/hardhat-ethers': - specifier: ^2.2.1 - version: 2.2.3(ethers@5.7.2)(hardhat@2.13.1) - '@nomiclabs/hardhat-etherscan': - specifier: ^3.1.3 - version: 3.1.7(hardhat@2.13.1) + specifier: ^3.0.0 + version: 3.0.0(@nomicfoundation/hardhat-chai-matchers@2.0.2)(@nomicfoundation/hardhat-ethers@3.0.4)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomicfoundation/hardhat-verify@1.1.1)(@typechain/ethers-v6@0.4.3)(@typechain/hardhat@8.0.3)(@types/chai@4.3.9)(@types/mocha@9.1.0)(@types/node@18.18.7)(chai@4.3.10)(ethers@6.8.0)(hardhat-gas-reporter@1.0.9)(hardhat@2.18.3)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.2)(typescript@4.9.5) '@openzeppelin/contracts': specifier: <5.0.0 version: 4.9.3 - '@openzeppelin/hardhat-defender': - specifier: ^1.8.2 - version: 1.9.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.13.1) '@openzeppelin/hardhat-upgrades': - specifier: ^1.28 - version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.13.1) + specifier: 2.3.3 + version: 2.3.3(@nomicfoundation/hardhat-ethers@3.0.4)(@nomicfoundation/hardhat-verify@1.1.1)(ethers@6.8.0)(hardhat@2.18.3) '@primitivefi/hardhat-dodoc': specifier: ^0.2.3 - version: 0.2.3(hardhat@2.13.1)(squirrelly@8.0.8) + version: 0.2.3(hardhat@2.18.3)(squirrelly@8.0.8) '@rollup/plugin-commonjs': specifier: ^24.0.1 version: 24.1.0(rollup@4.1.4) @@ -96,18 +72,6 @@ importers: '@trivago/prettier-plugin-sort-imports': specifier: ^3.3.0 version: 3.4.0(prettier@2.8.8) - '@typechain/ethers-v5': - specifier: ^11.1.1 - version: 11.1.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) - '@typechain/hardhat': - specifier: ^9.0.0 - version: 9.1.0(@typechain/ethers-v6@0.5.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2) - '@types/chai': - specifier: ^4.3.4 - version: 4.3.9 - '@types/mocha': - specifier: 9.1.0 - version: 9.1.0 '@types/node': specifier: ^18.11.11 version: 18.18.7 @@ -117,15 +81,9 @@ importers: '@typescript-eslint/parser': specifier: ^5.38.0 version: 5.62.0(eslint@8.52.0)(typescript@4.9.5) - chai: - specifier: ^4.3.7 - version: 4.3.10 commitizen: specifier: ^4.2.5 version: 4.3.0(typescript@4.9.5) - copyfiles: - specifier: ^2.4.1 - version: 2.4.1 cross-env: specifier: ^7.0.3 version: 7.0.3 @@ -142,20 +100,14 @@ importers: specifier: ^8.5.0 version: 8.10.0(eslint@8.52.0) ethers: - specifier: ^5.7.2 - version: 5.7.2 - hardhat: - specifier: 2.13.1 - version: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + specifier: ^6.8.0 + version: 6.8.0 hardhat-abi-exporter: specifier: ^2.10.1 - version: 2.10.1(hardhat@2.13.1) - hardhat-gas-reporter: - specifier: ^1.0.9 - version: 1.0.9(hardhat@2.13.1) + version: 2.10.1(hardhat@2.18.3) hardhat-preprocessor: specifier: ^0.1.5 - version: 0.1.5(hardhat@2.13.1) + version: 0.1.5(hardhat@2.18.3) husky: specifier: ^8.0.1 version: 8.0.3 @@ -253,7 +205,7 @@ importers: specifier: ^16.0.3 version: 16.3.1 ethers: - specifier: ^5.7.2 + specifier: 5.7.2 version: 5.7.2 node-fetch: specifier: ^3.3.0 @@ -423,7 +375,7 @@ importers: specifier: ^16.0.3 version: 16.3.1 ethers: - specifier: ^5.7.2 + specifier: 5.7.2 version: 5.7.2 formik: specifier: ^2.2.9 @@ -568,8 +520,8 @@ importers: sdk: dependencies: '@ethereum-attestation-service/eas-sdk': - specifier: ^0.28.3 - version: 0.28.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ts-node@10.9.1)(typescript@4.9.5) + specifier: 1.2.2-beta.0 + version: 1.2.2-beta.0(ts-node@10.9.1)(typescript@5.1.6) '@ethersproject/abstract-signer': specifier: ^5.7.0 version: 5.7.0 @@ -578,7 +530,7 @@ importers: version: 1.0.20(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) '@graphprotocol/client-polling-live': specifier: ^2.0.0 - version: 2.0.0(@envelop/core@4.0.3)(@graphql-tools/merge@9.0.0)(graphql@16.8.1) + version: 2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@9.0.0)(graphql@16.8.1) '@graphql-mesh/cache-localforage': specifier: ^0.95.7 version: 0.95.8(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) @@ -628,7 +580,7 @@ importers: specifier: ^16.0.3 version: 16.3.1 ethers: - specifier: ^5.7.2 + specifier: 5.7.2 version: 5.7.2 graphql: specifier: ^16.6.0 @@ -636,9 +588,6 @@ importers: ipfs-core: specifier: ^0.17.0 version: 0.17.0(uint8arraylist@2.4.3) - jest: - specifier: ^29.3.1 - version: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) loglevel: specifier: ^1.8.1 version: 1.8.1 @@ -648,6 +597,9 @@ importers: nft.storage: specifier: ^7.1.1 version: 7.1.1(node-fetch@3.3.2) + viem: + specifier: 1.5.3 + version: 1.5.3(typescript@5.1.6)(zod@3.22.4) web3.storage: specifier: ^4.5.5 version: 4.5.5(node-fetch@3.3.2) @@ -666,7 +618,7 @@ importers: version: 8.2.0 '@graphprotocol/client-cli': specifier: ^3.0.0 - version: 3.0.0(@babel/core@7.23.2)(@envelop/core@4.0.3)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) + version: 3.0.0(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) '@jest/globals': specifier: ^29.7.0 version: 29.7.0 @@ -697,6 +649,12 @@ importers: '@types/sinon': specifier: ^10.0.15 version: 10.0.20 + '@viem/anvil': + specifier: ^0.0.6 + version: 0.0.6 + abitype: + specifier: ^0.10.2 + version: 0.10.2(typescript@5.1.6)(zod@3.22.4) babel-jest: specifier: ^29.7.0 version: 29.7.0(@babel/core@7.23.2) @@ -714,19 +672,28 @@ importers: version: 0.17.19 ethereum-waffle: specifier: ^4.0.10 - version: 4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@4.9.5) + version: 4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.1.6) + fetch-mock: + specifier: ^9.11.0 + version: 9.11.0(node-fetch@3.3.2) it-all: specifier: ^2.0.0 version: 2.0.1 + jest: + specifier: ^29.3.1 + version: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) jest-extended: specifier: ^4.0.0 version: 4.0.2(jest@29.7.0) + jest-fetch-mock: + specifier: ^3.0.3 + version: 3.0.3 json-schema-to-typescript: specifier: ^12.0.0 version: 12.0.0 msw: specifier: ^1.2.1 - version: 1.3.2(typescript@4.9.5) + version: 1.3.2(typescript@5.1.6) nyc: specifier: ^15.1.0 version: 15.1.0 @@ -738,7 +705,7 @@ importers: version: 2.0.0(rollup@3.29.4) rollup-plugin-dts: specifier: ^5.2.0 - version: 5.3.1(rollup@3.29.4)(typescript@4.9.5) + version: 5.3.1(rollup@3.29.4)(typescript@5.1.6) rollup-plugin-esbuild: specifier: ^5.0.0 version: 5.0.0(esbuild@0.17.19)(rollup@3.29.4) @@ -753,7 +720,7 @@ importers: version: 15.2.0 ts-jest: specifier: ^29.0.3 - version: 29.1.1(@babel/core@7.23.2)(babel-jest@29.7.0)(esbuild@0.17.19)(jest@29.7.0)(typescript@4.9.5) + version: 29.1.1(@babel/core@7.23.2)(babel-jest@29.7.0)(esbuild@0.17.19)(jest@29.7.0)(typescript@5.1.6) ts-jest-resolver: specifier: ^2.0.0 version: 2.0.1 @@ -762,7 +729,7 @@ importers: version: 10.0.0(mocha@10.2.0) ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) + version: 10.9.1(@types/node@18.18.7)(typescript@5.1.6) tslib: specifier: ^2.5.0 version: 2.6.2 @@ -771,16 +738,16 @@ importers: version: 3.14.0 typedoc: specifier: ^0.23.25 - version: 0.23.28(typescript@4.9.5) + version: 0.23.28(typescript@5.1.6) typedoc-plugin-markdown: specifier: ^3.14.0 - version: 3.16.0(typedoc@0.23.28) + version: 3.17.0(typedoc@0.23.28) typedoc-plugin-missing-exports: specifier: ^2.0.0 version: 2.1.0(typedoc@0.23.28) typescript: - specifier: ^4.9.0 - version: 4.9.5 + specifier: 5.1.6 + version: 5.1.6 vendor/observabletreemap: dependencies: @@ -830,6 +797,9 @@ packages: resolution: {integrity: sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==} dev: true + /@adraffy/ens-normalize@1.10.0: + resolution: {integrity: sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==} + /@adraffy/ens-normalize@1.9.0: resolution: {integrity: sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ==} @@ -981,7 +951,7 @@ packages: /@apollo/client@3.8.6(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-FnHg3vhQP8tQzgBs6oTJCFFIbovelDGYujj6MK7CJneiHf62TJstCIO0Ot4A1h7XrgFEtgl8a/OgajQWqrTuYw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 graphql-ws: ^5.5.5 react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -1030,7 +1000,7 @@ packages: resolution: {integrity: sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q==} hasBin: true peerDependencies: - graphql: ^16.6.0 + graphql: '*' dependencies: '@babel/core': 7.23.2 '@babel/generator': 7.23.0 @@ -1514,7 +1484,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.9 - '@babel/helper-plugin-utils': 7.10.4 + '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.12.9) '@babel/plugin-transform-parameters': 7.22.15(@babel/core@7.12.9) dev: false @@ -2649,10 +2619,10 @@ packages: - zod dev: false - /@chainlink/contracts@0.8.0(ethers@5.7.2): + /@chainlink/contracts@0.8.0(ethers@6.8.0): resolution: {integrity: sha512-nUv1Uxw5Mn92wgLs2bgPYmo8hpdQ3s9jB/lcbdU0LmNOVu0hbfmouVnqwRLa28Ll50q6GczUA+eO0ikNIKLZsA==} dependencies: - '@eth-optimism/contracts': 0.5.40(ethers@5.7.2) + '@eth-optimism/contracts': 0.5.40(ethers@6.8.0) '@openzeppelin/contracts': 4.3.3 '@openzeppelin/contracts-upgradeable-4.7.3': /@openzeppelin/contracts-upgradeable@4.7.3 '@openzeppelin/contracts-v0.7': /@openzeppelin/contracts@3.4.2 @@ -3190,13 +3160,13 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} - /@dlsl/hardhat-markup@1.0.0-rc.14(hardhat@2.13.1)(prettier@2.8.8): + /@dlsl/hardhat-markup@1.0.0-rc.14(hardhat@2.18.3)(prettier@2.8.8): resolution: {integrity: sha512-fhkjuHjM6sDzjY6xiNHiENTdNRQGDEZ8RTkFnmvGVSYP2G7VKjVvay0ZWxILIXb+WvK+JdkcVtpvR00eo8wuWg==} deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. peerDependencies: hardhat: ^2.10.0 dependencies: - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) json2md: 2.0.0 prettier-plugin-solidity: 1.1.3(prettier@2.8.8) solidity-ast: 0.4.52 @@ -4185,13 +4155,6 @@ packages: '@envelop/types': 3.0.2 tslib: 2.6.2 - /@envelop/core@4.0.3: - resolution: {integrity: sha512-O0Vz8E0TObT6ijAob8jYFVJavcGywKThM3UAsxUIBBVPYZTMiqI9lo2gmAnbMUnrDcAYkUTZEW9FDYPRdF5l6g==} - engines: {node: '>=16.0.0'} - dependencies: - '@envelop/types': 4.0.1 - tslib: 2.6.2 - /@envelop/core@5.0.0: resolution: {integrity: sha512-aJdnH/ptv+cvwfvciCBe7TSvccBwo9g0S5f6u35TBVzRVqIGkK03lFlIL+x1cnfZgN9EfR2b1PH2galrT1CdCQ==} engines: {node: '>=18.0.0'} @@ -4204,7 +4167,7 @@ packages: resolution: {integrity: sha512-aXAf1bg5Z71YfEKLCZ8OMUZAOYPGHV/a+7avd5TIMFNDxl5wJTmIonep3T+kdMpwRInDphfNPGFD0GcGdGxpHg==} peerDependencies: '@envelop/core': ^3.0.6 - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@envelop/core': 3.0.6 '@graphql-tools/utils': 8.13.1(graphql@16.8.1) @@ -4216,7 +4179,7 @@ packages: engines: {node: '>=18.0.0'} peerDependencies: '@envelop/core': ^5.0.0 - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@envelop/core': 5.0.0 '@graphql-tools/utils': 10.0.7(graphql@16.8.1) @@ -4229,7 +4192,7 @@ packages: engines: {node: '>=18.0.0'} peerDependencies: '@envelop/core': ^5.0.0 - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@envelop/core': 5.0.0 graphql: 16.8.1 @@ -4243,12 +4206,6 @@ packages: dependencies: tslib: 2.6.2 - /@envelop/types@4.0.1: - resolution: {integrity: sha512-ULo27/doEsP7uUhm2iTnElx13qTO6I5FKvmLoX41cpfuw8x6e0NUFknoqhEsLzAbgz8xVS5mjwcxGCXh4lDYzg==} - engines: {node: '>=16.0.0'} - dependencies: - tslib: 2.6.2 - /@envelop/types@5.0.0: resolution: {integrity: sha512-IPjmgSc4KpQRlO4qbEDnBEixvtb06WDmjKfi/7fkZaryh5HuOmTtixe1EupQI5XfXO8joc3d27uUZ0QdC++euA==} engines: {node: '>=18.0.0'} @@ -4260,7 +4217,7 @@ packages: resolution: {integrity: sha512-MkzcScQHJJQ/9YCAPdWShEi3xZv4F4neTs+NszzSrZOdlU8z/THuRt7gZ0sO0y2be+sx+SKjHQP8Gq3VXXcTTg==} peerDependencies: '@envelop/core': ^3.0.6 - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@envelop/core': 3.0.6 graphql: 16.8.1 @@ -5138,15 +5095,15 @@ packages: resolution: {integrity: sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@eth-optimism/contracts@0.5.40(ethers@5.7.2): + /@eth-optimism/contracts@0.5.40(ethers@6.8.0): resolution: {integrity: sha512-MrzV0nvsymfO/fursTB7m/KunkPsCndltVgfdHaT1Aj5Vi6R/doKIGGkOofHX+8B6VMZpuZosKCMQ5lQuqjt8w==} peerDependencies: - ethers: ^5.7.2 + ethers: ^5 dependencies: '@eth-optimism/core-utils': 0.12.0 '@ethersproject/abstract-provider': 5.7.0 '@ethersproject/abstract-signer': 5.7.0 - ethers: 5.7.2 + ethers: 6.8.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -5176,13 +5133,13 @@ packages: - utf-8-validate dev: true - /@ethereum-attestation-service/eas-contracts@0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(ts-node@10.9.1)(typescript@4.9.5): + /@ethereum-attestation-service/eas-contracts@0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.1.6): resolution: {integrity: sha512-ly1N/jLbXJjACDL7dnMSkzViBxxuVc+aMZ3EB1kpFxeMWrXkb7nN6w9gxGTH+m3gJztaKvyMsyr/13pA0OYq6Q==} dependencies: - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) + '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.1.6) '@typechain/hardhat': 6.1.6(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@10.2.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2) - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) - typechain: 8.3.2(typescript@4.9.5) + hardhat: 2.13.1(typescript@5.1.6) + typechain: 8.3.2(typescript@5.1.6) transitivePeerDependencies: - '@ethersproject/abi' - '@ethersproject/providers' @@ -5194,28 +5151,22 @@ packages: - utf-8-validate dev: false - /@ethereum-attestation-service/eas-contracts@0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.1.6): - resolution: {integrity: sha512-ly1N/jLbXJjACDL7dnMSkzViBxxuVc+aMZ3EB1kpFxeMWrXkb7nN6w9gxGTH+m3gJztaKvyMsyr/13pA0OYq6Q==} + /@ethereum-attestation-service/eas-contracts@1.2.0-beta.1(ts-node@10.9.1)(typescript@5.1.6): + resolution: {integrity: sha512-NOicVFjm3UOY6HHmMPIpFTZJ7ieuETl7GRJyceW/CPPXxMMBBu9tf9eDVbVrDn6D7fYX3NMDIR39RoK5BhpWYA==} dependencies: - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.1.6) - '@typechain/hardhat': 6.1.6(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@10.2.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2) - hardhat: 2.13.1(typescript@5.1.6) - typechain: 8.3.2(typescript@5.1.6) + hardhat: 2.18.2(ts-node@10.9.1)(typescript@5.1.6) transitivePeerDependencies: - - '@ethersproject/abi' - - '@ethersproject/providers' - bufferutil - - ethers - supports-color - ts-node - typescript - utf-8-validate dev: false - /@ethereum-attestation-service/eas-sdk@0.28.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ts-node@10.9.1)(typescript@4.9.5): + /@ethereum-attestation-service/eas-sdk@0.28.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(typescript@5.1.6): resolution: {integrity: sha512-Z197jE5oi8Eh9SmjldTnkPKKhOId2NA9OyEFvbXDMafoHtfC6V117r0GHj9IlsOGtaK8Y0fiZYX1EKMKcJb6UQ==} dependencies: - '@ethereum-attestation-service/eas-contracts': 0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(ts-node@10.9.1)(typescript@4.9.5) + '@ethereum-attestation-service/eas-contracts': 0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.1.6) ethers: 5.7.2 multiformats: 9.9.0 transitivePeerDependencies: @@ -5228,15 +5179,17 @@ packages: - utf-8-validate dev: false - /@ethereum-attestation-service/eas-sdk@0.28.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(typescript@5.1.6): - resolution: {integrity: sha512-Z197jE5oi8Eh9SmjldTnkPKKhOId2NA9OyEFvbXDMafoHtfC6V117r0GHj9IlsOGtaK8Y0fiZYX1EKMKcJb6UQ==} + /@ethereum-attestation-service/eas-sdk@1.2.2-beta.0(ts-node@10.9.1)(typescript@5.1.6): + resolution: {integrity: sha512-penkXiCKvHY8jN9UVV3B9IX001YnwWCNjbrBNE5e8Wy1rAzcPv7tqTBuvqXzjqmHfcASv7UFOIbfPEc5hd9mpA==} dependencies: - '@ethereum-attestation-service/eas-contracts': 0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.1.6) - ethers: 5.7.2 + '@ethereum-attestation-service/eas-contracts': 1.2.0-beta.1(ts-node@10.9.1)(typescript@5.1.6) + ethers: 6.8.0 + js-base64: 3.7.5 + lodash: 4.17.21 multiformats: 9.9.0 + pako: 2.1.0 + semver: 7.5.4 transitivePeerDependencies: - - '@ethersproject/abi' - - '@ethersproject/providers' - bufferutil - supports-color - ts-node @@ -5248,7 +5201,7 @@ packages: resolution: {integrity: sha512-X5RepE7Dn8KQLFO7HHAAe+KeGaX/by14hn90wePGBhzL54tq4Y8JscZFu+/LCwCl6TnkAAy5ebiMoqJ37sFtWw==} engines: {node: '>=10.0'} peerDependencies: - ethers: ^5.7.2 + ethers: '*' dependencies: '@ethereum-waffle/provider': 4.0.5(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(ethers@5.7.2) debug: 4.3.4(supports-color@8.1.1) @@ -5260,24 +5213,24 @@ packages: - supports-color dev: true - /@ethereum-waffle/compiler@4.0.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(solc@0.8.15)(typechain@8.3.2)(typescript@4.9.5): + /@ethereum-waffle/compiler@4.0.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(solc@0.8.15)(typechain@8.3.2)(typescript@5.1.6): resolution: {integrity: sha512-5x5U52tSvEVJS6dpCeXXKvRKyf8GICDwiTwUvGD3/WD+DpvgvaoHOL82XqpTSUHgV3bBq6ma5/8gKUJUIAnJCw==} engines: {node: '>=10.0'} peerDependencies: - ethers: ^5.7.2 + ethers: '*' solc: '*' typechain: ^8.0.0 dependencies: '@resolver-engine/imports': 0.3.3 '@resolver-engine/imports-fs': 0.3.3 - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) + '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.1.6) '@types/mkdirp': 0.5.2 - '@types/node-fetch': 2.6.7 + '@types/node-fetch': 2.6.8 ethers: 5.7.2 mkdirp: 0.5.6 node-fetch: 2.7.0 solc: 0.8.15 - typechain: 8.3.2(typescript@4.9.5) + typechain: 8.3.2(typescript@5.1.6) transitivePeerDependencies: - '@ethersproject/abi' - '@ethersproject/providers' @@ -5292,7 +5245,7 @@ packages: peerDependencies: '@ensdomains/ens': ^0.4.4 '@ensdomains/resolver': ^0.2.4 - ethers: ^5.7.2 + ethers: '*' dependencies: '@ensdomains/ens': 0.4.5 '@ensdomains/resolver': 0.2.4 @@ -5303,7 +5256,7 @@ packages: resolution: {integrity: sha512-LwEj5SIuEe9/gnrXgtqIkWbk2g15imM/qcJcxpLyAkOj981tQxXmtV4XmQMZsdedEsZ/D/rbUAOtZbgwqgUwQA==} engines: {node: '>=10.0'} peerDependencies: - ethers: ^5.7.2 + ethers: '*' dependencies: ethers: 5.7.2 dev: true @@ -5312,7 +5265,7 @@ packages: resolution: {integrity: sha512-40uzfyzcrPh+Gbdzv89JJTMBlZwzya1YLDyim8mVbEqYLP5VRYWoGp0JMyaizgV3hMoUFRqJKVmIUw4v7r3hYw==} engines: {node: '>=10.0'} peerDependencies: - ethers: ^5.7.2 + ethers: '*' dependencies: '@ethereum-waffle/ens': 4.0.3(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(ethers@5.7.2) '@ganache/ethereum-options': 0.1.4 @@ -5353,7 +5306,7 @@ packages: resolution: {integrity: sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA==} dependencies: crc-32: 1.2.2 - ethereumjs-util: 7.1.3 + ethereumjs-util: 7.1.5 dev: true /@ethereumjs/common@2.6.5: @@ -5383,7 +5336,7 @@ packages: resolution: {integrity: sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw==} dependencies: '@ethereumjs/common': 2.6.0 - ethereumjs-util: 7.1.3 + ethereumjs-util: 7.1.5 dev: true /@ethereumjs/tx@3.5.2: @@ -5412,7 +5365,7 @@ packages: async-eventemitter: 0.2.4 core-js-pure: 3.33.1 debug: 2.6.9 - ethereumjs-util: 7.1.3 + ethereumjs-util: 7.1.5 functional-red-black-tree: 1.0.1 mcl-wasm: 0.7.9 merkle-patricia-tree: 4.2.4 @@ -5844,7 +5797,7 @@ packages: '@graphql-tools/delegate': ^9.0.32 '@graphql-tools/utils': ^9.2.1 '@graphql-tools/wrap': ^9.4.2 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) @@ -5862,7 +5815,7 @@ packages: '@graphql-tools/delegate': ^9.0.32 '@graphql-tools/utils': ^9.2.1 '@graphql-tools/wrap': ^9.4.2 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) @@ -5881,7 +5834,7 @@ packages: '@graphql-tools/delegate': ^9.0.32 || ^10.0.0 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 '@graphql-tools/wrap': ^9.4.2 || ^10.0.0 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) @@ -5899,7 +5852,7 @@ packages: '@graphql-tools/delegate': ^9.0.32 '@graphql-tools/utils': ^9.2.1 '@graphql-tools/wrap': ^9.4.2 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) @@ -5918,7 +5871,7 @@ packages: '@graphql-tools/delegate': ^9.0.32 || ^10.0.0 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 '@graphql-tools/wrap': ^9.4.2 || ^10.0.0 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) @@ -5934,7 +5887,7 @@ packages: peerDependencies: '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 '@graphql-tools/delegate': ^9.0.32 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -5951,7 +5904,7 @@ packages: peerDependencies: '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 '@graphql-tools/delegate': ^9.0.32 || ^10.0.0 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -5966,7 +5919,7 @@ packages: resolution: {integrity: sha512-Eim0fZ0AgukHt5770j/UYDxfrqJroOhDe8FfNKKN7mDVRoMBoCsNknH47i03fh4A/kE8R+J6Job/zEJZPTtKnQ==} peerDependencies: '@graphql-tools/delegate': ^9.0.32 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -5979,7 +5932,7 @@ packages: engines: {node: '>=16.0.0'} peerDependencies: '@graphql-tools/delegate': ^9.0.32 || ^10.0.0 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/utils': 10.0.7(graphql@16.8.1) @@ -5991,7 +5944,7 @@ packages: resolution: {integrity: sha512-PIi8rFibYZVup+0jb08399RmbGF1ZrqUe6RXzLtKZBT57OWIMWwsFvdJyUAdr8Y8f0rrMn6A+Oy4nP1lf3hc1g==} hasBin: true peerDependencies: - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) '@graphprotocol/client-auto-pagination': 1.1.18(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) @@ -6025,18 +5978,18 @@ packages: - utf-8-validate dev: false - /@graphprotocol/client-cli@3.0.0(@babel/core@7.23.2)(@envelop/core@4.0.3)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): + /@graphprotocol/client-cli@3.0.0(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@9.0.0)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): resolution: {integrity: sha512-hTISbOzKavlDifBNsR6JqQMfdYwY7++hflPy+c3WHRrZ4OMoxFmW7ZuvaP6LvgKdJV77O8w9dnT/uxeHs6a90g==} engines: {node: '>=16.0.0'} hasBin: true peerDependencies: - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@graphprotocol/client-add-source-name': 2.0.0(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) '@graphprotocol/client-auto-pagination': 2.0.0(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) '@graphprotocol/client-auto-type-merging': 2.0.0(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-block-tracking': 2.0.0(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) - '@graphprotocol/client-polling-live': 2.0.0(@envelop/core@4.0.3)(@graphql-tools/merge@9.0.0)(graphql@16.8.1) + '@graphprotocol/client-polling-live': 2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@9.0.0)(graphql@16.8.1) '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2) graphql: 16.8.1 @@ -6069,7 +6022,7 @@ packages: peerDependencies: '@envelop/core': ^2.4.2 || ^3.0.0 '@graphql-tools/merge': ^8.3.14 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@envelop/core': 3.0.6 '@graphql-tools/merge': 8.4.2(graphql@16.8.1) @@ -6084,7 +6037,7 @@ packages: peerDependencies: '@envelop/core': ^2.4.2 || ^3.0.0 || ^4.0.0 '@graphql-tools/merge': ^8.3.14 || ^9.0.0 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@envelop/core': 3.0.6 '@graphql-tools/merge': 8.4.2(graphql@16.8.1) @@ -6093,15 +6046,15 @@ packages: tslib: 2.6.2 dev: false - /@graphprotocol/client-polling-live@2.0.0(@envelop/core@4.0.3)(@graphql-tools/merge@9.0.0)(graphql@16.8.1): + /@graphprotocol/client-polling-live@2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@9.0.0)(graphql@16.8.1): resolution: {integrity: sha512-JQ0sKiFCX+ErR0fynBNUg/WDiVaaEndlS12fkgrFZrQA2vVpSyow9pW0nKMGVZJa4cN+VDskgwqK5BWXMvdeRA==} engines: {node: '>=16.0.0'} peerDependencies: '@envelop/core': ^2.4.2 || ^3.0.0 || ^4.0.0 '@graphql-tools/merge': ^8.3.14 || ^9.0.0 - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: - '@envelop/core': 4.0.3 + '@envelop/core': 3.0.6 '@graphql-tools/merge': 9.0.0(graphql@16.8.1) '@repeaterjs/repeater': 3.0.4 graphql: 16.8.1 @@ -6127,7 +6080,7 @@ packages: fs-extra: 9.1.0 glob: 9.3.5 gluegun: 5.1.2(debug@4.3.4) - graphql: 16.8.1 + graphql: 15.5.0 immutable: 4.2.1 ipfs-http-client: 55.0.0(node-fetch@3.3.2) jayson: 4.0.0 @@ -6161,7 +6114,7 @@ packages: /@graphql-codegen/core@3.1.0(graphql@16.8.1): resolution: {integrity: sha512-DH1/yaR7oJE6/B+c6ZF2Tbdh7LixF1K8L+8BoSubjNyQ8pNwR4a70mvc1sv6H7qgp6y1bPQ9tKE+aazRRshysw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) '@graphql-tools/schema': 9.0.19(graphql@16.8.1) @@ -6172,7 +6125,7 @@ packages: /@graphql-codegen/plugin-helpers@2.7.2(graphql@16.8.1): resolution: {integrity: sha512-kln2AZ12uii6U59OQXdjLk5nOlh1pHis1R98cDZGFnfaiAbX9V3fxcZ1MMJkB7qFUymTALzyjZoXXdyVmPMfRg==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-tools/utils': 8.13.1(graphql@16.8.1) change-case-all: 1.0.14 @@ -6185,7 +6138,7 @@ packages: /@graphql-codegen/plugin-helpers@3.1.2(graphql@16.8.1): resolution: {integrity: sha512-emOQiHyIliVOIjKVKdsI5MXj312zmRDwmHpyUTZMjfpvxq/UVAHUJIVdVf+lnjjrI+LXBTgMlTWTgHQfmICxjg==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) change-case-all: 1.0.15 @@ -6198,7 +6151,7 @@ packages: /@graphql-codegen/plugin-helpers@4.2.0(graphql@16.8.1): resolution: {integrity: sha512-THFTCfg+46PXlXobYJ/OoCX6pzjI+9woQqCjdyKtgoI0tn3Xq2HUUCiidndxUpEYVrXb5pRiRXb7b/ZbMQqD0A==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) change-case-all: 1.0.15 @@ -6211,7 +6164,7 @@ packages: /@graphql-codegen/schema-ast@3.0.1(graphql@16.8.1): resolution: {integrity: sha512-rTKTi4XiW4QFZnrEqetpiYEWVsOFNoiR/v3rY9mFSttXFbIwNXPme32EspTiGWmEEdHY8UuTDtZN3vEcs/31zw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -6221,7 +6174,7 @@ packages: /@graphql-codegen/typed-document-node@4.0.1(graphql@16.8.1): resolution: {integrity: sha512-mQNYCd12JsFSaK6xLry4olY9TdYG7GxQPexU6qU4Om++eKhseGwk2eGmQDRG4Qp8jEDFLMXuHMVUKqMQ1M+F/A==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) '@graphql-codegen/visitor-plugin-common': 3.1.1(graphql@16.8.1) @@ -6236,7 +6189,7 @@ packages: /@graphql-codegen/typescript-generic-sdk@3.1.0(graphql-tag@2.12.6)(graphql@16.8.1): resolution: {integrity: sha512-nQZi/YGRI1+qCZZsh0V5nz6+hCHSN4OU9tKyOTDsEPyDFnGEukDuRdCH2IZasGn22a3Iu5TUDkgp5w9wEQwGmg==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 graphql-tag: ^2.0.0 dependencies: '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.8.1) @@ -6252,7 +6205,7 @@ packages: /@graphql-codegen/typescript-operations@3.0.4(graphql@16.8.1): resolution: {integrity: sha512-6yE2OL2+WJ1vd5MwFEGXpaxsFGzjAGUytPVHDML3Bi3TwP1F3lnQlIko4untwvHW0JhZEGQ7Ck30H9HjcxpdKA==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) '@graphql-codegen/typescript': 3.0.4(graphql@16.8.1) @@ -6267,7 +6220,7 @@ packages: /@graphql-codegen/typescript-resolvers@3.2.1(graphql@16.8.1): resolution: {integrity: sha512-2ZIHk5J6HTuylse5ZIxw+aega54prHxvj7vM8hiKJ6vejZ94kvVPAq4aWmSFOkZ5lqU3YnM/ZyWfnhT5CUDj1g==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) '@graphql-codegen/typescript': 3.0.4(graphql@16.8.1) @@ -6283,7 +6236,7 @@ packages: /@graphql-codegen/typescript@3.0.4(graphql@16.8.1): resolution: {integrity: sha512-x4O47447DZrWNtE/l5CU9QzzW4m1RbmCEdijlA3s2flG/y1Ckqdemob4CWfilSm5/tZ3w1junVDY616RDTSvZw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) '@graphql-codegen/schema-ast': 3.0.1(graphql@16.8.1) @@ -6298,7 +6251,7 @@ packages: /@graphql-codegen/visitor-plugin-common@2.13.1(graphql@16.8.1): resolution: {integrity: sha512-mD9ufZhDGhyrSaWQGrU1Q1c5f01TeWtSWy/cDwXYjJcHIj1Y/DG2x0tOflEfCvh5WcnmHNIw4lzDsg1W7iFJEg==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-codegen/plugin-helpers': 2.7.2(graphql@16.8.1) '@graphql-tools/optimize': 1.4.0(graphql@16.8.1) @@ -6318,7 +6271,7 @@ packages: /@graphql-codegen/visitor-plugin-common@3.1.1(graphql@16.8.1): resolution: {integrity: sha512-uAfp+zu/009R3HUAuTK2AamR1bxIltM6rrYYI6EXSmkM3rFtFsLTuJhjUDj98HcUCszJZrADppz8KKLGRUVlNg==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: '@graphql-codegen/plugin-helpers': 4.2.0(graphql@16.8.1) '@graphql-tools/optimize': 1.4.0(graphql@16.8.1) @@ -6338,7 +6291,7 @@ packages: /@graphql-inspector/core@3.3.0(graphql@16.8.1): resolution: {integrity: sha512-LRtk9sHgj9qqVPIkkThAVq3iZ7QxgHCx6elEwd0eesZBCmaIYQxD/BFu+VT8jr10YfOURBZuAnVdyGu64vYpBg==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: dependency-graph: 0.11.0 graphql: 16.8.1 @@ -6349,7 +6302,7 @@ packages: resolution: {integrity: sha512-1CWfFYucnRdULGiN1NDSinlNlpucBT+0x4i4AIthKe5n5jD9RIVyJtkA8zBbujUFrP++YE3l+TQifwbN1yTQsw==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: dependency-graph: 0.11.0 graphql: 16.8.1 @@ -6361,7 +6314,7 @@ packages: peerDependencies: '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6376,7 +6329,7 @@ packages: peerDependencies: '@graphql-mesh/types': ^0.95.8 '@graphql-mesh/utils': ^0.95.8 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6390,7 +6343,7 @@ packages: resolution: {integrity: sha512-5IuXpk+Zpg05u6qNPX19VzC5/HCiLdDRF6EPZ3ze57FIRgGA3YsB1CUGga6Ky3inalURYwx0kWqmdjbdKZYx1w==} hasBin: true peerDependencies: - graphql: ^16.6.0 + graphql: '*' dependencies: '@graphql-codegen/core': 3.1.0(graphql@16.8.1) '@graphql-codegen/typed-document-node': 4.0.1(graphql@16.8.1) @@ -6448,7 +6401,7 @@ packages: '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 '@graphql-tools/utils': ^9.2.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@envelop/core': 3.0.6 @@ -6478,7 +6431,7 @@ packages: resolution: {integrity: sha512-jseNppSNEwNWjcjDDwsxmRBK+ub8tz2qc/ca2ZfCTebuCk/+D3dI3LJ95ceNFOIhInK0g2HVq8BO8lMMX1pQtg==} peerDependencies: '@graphql-tools/utils': ^9.2.1 - graphql: ^16.6.0 + graphql: '*' dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) graphql: 16.8.1 @@ -6494,7 +6447,7 @@ packages: engines: {node: '>=16.0.0'} peerDependencies: '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: ^16.6.0 + graphql: '*' dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) graphql: 16.8.1 @@ -6508,7 +6461,7 @@ packages: '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 '@graphql-tools/utils': ^9.2.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) @@ -6538,7 +6491,7 @@ packages: '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 '@graphql-tools/utils': ^9.2.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) @@ -6569,7 +6522,7 @@ packages: '@graphql-mesh/types': ^0.95.8 '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) @@ -6602,7 +6555,7 @@ packages: '@graphql-mesh/runtime': ^0.93.2 '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) @@ -6622,7 +6575,7 @@ packages: '@graphql-mesh/runtime': ^0.96.13 '@graphql-mesh/types': ^0.95.8 '@graphql-mesh/utils': ^0.95.8 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) @@ -6641,7 +6594,7 @@ packages: '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 '@graphql-tools/utils': ^9.2.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/merger-stitching': 0.93.1(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6661,7 +6614,7 @@ packages: '@graphql-mesh/types': ^0.95.8 '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/merger-stitching': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6682,7 +6635,7 @@ packages: '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 '@graphql-tools/utils': ^9.2.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6704,7 +6657,7 @@ packages: '@graphql-mesh/types': ^0.95.8 '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6725,7 +6678,7 @@ packages: '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 '@graphql-tools/utils': ^9.2.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@envelop/core': 3.0.6 @@ -6751,7 +6704,7 @@ packages: '@graphql-mesh/types': ^0.95.8 '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@envelop/core': 5.0.0 @@ -6780,7 +6733,7 @@ packages: '@graphql-mesh/types': ^0.95.8 '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@envelop/core': 5.0.0 @@ -6808,7 +6761,7 @@ packages: '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 '@graphql-tools/utils': ^9.2.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-inspector/core': 3.3.0(graphql@16.8.1) @@ -6827,7 +6780,7 @@ packages: '@graphql-mesh/types': ^0.95.8 '@graphql-mesh/utils': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-inspector/core': 5.0.1(graphql@16.8.1) @@ -6841,7 +6794,7 @@ packages: /@graphql-mesh/string-interpolation@0.4.4(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-IotswBYZRaPswOebcr2wuOFuzD3dHIJxVEkPiiQubqjUIR8HhQI22XHJv0WNiQZ65z8NR9+GYWwEDIc2JRCNfQ==} peerDependencies: - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: dayjs: 1.11.7 @@ -6854,7 +6807,7 @@ packages: resolution: {integrity: sha512-/R4kj3M1uqUie/7RZ58zgRrT8RBrDsCCR6ii00s62DbLsl+jZYOZFyTqHGsFbP7L7aHnl0fo1dwhEJIs+rjCLg==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: dayjs: 1.11.10 @@ -6868,7 +6821,7 @@ packages: peerDependencies: '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6884,7 +6837,7 @@ packages: peerDependencies: '@graphql-mesh/types': ^0.93.1 '@graphql-mesh/utils': ^0.93.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6900,7 +6853,7 @@ packages: peerDependencies: '@graphql-mesh/store': ^0.93.1 '@graphql-tools/utils': ^9.2.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6917,7 +6870,7 @@ packages: peerDependencies: '@graphql-mesh/store': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) @@ -6934,7 +6887,7 @@ packages: '@graphql-mesh/cross-helpers': ^0.3.4 '@graphql-mesh/types': ^0.93.2 '@graphql-tools/utils': ^9.2.1 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) @@ -6957,7 +6910,7 @@ packages: '@graphql-mesh/cross-helpers': ^0.4.1 '@graphql-mesh/types': ^0.95.8 '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: ^16.6.0 + graphql: '*' tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.4.1(@graphql-tools/utils@9.2.1)(graphql@16.8.1) @@ -6977,7 +6930,7 @@ packages: /@graphql-tools/batch-delegate@8.4.27(graphql@16.8.1): resolution: {integrity: sha512-efgDDJhljma9d3Ky/LswIu1xm/if2oS27XA1sOcxcShW+Ze+Qxi0hZZ6iyI4eQxVDX5Lyy/n+NvQEZAK1riqnQ==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -6990,7 +6943,7 @@ packages: resolution: {integrity: sha512-23NmxcHQeKcfhMQyrRPTZfW4/+bSpAyR/qAhRjx+/hikDIa1Uv2XVgV9jIitSgM0OEk/KGPB4VQv+LCOWvAYiw==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/utils': 10.0.7(graphql@16.8.1) @@ -7002,7 +6955,7 @@ packages: /@graphql-tools/batch-execute@8.5.22(graphql@16.8.1): resolution: {integrity: sha512-hcV1JaY6NJQFQEwCKrYhpfLK8frSXDbtNMoTur98u10Cmecy1zrqNKSqhEyGetpgHxaJRqszGzKeI3RuroDN6A==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) dataloader: 2.2.2 @@ -7014,7 +6967,7 @@ packages: resolution: {integrity: sha512-Y2uwdZI6ZnatopD/SYfZ1eGuQFI7OU2KGZ2/B/7G9ISmgMl5K+ZZWz/PfIEXeiHirIDhyk54s4uka5rj2xwKqQ==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 10.0.7(graphql@16.8.1) dataloader: 2.2.2 @@ -7025,7 +6978,7 @@ packages: /@graphql-tools/code-file-loader@7.3.23(@babel/core@7.23.2)(graphql@16.8.1): resolution: {integrity: sha512-8Wt1rTtyTEs0p47uzsPJ1vAtfAx0jmxPifiNdmo9EOCuUPyQGEbMaik/YkqZ7QUFIEYEQu+Vgfo8tElwOPtx5Q==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/graphql-tag-pluck': 7.5.2(@babel/core@7.23.2)(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -7041,7 +6994,7 @@ packages: resolution: {integrity: sha512-Jor9oazZ07zuWkykD3OOhT/2XD74Zm6Ar0ENZMk75MDD51wB2UWUIMljtHxbJhV5A6UBC2v8x6iY0xdCGiIlyw==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/batch-execute': 9.0.2(graphql@16.8.1) '@graphql-tools/executor': 1.2.0(graphql@16.8.1) @@ -7054,7 +7007,7 @@ packages: /@graphql-tools/delegate@9.0.35(graphql@16.8.1): resolution: {integrity: sha512-jwPu8NJbzRRMqi4Vp/5QX1vIUeUPpWmlQpOkXQD2r1X45YsVceyUUBnktCrlJlDB4jPRVy7JQGwmYo3KFiOBMA==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/batch-execute': 8.5.22(graphql@16.8.1) '@graphql-tools/executor': 0.0.20(graphql@16.8.1) @@ -7068,7 +7021,7 @@ packages: /@graphql-tools/executor-graphql-ws@0.0.14(graphql@16.8.1): resolution: {integrity: sha512-P2nlkAsPZKLIXImFhj0YTtny5NQVGSsKnhi7PzXiaHSXc6KkzqbWZHKvikD4PObanqg+7IO58rKFpGXP7eeO+w==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@repeaterjs/repeater': 3.0.4 @@ -7086,7 +7039,7 @@ packages: resolution: {integrity: sha512-yM67SzwE8rYRpm4z4AuGtABlOp9mXXVy6sxXnTJRoYIdZrmDbKVfIY+CpZUJCqS0FX3xf2+GoHlsj7Qswaxgcg==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 10.0.7(graphql@16.8.1) '@types/ws': 8.5.8 @@ -7103,7 +7056,7 @@ packages: /@graphql-tools/executor-http@0.1.10(@types/node@18.18.7)(graphql@16.8.1): resolution: {integrity: sha512-hnAfbKv0/lb9s31LhWzawQ5hghBfHS+gYWtqxME6Rl0Aufq9GltiiLBcl7OVVOnkLF0KhwgbYP1mB5VKmgTGpg==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@repeaterjs/repeater': 3.0.4 @@ -7121,7 +7074,7 @@ packages: resolution: {integrity: sha512-5WZIMBevRaxMabZ8U2Ty0dTUPy/PpeYSlMNEmC/YJjKKykgSfc/AwSejx2sE4FFKZ0I2kxRKRenyoWMHRAV49Q==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 10.0.7(graphql@16.8.1) '@repeaterjs/repeater': 3.0.4 @@ -7138,7 +7091,7 @@ packages: /@graphql-tools/executor-legacy-ws@0.0.11(graphql@16.8.1): resolution: {integrity: sha512-4ai+NnxlNfvIQ4c70hWFvOZlSUN8lt7yc+ZsrwtNFbFPH/EroIzFMapAxM9zwyv9bH38AdO3TQxZ5zNxgBdvUw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@types/ws': 8.5.8 @@ -7154,7 +7107,7 @@ packages: resolution: {integrity: sha512-b7aGuRekZDS+m3af3BIvMKxu15bmVPMt5eGQVuP2v5pxmbaPTh+iv5mx9b3Plt32z5Ke5tycBnNm5urSFtW8ng==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 10.0.7(graphql@16.8.1) '@types/ws': 8.5.8 @@ -7170,7 +7123,7 @@ packages: /@graphql-tools/executor@0.0.18(graphql@16.8.1): resolution: {integrity: sha512-xZC0C+/npXoSHBB5bsJdwxDLgtl1Gu4fL9J2TPQmXoZC3L2N506KJoppf9LgWdHU/xK04luJrhP6WjhfkIN0pQ==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) @@ -7182,7 +7135,7 @@ packages: /@graphql-tools/executor@0.0.20(graphql@16.8.1): resolution: {integrity: sha512-GdvNc4vszmfeGvUqlcaH1FjBoguvMYzxAfT6tDd4/LgwymepHhinqLNA5otqwVLW+JETcDaK7xGENzFomuE6TA==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) @@ -7195,7 +7148,7 @@ packages: resolution: {integrity: sha512-SKlIcMA71Dha5JnEWlw4XxcaJ+YupuXg0QCZgl2TOLFz4SkGCwU/geAsJvUJFwK2RbVLpQv/UMq67lOaBuwDtg==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 10.0.7(graphql@16.8.1) '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) @@ -7208,7 +7161,7 @@ packages: resolution: {integrity: sha512-H51qTYwbtfIYBO1uHXlImRWzo9tknSoIGBgJckDh+hdxJx43sZaMjJiLHc2DjRc/A8d2Bf0bi0HbH++HqOos/w==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/executor-http': 1.0.3(@types/node@18.18.7)(graphql@16.8.1) @@ -7233,7 +7186,7 @@ packages: /@graphql-tools/graphql-file-loader@7.5.17(graphql@16.8.1): resolution: {integrity: sha512-hVwwxPf41zOYgm4gdaZILCYnKB9Zap7Ys9OhY1hbwuAuC4MMNY9GpUjoTU3CQc3zUiPoYStyRtUGkHSJZ3HxBw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/import': 6.7.18(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -7245,7 +7198,7 @@ packages: /@graphql-tools/graphql-tag-pluck@7.5.2(@babel/core@7.23.2)(graphql@16.8.1): resolution: {integrity: sha512-RW+H8FqOOLQw0BPXaahYepVSRjuOHw+7IL8Opaa5G5uYGOBxoXR7DceyQ7BcpMgktAOOmpDNQ2WtcboChOJSRA==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@babel/parser': 7.23.0 '@babel/plugin-syntax-import-assertions': 7.22.5(@babel/core@7.23.2) @@ -7261,7 +7214,7 @@ packages: /@graphql-tools/import@6.7.18(graphql@16.8.1): resolution: {integrity: sha512-XQDdyZTp+FYmT7as3xRWH/x8dx0QZA2WZqfMF5EWb36a0PiH7WwlRQYIdyYXj8YCLpiWkeBXgBRHmMnwEYR8iQ==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) graphql: 16.8.1 @@ -7271,7 +7224,7 @@ packages: /@graphql-tools/load@7.8.14(graphql@16.8.1): resolution: {integrity: sha512-ASQvP+snHMYm+FhIaLxxFgVdRaM0vrN9wW2BKInQpktwWTXVyk+yP5nQUCEGmn0RTdlPKrffBaigxepkEAJPrg==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/schema': 9.0.19(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -7282,7 +7235,7 @@ packages: /@graphql-tools/merge@8.4.2(graphql@16.8.1): resolution: {integrity: sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.8.1) graphql: 16.8.1 @@ -7292,7 +7245,7 @@ packages: resolution: {integrity: sha512-J7/xqjkGTTwOJmaJQJ2C+VDBDOWJL3lKrHJN4yMaRLAJH3PosB7GiPRaSDZdErs0+F77sH2MKs2haMMkywzx7Q==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/utils': 10.0.7(graphql@16.8.1) graphql: 16.8.1 @@ -7301,7 +7254,7 @@ packages: /@graphql-tools/optimize@1.4.0(graphql@16.8.1): resolution: {integrity: sha512-dJs/2XvZp+wgHH8T5J2TqptT9/6uVzIYvA6uFACha+ufvdMBedkfR4b4GbT8jAKLRARiqRTxy3dctnwkTM2tdw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: graphql: 16.8.1 tslib: 2.6.2 @@ -7309,7 +7262,7 @@ packages: /@graphql-tools/relay-operation-optimizer@6.5.18(graphql@16.8.1): resolution: {integrity: sha512-mc5VPyTeV+LwiM+DNvoDQfPqwQYhPV/cl5jOBjTgSniyaq8/86aODfMkrE2OduhQ5E00hqrkuL2Fdrgk0w1QJg==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@ardatan/relay-compiler': 12.0.0(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -7323,7 +7276,7 @@ packages: resolution: {integrity: sha512-kf3qOXMFcMs2f/S8Y3A8fm/2w+GaHAkfr3Gnhh2LOug/JgpY/ywgFVxO3jOeSpSEdoYcDKLcXVjMigNbY4AdQg==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/merge': 9.0.0(graphql@16.8.1) '@graphql-tools/utils': 10.0.7(graphql@16.8.1) @@ -7334,7 +7287,7 @@ packages: /@graphql-tools/schema@9.0.19(graphql@16.8.1): resolution: {integrity: sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/merge': 8.4.2(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -7345,7 +7298,7 @@ packages: /@graphql-tools/stitch@8.7.50(graphql@16.8.1): resolution: {integrity: sha512-VB1/uZyXjj1P5Wj0c4EKX3q8Q1Maj4dy6uNwodEPaO3EHMpaJU/DqyN0Bvnhxu0ol7RzdY3kgsvsdUjU2QMImw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/batch-delegate': 8.4.27(graphql@16.8.1) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) @@ -7362,7 +7315,7 @@ packages: resolution: {integrity: sha512-G03XahiHDu1pnaS8z2GNfsV/5BribMEUATT5dCHBAqj13Te5y1amZNQePrmw8DLtbf5qDbU6CO7kGHPxv0XO9A==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/batch-delegate': 9.0.0(graphql@16.8.1) '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) @@ -7379,7 +7332,7 @@ packages: /@graphql-tools/stitching-directives@2.3.34(graphql@16.8.1): resolution: {integrity: sha512-DVlo1/SW9jN6jN1IL279c7voEJiEHsLbYRD7tYsAW472zrHqn0rpB6jRzZDzLOlCpm7JRWPsegXVlkqf0qvqFQ==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -7389,7 +7342,7 @@ packages: /@graphql-tools/url-loader@7.17.18(@types/node@18.18.7)(graphql@16.8.1): resolution: {integrity: sha512-ear0CiyTj04jCVAxi7TvgbnGDIN2HgqzXzwsfcqiVg9cvjT40NcMlZ2P1lZDgqMkZ9oyLTV8Bw6j+SyG6A+xPw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@ardatan/sync-fetch': 0.0.1 '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) @@ -7415,7 +7368,7 @@ packages: resolution: {integrity: sha512-rPc9oDzMnycvz+X+wrN3PLrhMBQkG4+sd8EzaFN6dypcssiefgWKToXtRKI8HHK68n2xEq1PyrOpkjHFJB+GwA==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@ardatan/sync-fetch': 0.0.1 '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) @@ -7442,7 +7395,7 @@ packages: resolution: {integrity: sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) dset: 3.1.3 @@ -7452,7 +7405,7 @@ packages: /@graphql-tools/utils@8.13.1(graphql@16.8.1): resolution: {integrity: sha512-qIh9yYpdUFmctVqovwMdheVNJqFh+DQNWIhX87FJStfXYnmweBUDATok9fWPleKeFwxnW8IapKmY8m8toJEkAw==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: graphql: 16.8.1 tslib: 2.6.2 @@ -7460,7 +7413,7 @@ packages: /@graphql-tools/utils@9.2.1(graphql@16.8.1): resolution: {integrity: sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) graphql: 16.8.1 @@ -7470,7 +7423,7 @@ packages: resolution: {integrity: sha512-Cw6hVrKGM2OKBXeuAGltgy4tzuqQE0Nt7t/uAqnuokSXZhMHXJUb124Bnvxc2gPZn5chfJSDafDe4Cp8ZAVJgg==} engines: {node: '>=16.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/schema': 10.0.0(graphql@16.8.1) @@ -7483,7 +7436,7 @@ packages: /@graphql-tools/wrap@9.4.2(graphql@16.8.1): resolution: {integrity: sha512-DFcd9r51lmcEKn0JW43CWkkI2D6T9XI1juW/Yo86i04v43O9w2/k4/nx2XTJv4Yv+iXwUw7Ok81PGltwGJSDSA==} peerDependencies: - graphql: ^16.6.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/schema': 9.0.19(graphql@16.8.1) @@ -7495,7 +7448,7 @@ packages: /@graphql-typed-document-node/core@3.2.0(graphql@16.8.1): resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: graphql: 16.8.1 @@ -9661,7 +9614,6 @@ packages: resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} dependencies: '@noble/hashes': 1.3.2 - dev: false /@noble/ed25519@1.7.3: resolution: {integrity: sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==} @@ -9681,7 +9633,6 @@ packages: /@noble/hashes@1.3.2: resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} engines: {node: '>= 16'} - dev: false /@noble/secp256k1@1.7.1: resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} @@ -9718,6 +9669,22 @@ packages: transitivePeerDependencies: - bufferutil - utf-8-validate + dev: false + + /@nomicfoundation/ethereumjs-block@5.0.2: + resolution: {integrity: sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q==} + engines: {node: '>=14'} + dependencies: + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-trie': 6.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + ethereum-cryptography: 0.1.3 + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate /@nomicfoundation/ethereumjs-blockchain@7.0.0: resolution: {integrity: sha512-cVRCrXZminZr0Mbx2hm0/109GZLn1v5bf0/k+SIbGn50yZm6YCdQt9CgGT0Gk56N2vy8NhXD4apo167m4LWk6Q==} @@ -9740,12 +9707,42 @@ packages: - bufferutil - supports-color - utf-8-validate + dev: false + + /@nomicfoundation/ethereumjs-blockchain@7.0.2: + resolution: {integrity: sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w==} + engines: {node: '>=14'} + dependencies: + '@nomicfoundation/ethereumjs-block': 5.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-ethash': 3.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-trie': 6.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + abstract-level: 1.0.3 + debug: 4.3.4(supports-color@8.1.1) + ethereum-cryptography: 0.1.3 + level: 8.0.0 + lru-cache: 5.1.1 + memory-level: 1.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate /@nomicfoundation/ethereumjs-common@4.0.0: resolution: {integrity: sha512-UPpm5FAGAf2B6hQ8aVgO44Rdo0k73oMMCViqNJcKMlk1s9l3rxwuPTp1l20NiGvNO2Pzqk3chFL+BzmLL2g4wQ==} dependencies: '@nomicfoundation/ethereumjs-util': 9.0.0 crc-32: 1.2.2 + dev: false + + /@nomicfoundation/ethereumjs-common@4.0.2: + resolution: {integrity: sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg==} + dependencies: + '@nomicfoundation/ethereumjs-util': 9.0.2 + crc-32: 1.2.2 /@nomicfoundation/ethereumjs-ethash@3.0.0: resolution: {integrity: sha512-6zNv5Y3vNIsxjrsbKjMInVpo8cmR0c7yjZbBpy7NYuIMtm0JKhQoXsiFN56t/1sfn9V3v0wgrkAixo5v6bahpA==} @@ -9760,6 +9757,21 @@ packages: transitivePeerDependencies: - bufferutil - utf-8-validate + dev: false + + /@nomicfoundation/ethereumjs-ethash@3.0.2: + resolution: {integrity: sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg==} + engines: {node: '>=14'} + dependencies: + '@nomicfoundation/ethereumjs-block': 5.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + abstract-level: 1.0.3 + bigint-crypto-utils: 3.3.0 + ethereum-cryptography: 0.1.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate /@nomicfoundation/ethereumjs-evm@2.0.0: resolution: {integrity: sha512-D+tr3M9sictopr3E20OVgme7YF/d0fU566WKh+ofXwmxapz/Dd8RSLSaVeKgfCI2BkzVA+XqXY08NNCV8w8fWA==} @@ -9777,11 +9789,35 @@ packages: - bufferutil - supports-color - utf-8-validate + dev: false + + /@nomicfoundation/ethereumjs-evm@2.0.2: + resolution: {integrity: sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ==} + engines: {node: '>=14'} + dependencies: + '@ethersproject/providers': 5.7.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + debug: 4.3.4(supports-color@8.1.1) + ethereum-cryptography: 0.1.3 + mcl-wasm: 0.7.9 + rustbn.js: 0.2.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate /@nomicfoundation/ethereumjs-rlp@5.0.0: resolution: {integrity: sha512-U1A0y330PtGb8Wft4yPVv0myWYJTesi89ItGoB0ICdqz7793KmUhpfQb2vJUXBi98wSdnxkIABO/GmsQvGKVDw==} engines: {node: '>=14'} hasBin: true + dev: false + + /@nomicfoundation/ethereumjs-rlp@5.0.2: + resolution: {integrity: sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA==} + engines: {node: '>=14'} + hasBin: true /@nomicfoundation/ethereumjs-statemanager@2.0.0: resolution: {integrity: sha512-tgXtsx8yIDlxWMN+ThqPtGK0ITAuITrDy+GYIgGrnT6ZtelvXWM7SUYR0Mcv578lmGCoIwyHFtSBqOkOBYHLjw==} @@ -9796,6 +9832,21 @@ packages: - bufferutil - supports-color - utf-8-validate + dev: false + + /@nomicfoundation/ethereumjs-statemanager@2.0.2: + resolution: {integrity: sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA==} + dependencies: + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + debug: 4.3.4(supports-color@8.1.1) + ethereum-cryptography: 0.1.3 + ethers: 5.7.2 + js-sdsl: 4.4.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate /@nomicfoundation/ethereumjs-trie@6.0.0: resolution: {integrity: sha512-YqPWiNxrZvL+Ef7KHqgru1IlaIGXhu78wd2fxNFOvi/NAQBF845dVfTKKXs1L9x0QBRRQRephgxHCKMuISGppw==} @@ -9806,6 +9857,17 @@ packages: '@types/readable-stream': 2.3.15 ethereum-cryptography: 0.1.3 readable-stream: 3.6.2 + dev: false + + /@nomicfoundation/ethereumjs-trie@6.0.2: + resolution: {integrity: sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ==} + engines: {node: '>=14'} + dependencies: + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + '@types/readable-stream': 2.3.15 + ethereum-cryptography: 0.1.3 + readable-stream: 3.6.2 /@nomicfoundation/ethereumjs-tx@5.0.0: resolution: {integrity: sha512-LTyxI+zBJ+HuEBblUGbxvfKl1hg1uJlz2XhnszNagiBWQSgLb1vQCa1QaXV5Q8cUDYkr/Xe4NXWiUGEvH4e6lA==} @@ -9820,6 +9882,21 @@ packages: transitivePeerDependencies: - bufferutil - utf-8-validate + dev: false + + /@nomicfoundation/ethereumjs-tx@5.0.2: + resolution: {integrity: sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g==} + engines: {node: '>=14'} + dependencies: + '@chainsafe/ssz': 0.9.4 + '@ethersproject/providers': 5.7.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + ethereum-cryptography: 0.1.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate /@nomicfoundation/ethereumjs-util@9.0.0: resolution: {integrity: sha512-9EG98CsEC9BnI7AY27F4QXZ8Vf0re8R9XoxQ0//KWF+B7quu6GQvgTq1RlNUjGh/XNCCJNf8E3LOY9ULR85wFQ==} @@ -9828,6 +9905,15 @@ packages: '@chainsafe/ssz': 0.10.2 '@nomicfoundation/ethereumjs-rlp': 5.0.0 ethereum-cryptography: 0.1.3 + dev: false + + /@nomicfoundation/ethereumjs-util@9.0.2: + resolution: {integrity: sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ==} + engines: {node: '>=14'} + dependencies: + '@chainsafe/ssz': 0.10.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + ethereum-cryptography: 0.1.3 /@nomicfoundation/ethereumjs-vm@7.0.0: resolution: {integrity: sha512-eHkEoe/4r4+g+fZyIIlQjBHEjCPFs8CHiIEEMvMfvFrV4hyHnuTg4LH7l92ok7TGZqpWxgMG2JOEUFkNsXrKuQ==} @@ -9850,79 +9936,130 @@ packages: - bufferutil - supports-color - utf-8-validate + dev: false - /@nomicfoundation/hardhat-chai-matchers@1.0.6(@nomiclabs/hardhat-ethers@2.2.3)(chai@4.3.10)(ethers@5.7.2)(hardhat@2.13.1): - resolution: {integrity: sha512-f5ZMNmabZeZegEfuxn/0kW+mm7+yV7VNDxLpMOMGXWFJ2l/Ct3QShujzDRF9cOkK9Ui/hbDeOWGZqyQALDXVCQ==} + /@nomicfoundation/ethereumjs-vm@7.0.2: + resolution: {integrity: sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA==} + engines: {node: '>=14'} + dependencies: + '@nomicfoundation/ethereumjs-block': 5.0.2 + '@nomicfoundation/ethereumjs-blockchain': 7.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-evm': 2.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-statemanager': 2.0.2 + '@nomicfoundation/ethereumjs-trie': 6.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + debug: 4.3.4(supports-color@8.1.1) + ethereum-cryptography: 0.1.3 + mcl-wasm: 0.7.9 + rustbn.js: 0.2.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + /@nomicfoundation/hardhat-chai-matchers@2.0.2(@nomicfoundation/hardhat-ethers@3.0.4)(chai@4.3.10)(ethers@6.8.0)(hardhat@2.18.3): + resolution: {integrity: sha512-9Wu9mRtkj0U9ohgXYFbB/RQDa+PcEdyBm2suyEtsJf3PqzZEEjLUZgWnMjlFhATMk/fp3BjmnYVPrwl+gr8oEw==} peerDependencies: - '@nomiclabs/hardhat-ethers': ^2.0.0 + '@nomicfoundation/hardhat-ethers': ^3.0.0 chai: ^4.2.0 - ethers: ^5.7.2 + ethers: ^6.1.0 hardhat: ^2.9.4 dependencies: - '@ethersproject/abi': 5.7.0 - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.13.1) + '@nomicfoundation/hardhat-ethers': 3.0.4(ethers@6.8.0)(hardhat@2.18.3) '@types/chai-as-promised': 7.1.7 chai: 4.3.10 chai-as-promised: 7.1.1(chai@4.3.10) deep-eql: 4.1.3 - ethers: 5.7.2 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + ethers: 6.8.0 + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) ordinal: 1.0.3 dev: true - /@nomicfoundation/hardhat-network-helpers@1.0.9(hardhat@2.13.1): + /@nomicfoundation/hardhat-ethers@3.0.4(ethers@6.8.0)(hardhat@2.18.3): + resolution: {integrity: sha512-k9qbLoY7qn6C6Y1LI0gk2kyHXil2Tauj4kGzQ8pgxYXIGw8lWn8tuuL72E11CrlKaXRUvOgF0EXrv/msPI2SbA==} + peerDependencies: + ethers: ^6.1.0 + hardhat: ^2.0.0 + dependencies: + debug: 4.3.4(supports-color@8.1.1) + ethers: 6.8.0 + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) + lodash.isequal: 4.5.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@nomicfoundation/hardhat-network-helpers@1.0.9(hardhat@2.18.3): resolution: {integrity: sha512-OXWCv0cHpwLUO2u7bFxBna6dQtCC2Gg/aN/KtJLO7gmuuA28vgmVKYFRCDUqrbjujzgfwQ2aKyZ9Y3vSmDqS7Q==} peerDependencies: hardhat: ^2.9.5 dependencies: ethereumjs-util: 7.1.5 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) dev: true - /@nomicfoundation/hardhat-toolbox@2.0.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-chai-matchers@1.0.6)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(@typechain/ethers-v5@11.1.2)(@typechain/hardhat@9.1.0)(@types/chai@4.3.9)(@types/mocha@9.1.0)(@types/node@18.18.7)(chai@4.3.10)(ethers@5.7.2)(hardhat-gas-reporter@1.0.9)(hardhat@2.13.1)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.2)(typescript@4.9.5): - resolution: {integrity: sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg==} + /@nomicfoundation/hardhat-toolbox@3.0.0(@nomicfoundation/hardhat-chai-matchers@2.0.2)(@nomicfoundation/hardhat-ethers@3.0.4)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomicfoundation/hardhat-verify@1.1.1)(@typechain/ethers-v6@0.4.3)(@typechain/hardhat@8.0.3)(@types/chai@4.3.9)(@types/mocha@9.1.0)(@types/node@18.18.7)(chai@4.3.10)(ethers@6.8.0)(hardhat-gas-reporter@1.0.9)(hardhat@2.18.3)(solidity-coverage@0.8.5)(ts-node@10.9.1)(typechain@8.3.2)(typescript@4.9.5): + resolution: {integrity: sha512-MsteDXd0UagMksqm9KvcFG6gNKYNa3GGNCy73iQ6bEasEgg2v8Qjl6XA5hjs8o5UD5A3153B6W2BIVJ8SxYUtA==} peerDependencies: - '@ethersproject/abi': ^5.4.7 - '@ethersproject/providers': ^5.4.7 - '@nomicfoundation/hardhat-chai-matchers': ^1.0.0 + '@nomicfoundation/hardhat-chai-matchers': ^2.0.0 + '@nomicfoundation/hardhat-ethers': ^3.0.0 '@nomicfoundation/hardhat-network-helpers': ^1.0.0 - '@nomiclabs/hardhat-ethers': ^2.0.0 - '@nomiclabs/hardhat-etherscan': ^3.0.0 - '@typechain/ethers-v5': ^10.1.0 - '@typechain/hardhat': ^6.1.2 + '@nomicfoundation/hardhat-verify': ^1.0.0 + '@typechain/ethers-v6': ^0.4.0 + '@typechain/hardhat': ^8.0.0 '@types/chai': ^4.2.0 '@types/mocha': '>=9.1.0' '@types/node': '>=12.0.0' chai: ^4.2.0 - ethers: ^5.7.2 + ethers: ^6.4.0 hardhat: ^2.11.0 hardhat-gas-reporter: ^1.0.8 solidity-coverage: ^0.8.1 ts-node: '>=8.0.0' - typechain: ^8.1.0 + typechain: ^8.2.0 typescript: '>=4.5.0' dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/providers': 5.7.2 - '@nomicfoundation/hardhat-chai-matchers': 1.0.6(@nomiclabs/hardhat-ethers@2.2.3)(chai@4.3.10)(ethers@5.7.2)(hardhat@2.13.1) - '@nomicfoundation/hardhat-network-helpers': 1.0.9(hardhat@2.13.1) - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.13.1) - '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.13.1) - '@typechain/ethers-v5': 11.1.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) - '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2) + '@nomicfoundation/hardhat-chai-matchers': 2.0.2(@nomicfoundation/hardhat-ethers@3.0.4)(chai@4.3.10)(ethers@6.8.0)(hardhat@2.18.3) + '@nomicfoundation/hardhat-ethers': 3.0.4(ethers@6.8.0)(hardhat@2.18.3) + '@nomicfoundation/hardhat-network-helpers': 1.0.9(hardhat@2.18.3) + '@nomicfoundation/hardhat-verify': 1.1.1(hardhat@2.18.3) + '@typechain/ethers-v6': 0.4.3(ethers@6.8.0)(typechain@8.3.2)(typescript@4.9.5) + '@typechain/hardhat': 8.0.3(@typechain/ethers-v6@0.4.3)(ethers@6.8.0)(hardhat@2.18.3)(typechain@8.3.2) '@types/chai': 4.3.9 '@types/mocha': 9.1.0 '@types/node': 18.18.7 chai: 4.3.10 - ethers: 5.7.2 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) - hardhat-gas-reporter: 1.0.9(hardhat@2.13.1) - solidity-coverage: 0.8.5(hardhat@2.13.1) + ethers: 6.8.0 + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) + hardhat-gas-reporter: 1.0.9(hardhat@2.18.3) + solidity-coverage: 0.8.5(hardhat@2.18.3) ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) typechain: 8.3.2(typescript@4.9.5) typescript: 4.9.5 dev: true + /@nomicfoundation/hardhat-verify@1.1.1(hardhat@2.18.3): + resolution: {integrity: sha512-9QsTYD7pcZaQFEA3tBb/D/oCStYDiEVDN7Dxeo/4SCyHRSm86APypxxdOMEPlGmXsAvd+p1j/dTODcpxb8aztA==} + peerDependencies: + hardhat: ^2.0.4 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/address': 5.7.0 + cbor: 8.1.0 + chalk: 2.4.2 + debug: 4.3.4(supports-color@8.1.1) + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) + lodash.clonedeep: 4.5.0 + semver: 6.3.1 + table: 6.8.1 + undici: 5.26.5 + transitivePeerDependencies: + - supports-color + dev: true + /@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1: resolution: {integrity: sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==} engines: {node: '>= 10'} @@ -10018,36 +10155,6 @@ packages: '@nomicfoundation/solidity-analyzer-win32-ia32-msvc': 0.1.1 '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.1 - /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.13.1): - resolution: {integrity: sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==} - peerDependencies: - ethers: ^5.7.2 - hardhat: ^2.0.0 - dependencies: - ethers: 5.7.2 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) - dev: true - - /@nomiclabs/hardhat-etherscan@3.1.7(hardhat@2.13.1): - resolution: {integrity: sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==} - peerDependencies: - hardhat: ^2.0.4 - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/address': 5.7.0 - cbor: 8.1.0 - chalk: 2.4.2 - debug: 4.3.4(supports-color@8.1.1) - fs-extra: 7.0.1 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) - lodash: 4.17.21 - semver: 6.3.1 - table: 6.8.1 - undici: 5.26.5 - transitivePeerDependencies: - - supports-color - dev: true - /@observablehq/inspector@5.0.0: resolution: {integrity: sha512-Vvg/TQdsZTUaeYbH0IKxYEz37FbRO6kdowoz2PrHLQif54NC1CjEihEjg+ZMSBn587GQxTFABu0CGkFZgtR1UQ==} dependencies: @@ -10132,7 +10239,7 @@ packages: natural-orderby: 2.0.3 object-treeify: 1.1.33 password-prompt: 1.1.3 - semver: 7.4.0 + semver: 7.5.4 string-width: 4.2.3 strip-ansi: 6.0.1 supports-color: 8.1.1 @@ -10198,10 +10305,10 @@ packages: resolution: {integrity: sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==} dev: true - /@openzeppelin/defender-admin-client@1.50.0: + /@openzeppelin/defender-admin-client@1.50.0(debug@4.3.4): resolution: {integrity: sha512-JxeA111ifCIzXho2gFymhepufB0ElI1UMvFIMEfJLvRL7g7V69wSiN8v+OqZyqZTahiY32Rb+TwdhVjKF5Zu+A==} dependencies: - '@openzeppelin/defender-base-client': 1.50.0 + '@openzeppelin/defender-base-client': 1.50.0(debug@4.3.4) axios: 1.5.1(debug@4.3.4) ethers: 5.7.2 lodash: 4.17.21 @@ -10217,7 +10324,7 @@ packages: resolution: {integrity: sha512-QWob3F6xuOu8r8oPy0Y2XLfAL1PTuKE2F4nC4wGeu3JJT8/pJz3xnHX5DgUYwiGIMqnkitUNUoBcmi4CPI31yw==} hasBin: true dependencies: - '@openzeppelin/defender-base-client': 1.50.0 + '@openzeppelin/defender-base-client': 1.50.0(debug@4.3.4) axios: 1.5.1(debug@4.3.4) dotenv: 10.0.0 glob: 7.2.3 @@ -10245,7 +10352,7 @@ packages: - debug - encoding - /@openzeppelin/defender-base-client@1.50.0: + /@openzeppelin/defender-base-client@1.50.0(debug@4.3.4): resolution: {integrity: sha512-V5uJ4t3kr9ex1RrqGH2DwsHuyW7/hl3VK0sSkq3VVbAewtcsW3cdg/UkXd5ITu6mtz76RoYkvUBHtkYUm0nb+w==} dependencies: amazon-cognito-identity-js: 6.3.6 @@ -10257,66 +10364,71 @@ packages: - debug - encoding - /@openzeppelin/defender-sentinel-client@1.49.0: - resolution: {integrity: sha512-fr39U1GRWvJP1fWgwqjTYCz7uhfVfXJReWcivwxMeaoyMl+jYFxj8NkMhqkkbmI6O4TUyNMsmAQ34qFf0IS0/A==} + /@openzeppelin/defender-sdk-base-client@1.3.0: + resolution: {integrity: sha512-OMMt7NaAL8C95ralF9nMeKZpg96COLZT9FPpGpPsI7aB8fVZfCM8+6k99gTF44hMS6IsRdN2WthS3m7VzQeeoA==} + dependencies: + amazon-cognito-identity-js: 6.3.6 + async-retry: 1.3.3 + transitivePeerDependencies: + - encoding + dev: true + + /@openzeppelin/defender-sdk-deploy-client@1.3.0(debug@4.3.4): + resolution: {integrity: sha512-RTYM3HnVvD2d5NoYfTug8UwT41e0Jjwb13lk9v0Jl8z7mcclUVvAnKD4DHJ4b8RhKpg4B15oLQK/Igzjg1HHRA==} dependencies: '@ethersproject/abi': 5.7.0 - '@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4) + '@openzeppelin/defender-sdk-base-client': 1.3.0 axios: 1.5.1(debug@4.3.4) lodash: 4.17.21 - node-fetch: 2.7.0 transitivePeerDependencies: - debug - encoding - dev: false + dev: true - /@openzeppelin/hardhat-defender@1.9.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.13.1): - resolution: {integrity: sha512-dl2pQyBvwEZVq1sgw/i+mLQiu4ZD7iKn2/ghD9RbAGHIM8hZQ4ou8cXl1S6wCA92prpeO1rPGQ+NcJajbY4MCw==} - deprecated: '@openzeppelin/hardhat-defender is deprecated. This functionality is now included as part of @openzeppelin/hardhat-upgrades' + /@openzeppelin/defender-sentinel-client@1.49.0: + resolution: {integrity: sha512-fr39U1GRWvJP1fWgwqjTYCz7uhfVfXJReWcivwxMeaoyMl+jYFxj8NkMhqkkbmI6O4TUyNMsmAQ34qFf0IS0/A==} dependencies: - '@openzeppelin/defender-admin-client': 1.50.0 + '@ethersproject/abi': 5.7.0 '@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4) - '@openzeppelin/hardhat-upgrades': 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.13.1) - ethereumjs-util: 7.1.5 + axios: 1.5.1(debug@4.3.4) + lodash: 4.17.21 + node-fetch: 2.7.0 transitivePeerDependencies: - - '@nomiclabs/hardhat-ethers' - - '@nomiclabs/hardhat-etherscan' - - '@nomiclabs/harhdat-etherscan' - - bufferutil - debug - encoding - - ethers - - hardhat - - supports-color - - utf-8-validate - dev: true + dev: false - /@openzeppelin/hardhat-upgrades@1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.13.1): - resolution: {integrity: sha512-7sb/Jf+X+uIufOBnmHR0FJVWuxEs2lpxjJnLNN6eCJCP8nD0v+Ot5lTOW2Qb/GFnh+fLvJtEkhkowz4ZQ57+zQ==} + /@openzeppelin/hardhat-upgrades@2.3.3(@nomicfoundation/hardhat-ethers@3.0.4)(@nomicfoundation/hardhat-verify@1.1.1)(ethers@6.8.0)(hardhat@2.18.3): + resolution: {integrity: sha512-rF87xYSz6Q2WFq5zcUF1T1tx3Kiq83hmke0xOBn5Qgrl++osseiDwS5oXfDK3NSWvj06oYGLERRGHcXnpQ31FQ==} hasBin: true peerDependencies: - '@nomiclabs/hardhat-ethers': ^2.0.0 - '@nomiclabs/hardhat-etherscan': ^3.1.0 - '@nomiclabs/harhdat-etherscan': '*' - ethers: ^5.7.2 + '@nomicfoundation/hardhat-ethers': ^3.0.0 + '@nomicfoundation/hardhat-verify': ^1.1.0 + ethers: ^6.6.0 hardhat: ^2.0.2 peerDependenciesMeta: - '@nomiclabs/harhdat-etherscan': + '@nomicfoundation/hardhat-verify': optional: true dependencies: - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.13.1) - '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.13.1) + '@nomicfoundation/hardhat-ethers': 3.0.4(ethers@6.8.0)(hardhat@2.18.3) + '@nomicfoundation/hardhat-verify': 1.1.1(hardhat@2.18.3) + '@openzeppelin/defender-admin-client': 1.50.0(debug@4.3.4) '@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4) - '@openzeppelin/platform-deploy-client': 0.8.0(debug@4.3.4) + '@openzeppelin/defender-sdk-base-client': 1.3.0 + '@openzeppelin/defender-sdk-deploy-client': 1.3.0(debug@4.3.4) '@openzeppelin/upgrades-core': 1.31.0 chalk: 4.1.2 debug: 4.3.4(supports-color@8.1.1) - ethers: 5.7.2 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + ethereumjs-util: 7.1.5 + ethers: 6.8.0 + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) proper-lockfile: 4.1.2 + undici: 5.26.5 transitivePeerDependencies: + - bufferutil - encoding - supports-color + - utf-8-validate dev: true /@openzeppelin/merkle-tree@1.0.5: @@ -10326,20 +10438,6 @@ packages: ethereum-cryptography: 1.2.0 dev: false - /@openzeppelin/platform-deploy-client@0.8.0(debug@4.3.4): - resolution: {integrity: sha512-POx3AsnKwKSV/ZLOU/gheksj0Lq7Is1q2F3pKmcFjGZiibf+4kjGxr4eSMrT+2qgKYZQH1ZLQZ+SkbguD8fTvA==} - deprecated: '@openzeppelin/platform-deploy-client is deprecated. Please use @openzeppelin/defender-sdk-deploy-client' - dependencies: - '@ethersproject/abi': 5.7.0 - '@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4) - axios: 0.21.4(debug@4.3.4) - lodash: 4.17.21 - node-fetch: 2.7.0 - transitivePeerDependencies: - - debug - - encoding - dev: true - /@openzeppelin/upgrades-core@1.31.0: resolution: {integrity: sha512-E1Cz8lVpo2mnBeFWxiGDLWtuTYMFNTEWwbnhle4dZ+5UHX6xTRO+Q/CaWBHm33HHhuuiUbRwgGNnAR9zOu+fyQ==} hasBin: true @@ -10541,13 +10639,13 @@ packages: resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} dev: false - /@primitivefi/hardhat-dodoc@0.2.3(hardhat@2.13.1)(squirrelly@8.0.8): + /@primitivefi/hardhat-dodoc@0.2.3(hardhat@2.18.3)(squirrelly@8.0.8): resolution: {integrity: sha512-ver9uHa79LTDTeebOKZ/eOVRL/FP1k0s0x/5Bo/8ZaDdLWFVClKqZyZYVjjW4CJqTPCt8uU9b9p71P2vzH4O9A==} peerDependencies: hardhat: ^2.6.4 squirrelly: ^8.0.8 dependencies: - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) squirrelly: 8.0.8 dev: true @@ -11180,14 +11278,14 @@ packages: resolution: {integrity: sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==} dependencies: '@noble/curves': 1.0.0 - '@noble/hashes': 1.3.0 + '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 /@scure/bip32@1.3.1: resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==} dependencies: '@noble/curves': 1.1.0 - '@noble/hashes': 1.3.1 + '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 dev: true @@ -11200,13 +11298,13 @@ packages: /@scure/bip39@1.2.0: resolution: {integrity: sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==} dependencies: - '@noble/hashes': 1.3.0 + '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 /@scure/bip39@1.2.1: resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} dependencies: - '@noble/hashes': 1.3.1 + '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 dev: true @@ -11917,7 +12015,7 @@ packages: dotenv: 16.3.1 dotenv-parse-variables: 2.0.0 download: 8.0.0 - ethers: 5.7.2 + ethers: 6.8.0 etherscan-api: 10.3.0(debug@4.3.4) find-config: 1.0.0 get-port: 6.1.2 @@ -12166,29 +12264,12 @@ packages: /@tsconfig/node16@1.0.4: resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - /@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5): - resolution: {integrity: sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==} - peerDependencies: - '@ethersproject/abi': ^5.0.0 - '@ethersproject/providers': ^5.0.0 - ethers: ^5.7.2 - typechain: ^8.1.1 - typescript: '>=4.3.0' - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/providers': 5.7.2 - ethers: 5.7.2 - lodash: 4.17.21 - ts-essentials: 7.0.3(typescript@4.9.5) - typechain: 8.3.2(typescript@4.9.5) - typescript: 4.9.5 - /@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.1.6): resolution: {integrity: sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==} peerDependencies: '@ethersproject/abi': ^5.0.0 '@ethersproject/providers': ^5.0.0 - ethers: ^5.7.2 + ethers: ^5.1.3 typechain: ^8.1.1 typescript: '>=4.3.0' dependencies: @@ -12199,34 +12280,15 @@ packages: ts-essentials: 7.0.3(typescript@5.1.6) typechain: 8.3.2(typescript@5.1.6) typescript: 5.1.6 - dev: false - /@typechain/ethers-v5@11.1.2(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5): - resolution: {integrity: sha512-ID6pqWkao54EuUQa0P5RgjvfA3MYqxUQKpbGKERbsjBW5Ra7EIXvbMlPp2pcP5IAdUkyMCFYsP2SN5q7mPdLDQ==} + /@typechain/ethers-v6@0.4.3(ethers@6.8.0)(typechain@8.3.2)(typescript@4.9.5): + resolution: {integrity: sha512-TrxBsyb4ryhaY9keP6RzhFCviWYApcLCIRMPyWaKp2cZZrfaM3QBoxXTnw/eO4+DAY3l+8O0brNW0WgeQeOiDA==} peerDependencies: - '@ethersproject/abi': ^5.0.0 - '@ethersproject/providers': ^5.0.0 - ethers: ^5.7.2 - typechain: ^8.3.2 - typescript: '>=4.3.0' - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/providers': 5.7.2 - ethers: 5.7.2 - lodash: 4.17.21 - ts-essentials: 7.0.3(typescript@4.9.5) - typechain: 8.3.2(typescript@4.9.5) - typescript: 4.9.5 - dev: true - - /@typechain/ethers-v6@0.5.1(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5): - resolution: {integrity: sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==} - peerDependencies: - ethers: ^5.7.2 - typechain: ^8.3.2 + ethers: 6.x + typechain: ^8.3.1 typescript: '>=4.7.0' dependencies: - ethers: 5.7.2 + ethers: 6.8.0 lodash: 4.17.21 ts-essentials: 7.0.3(typescript@4.9.5) typechain: 8.3.2(typescript@4.9.5) @@ -12239,31 +12301,31 @@ packages: '@ethersproject/abi': ^5.4.7 '@ethersproject/providers': ^5.4.7 '@typechain/ethers-v5': ^10.2.1 - ethers: ^5.7.2 + ethers: ^5.4.7 hardhat: ^2.9.9 typechain: ^8.1.1 dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/providers': 5.7.2 - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) + '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.1.6) ethers: 5.7.2 fs-extra: 9.1.0 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) - typechain: 8.3.2(typescript@4.9.5) + hardhat: 2.13.1(typescript@5.1.6) + typechain: 8.3.2(typescript@5.1.6) dev: false - /@typechain/hardhat@9.1.0(@typechain/ethers-v6@0.5.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2): - resolution: {integrity: sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==} + /@typechain/hardhat@8.0.3(@typechain/ethers-v6@0.4.3)(ethers@6.8.0)(hardhat@2.18.3)(typechain@8.3.2): + resolution: {integrity: sha512-MytSmJJn+gs7Mqrpt/gWkTCOpOQ6ZDfRrRT2gtZL0rfGe4QrU4x9ZdW15fFbVM/XTa+5EsKiOMYXhRABibNeng==} peerDependencies: - '@typechain/ethers-v6': ^0.5.1 - ethers: ^5.7.2 + '@typechain/ethers-v6': ^0.4.3 + ethers: ^6.1.0 hardhat: ^2.9.9 - typechain: ^8.3.2 + typechain: ^8.3.1 dependencies: - '@typechain/ethers-v6': 0.5.1(ethers@5.7.2)(typechain@8.3.2)(typescript@4.9.5) - ethers: 5.7.2 + '@typechain/ethers-v6': 0.4.3(ethers@6.8.0)(typechain@8.3.2)(typescript@4.9.5) + ethers: 6.8.0 fs-extra: 9.1.0 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) typechain: 8.3.2(typescript@4.9.5) dev: true @@ -12506,6 +12568,7 @@ packages: /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + requiresBuild: true dev: true /@types/keyv@3.1.4: @@ -12576,8 +12639,8 @@ packages: '@types/node': 18.18.7 dev: false - /@types/node-fetch@2.6.7: - resolution: {integrity: sha512-lX17GZVpJ/fuCjguZ5b3TjEbSENxmEk1B2z02yoXSK9WMEWRivhdSY73wWMn6bpcCDAOh6qAdktpKHIlkDk2lg==} + /@types/node-fetch@2.6.8: + resolution: {integrity: sha512-nnH5lV9QCMPsbEVdTb5Y+F3GQxLSw1xQgIydrb2gSfEavRPs50FnMr+KUaa+LoPSqibm2N+ZZxH7lavZlAT4GA==} dependencies: '@types/node': 18.18.7 form-data: 4.0.0 @@ -12602,6 +12665,9 @@ packages: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} dev: false + /@types/node@18.15.13: + resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} + /@types/node@18.18.7: resolution: {integrity: sha512-bw+lEsxis6eqJYW8Ql6+yTqkE6RuFtsQPSe5JxXbqYRFQEER5aJA9a5UH9igqDWm3X4iLHIKOHlnAXLM4mi7uQ==} dependencies: @@ -12762,17 +12828,13 @@ packages: /@types/sinon@10.0.20: resolution: {integrity: sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg==} dependencies: - '@types/sinonjs__fake-timers': 8.1.4 + '@types/sinonjs__fake-timers': 8.1.1 dev: true /@types/sinonjs__fake-timers@8.1.1: resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} dev: true - /@types/sinonjs__fake-timers@8.1.4: - resolution: {integrity: sha512-GDV68H0mBSN449sa5HEj51E0wfpVQb8xNSMzxf/PrypMFcLTMwJMOM/cgXiv71Mq5drkOQmUGvL1okOZcu6RrQ==} - dev: true - /@types/sizzle@2.3.5: resolution: {integrity: sha512-tAe4Q+OLFOA/AMD+0lq8ovp8t3ysxAOeaScnfNdZpUxaGl51ZMDEITxkvFl1STudQ58mz6gzVGl9VhMKhwRnZQ==} dev: true @@ -13182,6 +13244,19 @@ packages: - utf-8-validate dev: true + /@viem/anvil@0.0.6: + resolution: {integrity: sha512-OjKR/+FVwzuygXYFqP8MBal1SXG8bT2gbZwqqB0XuLw81LNBBvmE/Repm6+5kkBh4IUj0PhYdrqOsnayS14Gtg==} + dependencies: + execa: 7.2.0 + get-port: 6.1.2 + http-proxy: 1.18.1(debug@4.3.4) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + dev: true + /@vitest/expect@0.28.5: resolution: {integrity: sha512-gqTZwoUTwepwGIatnw4UKpQfnoyV0Z9Czn9+Lo2/jLIt4/AXLTn+oVZxlQ7Ng8bzcNkR+3DqLJ08kNr8jRmdNQ==} dependencies: @@ -14176,6 +14251,7 @@ packages: /@wry/context@0.7.4: resolution: {integrity: sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==} engines: {node: '>=8'} + requiresBuild: true dependencies: tslib: 2.6.2 dev: false @@ -14183,6 +14259,7 @@ packages: /@wry/equality@0.5.7: resolution: {integrity: sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==} engines: {node: '>=8'} + requiresBuild: true dependencies: tslib: 2.6.2 dev: false @@ -14190,6 +14267,7 @@ packages: /@wry/trie@0.4.3: resolution: {integrity: sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==} engines: {node: '>=8'} + requiresBuild: true dependencies: tslib: 2.6.2 dev: false @@ -14241,6 +14319,21 @@ packages: resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} dev: true + /abitype@0.10.2(typescript@5.1.6)(zod@3.22.4): + resolution: {integrity: sha512-1XndI+RKFWK4+TXCNv1683MRyX5NGmlHXCvqzjOqhSS3PQrxT2QYRZq1bMPPRNjn89B3eVaM2w7y3jVj/OIUzA==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + dependencies: + typescript: 5.1.6 + zod: 3.22.4 + dev: true + /abitype@0.8.7(typescript@5.1.6)(zod@3.22.4): resolution: {integrity: sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w==} peerDependencies: @@ -14306,7 +14399,7 @@ packages: engines: {node: '>=6'} dependencies: buffer: 5.7.1 - immediate: 3.3.0 + immediate: 3.2.3 level-concat-iterator: 2.0.1 level-supports: 1.0.1 xtend: 4.0.2 @@ -14387,6 +14480,9 @@ packages: resolution: {integrity: sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==} dev: false + /aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + /agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -16796,19 +16892,6 @@ packages: webpack: 5.89.0(webpack-cli@5.1.4) dev: false - /copyfiles@2.4.1: - resolution: {integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==} - hasBin: true - dependencies: - glob: 7.2.3 - minimatch: 3.1.2 - mkdirp: 1.0.4 - noms: 0.0.0 - through2: 2.0.5 - untildify: 4.0.0 - yargs: 16.2.0 - dev: true - /core-js-compat@3.33.1: resolution: {integrity: sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==} dependencies: @@ -19390,20 +19473,20 @@ packages: '@scure/bip39': 1.2.1 dev: true - /ethereum-waffle@4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@4.9.5): + /ethereum-waffle@4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.1.6): resolution: {integrity: sha512-iw9z1otq7qNkGDNcMoeNeLIATF9yKl1M8AIeu42ElfNBplq0e+5PeasQmm8ybY/elkZ1XyRO0JBQxQdVRb8bqQ==} engines: {node: '>=10.0'} hasBin: true peerDependencies: - ethers: ^5.7.2 + ethers: '*' dependencies: '@ethereum-waffle/chai': 4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(ethers@5.7.2) - '@ethereum-waffle/compiler': 4.0.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(solc@0.8.15)(typechain@8.3.2)(typescript@4.9.5) + '@ethereum-waffle/compiler': 4.0.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(solc@0.8.15)(typechain@8.3.2)(typescript@5.1.6) '@ethereum-waffle/mock-contract': 4.0.4(ethers@5.7.2) '@ethereum-waffle/provider': 4.0.5(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(ethers@5.7.2) ethers: 5.7.2 solc: 0.8.15 - typechain: 8.3.2(typescript@4.9.5) + typechain: 8.3.2(typescript@5.1.6) transitivePeerDependencies: - '@ensdomains/ens' - '@ensdomains/resolver' @@ -19491,6 +19574,21 @@ packages: - bufferutil - utf-8-validate + /ethers@6.8.0: + resolution: {integrity: sha512-zrFbmQRlraM+cU5mE4CZTLBurZTs2gdp2ld0nG/f3ecBK+x6lZ69KSxBqZ4NjclxwfTxl5LeNufcBbMsTdY53Q==} + engines: {node: '>=14.0.0'} + dependencies: + '@adraffy/ens-normalize': 1.10.0 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@types/node': 18.15.13 + aes-js: 4.0.0-beta.5 + tslib: 2.4.0 + ws: 8.5.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + /etherscan-api@10.3.0(debug@4.3.4): resolution: {integrity: sha512-XH+E7J2c6Wq750stvFuIIMdiLv5v65nTRftQojXuQXNfEsQaZOOgeY11WHdrGh6yh90ekDJQldgf033tIS1rCw==} dependencies: @@ -19911,6 +20009,30 @@ packages: node-domexception: 1.0.0 web-streams-polyfill: 3.2.1 + /fetch-mock@9.11.0(node-fetch@3.3.2): + resolution: {integrity: sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q==} + engines: {node: '>=4.0.0'} + peerDependencies: + node-fetch: '*' + peerDependenciesMeta: + node-fetch: + optional: true + dependencies: + '@babel/core': 7.23.2 + '@babel/runtime': 7.23.2 + core-js: 3.33.1 + debug: 4.3.4(supports-color@8.1.1) + glob-to-regexp: 0.4.1 + is-subset: 0.1.1 + lodash.isequal: 4.5.0 + node-fetch: 3.3.2 + path-to-regexp: 2.2.1 + querystring: 0.2.1 + whatwg-url: 6.5.0 + transitivePeerDependencies: + - supports-color + dev: true + /fets@0.1.5: resolution: {integrity: sha512-mL/ya591WOgCP1yBBPbp8E37nynj8QQF6iQCUVl0aHDL80BZ9SOL4BcKBy0dnKdC+clnnAkMm05KB9hsj4m4jQ==} dependencies: @@ -21015,14 +21137,14 @@ packages: /graphql-import-node@0.0.5(graphql@16.8.1): resolution: {integrity: sha512-OXbou9fqh9/Lm7vwXT0XoRN9J5+WCYKnbiTalgFDvkQERITRmcfncZs6aVABedd5B85yQU5EULS4a5pnbpuI0Q==} peerDependencies: - graphql: ^16.6.0 + graphql: '*' dependencies: graphql: 16.8.1 /graphql-jit@0.8.2(graphql@16.8.1): resolution: {integrity: sha512-P9KtM/UY4JTtHVRqRlZzFXPmDEtps1Bd27Mvj/naQIa5d0j83zPxAx4jewq1wueF3UEZu1JFZwX1XVBBkoo1Mg==} peerDependencies: - graphql: ^16.6.0 + graphql: '>=15' dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) fast-json-stringify: 1.21.0 @@ -21038,7 +21160,7 @@ packages: resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} engines: {node: '>=10'} peerDependencies: - graphql: ^16.6.0 + graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: graphql: 16.8.1 tslib: 2.6.2 @@ -21047,7 +21169,7 @@ packages: resolution: {integrity: sha512-umt4f5NnMK46ChM2coO36PTFhHouBrK9stWWBczERguwYrGnPNxJ9dimU6IyOBfOkC6Izhkg4H8+F51W/8CYDg==} engines: {node: '>=10'} peerDependencies: - graphql: ^16.6.0 + graphql: '>=0.11 <=16' dependencies: graphql: 16.8.1 @@ -21055,14 +21177,14 @@ packages: resolution: {integrity: sha512-LycmCwhZ+Op2GlHz4BZDsUYHKRiiUz+3r9wbhBATMETNlORQJAaFlAgTFoeRh6xQoQegwYwIylVD1Qns9/DA3w==} engines: {node: '>=10'} peerDependencies: - graphql: ^16.6.0 + graphql: '>=0.11 <=16' dependencies: graphql: 16.8.1 /graphql-yoga@3.9.1(graphql@16.8.1): resolution: {integrity: sha512-BB6EkN64VBTXWmf9Kym2OsVZFzBC0mAsQNo9eNB5xIr3t+x7qepQ34xW5A353NWol3Js3xpzxwIKFVF6l9VsPg==} peerDependencies: - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@envelop/core': 3.0.6 '@envelop/validation-cache': 5.1.3(@envelop/core@3.0.6)(graphql@16.8.1) @@ -21082,7 +21204,7 @@ packages: resolution: {integrity: sha512-ZvZlO8MHMDWuLRoDhvJQnXg8SOJD0iDaCA+M/zWuD26AlhEugOEbpnhw/645oqXTYtvHsM91WyxtV7p5XJWYMg==} engines: {node: '>=18.0.0'} peerDependencies: - graphql: ^16.6.0 + graphql: ^15.2.0 || ^16.0.0 dependencies: '@envelop/core': 5.0.0 '@graphql-tools/executor': 1.2.0(graphql@16.8.1) @@ -21098,6 +21220,11 @@ packages: tslib: 2.6.2 dev: false + /graphql@15.5.0: + resolution: {integrity: sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA==} + engines: {node: '>= 10.x'} + dev: true + /graphql@16.8.1: resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} @@ -21169,7 +21296,7 @@ packages: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} engines: {node: '>=6'} - /hardhat-abi-exporter@2.10.1(hardhat@2.13.1): + /hardhat-abi-exporter@2.10.1(hardhat@2.18.3): resolution: {integrity: sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==} engines: {node: '>=14.14.0'} peerDependencies: @@ -21177,17 +21304,17 @@ packages: dependencies: '@ethersproject/abi': 5.7.0 delete-empty: 3.0.0 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) dev: true - /hardhat-gas-reporter@1.0.9(hardhat@2.13.1): + /hardhat-gas-reporter@1.0.9(hardhat@2.18.3): resolution: {integrity: sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==} peerDependencies: hardhat: ^2.0.2 dependencies: array-uniq: 1.0.3 eth-gas-reporter: 0.2.27 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) sha1: 1.1.1 transitivePeerDependencies: - '@codechecks/client' @@ -21196,16 +21323,16 @@ packages: - utf-8-validate dev: true - /hardhat-preprocessor@0.1.5(hardhat@2.13.1): + /hardhat-preprocessor@0.1.5(hardhat@2.18.3): resolution: {integrity: sha512-j8m44mmPxpxAAd0G8fPHRHOas/INZdzptSur0TNJvMEGcFdLDhbHHxBcqZVQ/bmiW42q4gC60AP4CXn9EF018g==} peerDependencies: hardhat: ^2.0.5 dependencies: - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) murmur-128: 0.2.1 dev: true - /hardhat@2.13.1(ts-node@10.9.1)(typescript@4.9.5): + /hardhat@2.13.1(typescript@5.1.6): resolution: {integrity: sha512-ZZL7LQxHmbw4JQJsiEv2qE35nbR+isr2sIdtgZVPp0+zWqRkpr1OT7gmvhCNYfjpEPyfjZIxWriQWlphJhVPLQ==} engines: {node: '>=14.0.0'} hasBin: true @@ -21264,9 +21391,8 @@ packages: solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 - ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) tsort: 0.0.1 - typescript: 4.9.5 + typescript: 5.1.6 undici: 5.26.5 uuid: 8.3.2 ws: 7.5.9 @@ -21274,10 +21400,10 @@ packages: - bufferutil - supports-color - utf-8-validate + dev: false - /hardhat@2.13.1(typescript@5.1.6): - resolution: {integrity: sha512-ZZL7LQxHmbw4JQJsiEv2qE35nbR+isr2sIdtgZVPp0+zWqRkpr1OT7gmvhCNYfjpEPyfjZIxWriQWlphJhVPLQ==} - engines: {node: '>=14.0.0'} + /hardhat@2.18.2(ts-node@10.9.1)(typescript@5.1.6): + resolution: {integrity: sha512-lUVmJg7DsKcUCDpqv57CJl6vHqo/1PeHSfM3+WIa8UtRKmXyVTj1qQK01TDiuetkZBVg9Dn52qU+ZwaJQynaKA==} hasBin: true peerDependencies: ts-node: '*' @@ -21290,21 +21416,20 @@ packages: dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.1 - '@nomicfoundation/ethereumjs-block': 5.0.0 - '@nomicfoundation/ethereumjs-blockchain': 7.0.0 - '@nomicfoundation/ethereumjs-common': 4.0.0 - '@nomicfoundation/ethereumjs-evm': 2.0.0 - '@nomicfoundation/ethereumjs-rlp': 5.0.0 - '@nomicfoundation/ethereumjs-statemanager': 2.0.0 - '@nomicfoundation/ethereumjs-trie': 6.0.0 - '@nomicfoundation/ethereumjs-tx': 5.0.0 - '@nomicfoundation/ethereumjs-util': 9.0.0 - '@nomicfoundation/ethereumjs-vm': 7.0.0 + '@nomicfoundation/ethereumjs-block': 5.0.2 + '@nomicfoundation/ethereumjs-blockchain': 7.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-evm': 2.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-statemanager': 2.0.2 + '@nomicfoundation/ethereumjs-trie': 6.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + '@nomicfoundation/ethereumjs-vm': 7.0.2 '@nomicfoundation/solidity-analyzer': 0.1.1 '@sentry/node': 5.30.0 '@types/bn.js': 5.1.3 '@types/lru-cache': 5.1.1 - abort-controller: 3.0.0 adm-zip: 0.4.16 aggregate-error: 3.1.0 ansi-escapes: 4.3.2 @@ -21327,13 +21452,13 @@ packages: mnemonist: 0.38.5 mocha: 10.2.0 p-map: 4.0.0 - qs: 6.11.2 raw-body: 2.5.2 resolve: 1.17.0 semver: 6.3.1 solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 + ts-node: 10.9.1(@types/node@18.18.7)(typescript@5.1.6) tsort: 0.0.1 typescript: 5.1.6 undici: 5.26.5 @@ -21345,6 +21470,73 @@ packages: - utf-8-validate dev: false + /hardhat@2.18.3(ts-node@10.9.1)(typescript@4.9.5): + resolution: {integrity: sha512-JuYaTG+4ZHVjEHCW5Hn6jCHH3LpO75dtgznZpM/dLv12RcSlw/xHbeQh3FAsGahQr1epKryZcZEMHvztVZHe0g==} + hasBin: true + peerDependencies: + ts-node: '*' + typescript: '*' + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + dependencies: + '@ethersproject/abi': 5.7.0 + '@metamask/eth-sig-util': 4.0.1 + '@nomicfoundation/ethereumjs-block': 5.0.2 + '@nomicfoundation/ethereumjs-blockchain': 7.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-evm': 2.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-statemanager': 2.0.2 + '@nomicfoundation/ethereumjs-trie': 6.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + '@nomicfoundation/ethereumjs-vm': 7.0.2 + '@nomicfoundation/solidity-analyzer': 0.1.1 + '@sentry/node': 5.30.0 + '@types/bn.js': 5.1.3 + '@types/lru-cache': 5.1.1 + adm-zip: 0.4.16 + aggregate-error: 3.1.0 + ansi-escapes: 4.3.2 + chalk: 2.4.2 + chokidar: 3.5.3 + ci-info: 2.0.0 + debug: 4.3.4(supports-color@8.1.1) + enquirer: 2.4.1 + env-paths: 2.2.1 + ethereum-cryptography: 1.2.0 + ethereumjs-abi: 0.6.8 + find-up: 2.1.0 + fp-ts: 1.19.3 + fs-extra: 7.0.1 + glob: 7.2.0 + immutable: 4.3.4 + io-ts: 1.10.4 + keccak: 3.0.4 + lodash: 4.17.21 + mnemonist: 0.38.5 + mocha: 10.2.0 + p-map: 4.0.0 + raw-body: 2.5.2 + resolve: 1.17.0 + semver: 6.3.1 + solc: 0.7.3(debug@4.3.4) + source-map-support: 0.5.21 + stacktrace-parser: 0.1.10 + ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) + tsort: 0.0.1 + typescript: 4.9.5 + undici: 5.26.5 + uuid: 8.3.2 + ws: 7.5.9 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true @@ -21557,6 +21749,7 @@ packages: /hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + requiresBuild: true dependencies: react-is: 16.13.1 dev: false @@ -22026,27 +22219,6 @@ packages: wrap-ansi: 7.0.0 dev: true - /inquirer@8.2.6: - resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} - engines: {node: '>=12.0.0'} - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - ora: 5.4.1 - run-async: 2.4.1 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - wrap-ansi: 6.2.0 - dev: true - /interface-blockstore@2.0.3: resolution: {integrity: sha512-OwVUnlNcx7H5HloK0Myv6c/C1q9cNG11HX6afdeU6q6kbuNj8jKCwVnmJHhC94LZaJ+9hvVOk4IUstb3Esg81w==} dependencies: @@ -23185,6 +23357,10 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-subset@0.1.1: + resolution: {integrity: sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==} + dev: true + /is-symbol@1.0.4: resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} engines: {node: '>= 0.4'} @@ -23923,7 +24099,7 @@ packages: pretty-format: 29.7.0 slash: 3.0.0 strip-json-comments: 3.1.1 - ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@18.18.7)(typescript@5.1.6) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -24001,6 +24177,15 @@ packages: jest-get-type: 29.6.3 dev: true + /jest-fetch-mock@3.0.3: + resolution: {integrity: sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==} + dependencies: + cross-fetch: 3.1.8 + promise-polyfill: 8.3.0 + transitivePeerDependencies: + - encoding + dev: true + /jest-get-type@29.6.3: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -24288,6 +24473,10 @@ packages: engines: {node: '>=10'} dev: true + /js-base64@3.7.5: + resolution: {integrity: sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==} + dev: false + /js-confetti@0.11.0: resolution: {integrity: sha512-Hc7I3VI4r4H0nq5q/oQK+JJwGoYRYVHK72fGk8E9Ay1dbh+aiZ9yl0yFp1K4oYeq7YFDQAndYChwqLPA3QWQuA==} dev: false @@ -24523,6 +24712,7 @@ packages: /json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true + requiresBuild: true dependencies: minimist: 1.2.8 dev: true @@ -25171,6 +25361,10 @@ packages: /lodash.clone@4.5.0: resolution: {integrity: sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==} + /lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + dev: true + /lodash.curry@4.1.1: resolution: {integrity: sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA==} dev: false @@ -25203,7 +25397,6 @@ packages: /lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - dev: false /lodash.isfunction@3.0.9: resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} @@ -25270,6 +25463,10 @@ packages: resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} dev: true + /lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + dev: true + /lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} dev: true @@ -26590,7 +26787,7 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - /msw@1.3.2(typescript@4.9.5): + /msw@1.3.2(typescript@5.1.6): resolution: {integrity: sha512-wKLhFPR+NitYTkQl5047pia0reNGgf0P6a1eTnA5aNlripmiz0sabMvvHcicE8kQ3/gZcI0YiPFWmYfowfm3lA==} engines: {node: '>=14'} hasBin: true @@ -26611,7 +26808,7 @@ packages: cookie: 0.4.2 graphql: 16.8.1 headers-polyfill: 3.2.5 - inquirer: 8.2.6 + inquirer: 8.2.5 is-node-process: 1.2.0 js-levenshtein: 1.1.6 node-fetch: 2.7.0 @@ -26619,7 +26816,7 @@ packages: path-to-regexp: 6.2.1 strict-event-emitter: 0.4.6 type-fest: 2.19.0 - typescript: 4.9.5 + typescript: 5.1.6 yargs: 17.7.2 transitivePeerDependencies: - encoding @@ -26972,13 +27169,6 @@ packages: engines: {node: '>=12.19'} dev: true - /noms@0.0.0: - resolution: {integrity: sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==} - dependencies: - inherits: 2.0.4 - readable-stream: 1.0.34 - dev: true - /non-layered-tidy-tree-layout@2.0.2: resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} dev: false @@ -27307,6 +27497,7 @@ packages: /optimism@0.17.5: resolution: {integrity: sha512-TEcp8ZwK1RczmvMnvktxHSF2tKgMWjJ71xEFGX5ApLh67VsMSTy1ZUlipJw8W+KaqgOmQ+4pqwkeivY89j+4Vw==} + requiresBuild: true dependencies: '@wry/context': 0.7.4 '@wry/trie': 0.4.3 @@ -27801,7 +27992,6 @@ packages: /path-to-regexp@2.2.1: resolution: {integrity: sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==} - dev: false /path-to-regexp@6.2.1: resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} @@ -28586,6 +28776,10 @@ packages: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} + /promise-polyfill@8.3.0: + resolution: {integrity: sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==} + dev: true + /promise@7.3.1: resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} dependencies: @@ -29045,6 +29239,7 @@ packages: /react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + requiresBuild: true /react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} @@ -29892,6 +30087,7 @@ packages: /response-iterator@0.2.6: resolution: {integrity: sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==} engines: {node: '>=0.8'} + requiresBuild: true dev: false /responselike@1.0.2: @@ -30018,7 +30214,7 @@ packages: semver: 5.7.2 dev: true - /rollup-plugin-dts@5.3.1(rollup@3.29.4)(typescript@4.9.5): + /rollup-plugin-dts@5.3.1(rollup@3.29.4)(typescript@5.1.6): resolution: {integrity: sha512-gusMi+Z4gY/JaEQeXnB0RUdU82h1kF0WYzCWgVmV4p3hWXqelaKuCvcJawfeg+EKn2T1Ie+YWF2OiN1/L8bTVg==} engines: {node: '>=v14.21.3'} peerDependencies: @@ -30027,7 +30223,7 @@ packages: dependencies: magic-string: 0.30.5 rollup: 3.29.4 - typescript: 4.9.5 + typescript: 5.1.6 optionalDependencies: '@babel/code-frame': 7.22.13 dev: true @@ -30866,7 +31062,7 @@ packages: resolution: {integrity: sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==} dev: true - /solidity-coverage@0.8.5(hardhat@2.13.1): + /solidity-coverage@0.8.5(hardhat@2.18.3): resolution: {integrity: sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ==} hasBin: true peerDependencies: @@ -30882,7 +31078,7 @@ packages: ghost-testrpc: 0.0.2 global-modules: 2.0.0 globby: 10.0.2 - hardhat: 2.13.1(ts-node@10.9.1)(typescript@4.9.5) + hardhat: 2.18.3(ts-node@10.9.1)(typescript@4.9.5) jsonschema: 1.4.1 lodash: 4.17.21 mocha: 10.2.0 @@ -31588,6 +31784,7 @@ packages: /symbol-observable@4.0.0: resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} engines: {node: '>=0.10'} + requiresBuild: true dev: false /symbol-tree@3.2.4: @@ -31979,6 +32176,12 @@ packages: /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + /tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + dependencies: + punycode: 2.3.0 + dev: true + /tr46@3.0.0: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} engines: {node: '>=12'} @@ -32051,6 +32254,7 @@ packages: typescript: '>=3.7.0' dependencies: typescript: 4.9.5 + dev: true /ts-essentials@7.0.3(typescript@5.1.6): resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} @@ -32058,7 +32262,6 @@ packages: typescript: '>=3.7.0' dependencies: typescript: 5.1.6 - dev: false /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} @@ -32067,6 +32270,7 @@ packages: /ts-invariant@0.10.3: resolution: {integrity: sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==} engines: {node: '>=8'} + requiresBuild: true dependencies: tslib: 2.6.2 dev: false @@ -32077,7 +32281,7 @@ packages: jest-resolve: 29.7.0 dev: true - /ts-jest@29.1.1(@babel/core@7.23.2)(babel-jest@29.7.0)(esbuild@0.17.19)(jest@29.7.0)(typescript@4.9.5): + /ts-jest@29.1.1(@babel/core@7.23.2)(babel-jest@29.7.0)(esbuild@0.17.19)(jest@29.7.0)(typescript@5.1.6): resolution: {integrity: sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -32109,7 +32313,7 @@ packages: lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.5.4 - typescript: 4.9.5 + typescript: 5.1.6 yargs-parser: 21.1.1 dev: true @@ -32250,6 +32454,7 @@ packages: /tsconfig-paths@3.14.2: resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} + requiresBuild: true dependencies: '@types/json5': 0.0.29 json5: 1.0.2 @@ -32268,6 +32473,9 @@ packages: /tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + /tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + /tslib@2.4.1: resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} @@ -32472,6 +32680,7 @@ packages: typescript: 4.9.5 transitivePeerDependencies: - supports-color + dev: true /typechain@8.3.2(typescript@5.1.6): resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} @@ -32492,7 +32701,6 @@ packages: typescript: 5.1.6 transitivePeerDependencies: - supports-color - dev: false /typed-array-buffer@1.0.0: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} @@ -32541,13 +32749,13 @@ packages: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: true - /typedoc-plugin-markdown@3.16.0(typedoc@0.23.28): - resolution: {integrity: sha512-eeiC78fDNGFwemPIHiwRC+mEC7W5jwt3fceUev2gJ2nFnXpVHo8eRrpC9BLWZDee6ehnz/sPmNjizbXwpfaTBw==} + /typedoc-plugin-markdown@3.17.0(typedoc@0.23.28): + resolution: {integrity: sha512-+uh5fHNfNSGdUxae0FWOuJ8Xu9Sl08jkdshOg6dilAqN/ZXmYsUFFDKw70fYfiGxdCLvpUuyr9FYO+WAa2lHeA==} peerDependencies: typedoc: '>=0.24.0' dependencies: handlebars: 4.7.8 - typedoc: 0.23.28(typescript@4.9.5) + typedoc: 0.23.28(typescript@5.1.6) dev: true /typedoc-plugin-missing-exports@2.1.0(typedoc@0.23.28): @@ -32555,10 +32763,10 @@ packages: peerDependencies: typedoc: 0.24.x || 0.25.x dependencies: - typedoc: 0.23.28(typescript@4.9.5) + typedoc: 0.23.28(typescript@5.1.6) dev: true - /typedoc@0.23.28(typescript@4.9.5): + /typedoc@0.23.28(typescript@5.1.6): resolution: {integrity: sha512-9x1+hZWTHEQcGoP7qFmlo4unUoVJLB0H/8vfO/7wqTnZxg4kPuji9y3uRzEu0ZKez63OJAUmiGhUrtukC6Uj3w==} engines: {node: '>= 14.14'} hasBin: true @@ -32569,7 +32777,7 @@ packages: marked: 4.3.0 minimatch: 7.4.6 shiki: 0.14.5 - typescript: 4.9.5 + typescript: 5.1.6 dev: true /typescript@4.9.5: @@ -33641,6 +33849,10 @@ packages: /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + /webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + dev: true + /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -33888,6 +34100,14 @@ packages: tr46: 0.0.3 webidl-conversions: 3.0.1 + /whatwg-url@6.5.0: + resolution: {integrity: sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==} + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + dev: true + /wherearewe@2.0.1: resolution: {integrity: sha512-XUguZbDxCA2wBn2LoFtcEhXL6AXo+hVjGonwhSTTTU9SzbWG8Xu3onNIpzf9j/mYUcJQ0f+m37SzG77G851uFw==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -34192,6 +34412,18 @@ packages: bufferutil: 4.0.8 utf-8-validate: 5.0.10 + /ws@8.5.0: + resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + /xdg-basedir@4.0.0: resolution: {integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==} engines: {node: '>=8'} @@ -34420,12 +34652,14 @@ packages: /zen-observable-ts@1.2.5: resolution: {integrity: sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==} + requiresBuild: true dependencies: zen-observable: 0.8.15 dev: false /zen-observable@0.8.15: resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} + requiresBuild: true dev: false /zod-to-json-schema@3.21.4(zod@3.22.4): diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index aaa9186b..fcd6e04d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,6 +4,6 @@ packages: - "docs" - "frontend" - "graph" - - "vendor/observabletreemap" - "sdk" + - "vendor/observabletreemap" - "contracts" diff --git a/sdk/.graphclient/index.ts b/sdk/.graphclient/index.ts index ee00cdac..ea5a9a56 100644 --- a/sdk/.graphclient/index.ts +++ b/sdk/.graphclient/index.ts @@ -798,8 +798,7 @@ export type DirectiveResolvers(moduleId: string) => { const relativeModuleId = (pathModule.isAbsolute(moduleId) ? pathModule.relative(baseDir, moduleId) : moduleId).split('\\').join('/').replace(baseDir + '/', ''); diff --git a/sdk/jest.config.ts b/sdk/jest.config.ts index 543f7ca1..7d3d6afb 100644 --- a/sdk/jest.config.ts +++ b/sdk/jest.config.ts @@ -14,6 +14,7 @@ const config: Config = { resolver: "ts-jest-resolver", moduleFileExtensions: ["js", "jsx", "json", "ts"], transform: {}, + workerThreads: true, }; export default config; diff --git a/sdk/package.json b/sdk/package.json index 28589b71..9462fd80 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@hypercerts-org/sdk", - "version": "0.8.16", + "version": "0.9.0-viem", "description": "SDK for hypercerts protocol", "repository": "git@github.com:hypercerts-org/hypercerts.git", "author": "Hypercerts team", @@ -23,7 +23,7 @@ "package.json" ], "dependencies": { - "@ethereum-attestation-service/eas-sdk": "^0.28.3", + "@ethereum-attestation-service/eas-sdk": "1.2.2-beta.0", "@ethersproject/abstract-signer": "^5.7.0", "@graphprotocol/client-add-source-name": "^1.0.16", "@graphprotocol/client-polling-live": "^2.0.0", @@ -43,13 +43,13 @@ "ajv": "^8.11.2", "axios": "^1.2.2", "dotenv": "^16.0.3", - "ethers": "^5.7.2", + "ethers": "5.7.2", "graphql": "^16.6.0", "ipfs-core": "^0.17.0", - "jest": "^29.3.1", "loglevel": "^1.8.1", "mime": "^3.0.0", "nft.storage": "^7.1.1", + "viem": "1.5.3", "web3.storage": "^4.5.5" }, "devDependencies": { @@ -68,14 +68,19 @@ "@types/mocha": "9.1.0", "@types/node": "^18.11.17", "@types/sinon": "^10.0.15", + "@viem/anvil": "^0.0.6", + "abitype": "^0.10.2", "babel-jest": "^29.7.0", "chai": "^4.3.7", "chai-assertions-count": "^1.0.2", "chai-subset": "^1.6.0", "esbuild": "^0.17.10", "ethereum-waffle": "^4.0.10", + "fetch-mock": "^9.11.0", "it-all": "^2.0.0", + "jest": "^29.3.1", "jest-extended": "^4.0.0", + "jest-fetch-mock": "^3.0.3", "json-schema-to-typescript": "^12.0.0", "msw": "^1.2.1", "nyc": "^15.1.0", @@ -95,7 +100,7 @@ "typedoc": "^0.23.25", "typedoc-plugin-markdown": "^3.14.0", "typedoc-plugin-missing-exports": "^2.0.0", - "typescript": "^4.9.0" + "typescript": "5.1.6" }, "scripts": { "build": "pnpm types:json && pnpm graph:build:esm && rollup -c", diff --git a/sdk/src/client.ts b/sdk/src/client.ts index 6163bf03..f092a6c7 100644 --- a/sdk/src/client.ts +++ b/sdk/src/client.ts @@ -1,10 +1,17 @@ -import { HypercertMinter, HypercertMinterAbi } from "@hypercerts-org/contracts"; +import { HypercertMinterAbi } from "@hypercerts-org/contracts"; import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; -import { BigNumber, BigNumberish, BytesLike, ContractTransaction, ethers, providers } from "ethers"; - -import { DEFAULT_CHAIN_ID } from "./constants.js"; -import HypercertEvaluator from "./evaluations/index.js"; -import HypercertIndexer from "./indexer.js"; +import { + ByteArray, + GetContractReturnType, + Hex, + PublicClient, + WriteContractReturnType, + getContract, + parseAbi, +} from "viem"; +import { DEFAULT_CHAIN_ID } from "./constants"; +import HypercertEvaluator from "./evaluations/index"; +import HypercertIndexer from "./indexer"; import HypercertsStorage from "./storage.js"; import { AllowlistEntry, @@ -14,11 +21,12 @@ import { HypercertMetadata, InvalidOrMissingError, MalformedDataError, + SupportedOverrides, TransferRestrictions, -} from "./types/index.js"; -import { getConfig } from "./utils/config.js"; -import logger from "./utils/logger.js"; -import { validateAllowlist, validateMetaData, verifyMerkleProof, verifyMerkleProofs } from "./validator/index.js"; +} from "./types"; +import { getConfig } from "./utils/config"; +import logger from "./utils/logger"; +import { validateAllowlist, validateMetaData, verifyMerkleProof, verifyMerkleProofs } from "./validator"; /** * Hypercerts client factory @@ -28,26 +36,33 @@ import { validateAllowlist, validateMetaData, verifyMerkleProof, verifyMerklePro * @param storage - Hypercerts storage object */ export default class HypercertClient implements HypercertClientInterface { - readonly _config: HypercertClientConfig; + readonly _config; private _storage: HypercertsStorage; private _evaluator: HypercertEvaluator; private _indexer: HypercertIndexer; //TODO added the TypedDataSigner since that's needed for EAS signing. Will this work on front-end? - private _operator: ethers.providers.Provider | ethers.Signer; - private _contract: HypercertMinter; + private _publicClient: PublicClient; + private _walletClient; + private _contract: GetContractReturnType; readonly: boolean; /** * Creates a new instance of the `HypercertClient` class. * @param config The configuration options for the client. */ - constructor(config = { chainId: DEFAULT_CHAIN_ID } as Partial) { + constructor(config = { id: DEFAULT_CHAIN_ID } as Partial) { this._config = getConfig(config); - this._operator = this._config.operator; + if (!this._config.publicClient) { + throw new ClientError("Could not connect to public client."); + } - this._contract = ( - new ethers.Contract(this._config.contractAddress, HypercertMinterAbi, this._operator) - ); + this._publicClient = this._config.publicClient; + this._walletClient = this._config?.walletClient; + + this._contract = getContract({ + address: this._config.contractAddress as `0x${string}`, + abi: parseAbi(HypercertMinterAbi), + }); this._storage = new HypercertsStorage(this._config); @@ -55,11 +70,7 @@ export default class HypercertClient implements HypercertClientInterface { this._evaluator = new HypercertEvaluator(this._config); - this.readonly = - providers.Provider.isProvider(this._operator) || - !ethers.Signer.isSigner(this._operator) || - !this._config.contractAddress || - this._storage.readonly; + this.readonly = !this._walletClient || this._storage.readonly; if (this.readonly) { logger.warn("HypercertsClient is in readonly mode", "client"); @@ -70,7 +81,7 @@ export default class HypercertClient implements HypercertClientInterface { * Gets the config for the client. * @returns The client config. */ - get config(): HypercertClientConfig { + get config(): Partial { return this._config; } @@ -94,7 +105,7 @@ export default class HypercertClient implements HypercertClientInterface { * Gets the HypercertMinter contract used by the client. * @returns The contract. */ - get contract(): HypercertMinter { + get contract(): GetContractReturnType { return this._contract; } @@ -108,17 +119,17 @@ export default class HypercertClient implements HypercertClientInterface { */ mintClaim = async ( metaData: HypercertMetadata, - totalUnits: BigNumberish, + totalUnits: bigint, transferRestriction: TransferRestrictions, - overrides?: ethers.Overrides, - ): Promise => { + overrides?: SupportedOverrides, + ): Promise => { this.checkWritable(); - if (!ethers.Signer.isSigner(this._config.operator)) { - throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); + if (!this._walletClient) { + throw new ClientError("Could not detect account; sending transactions not allowed."); } - const signerAddress = await this._config.operator.getAddress(); + const operator = this._walletClient; // validate metadata const { valid, errors } = validateMetaData(metaData); @@ -129,9 +140,15 @@ export default class HypercertClient implements HypercertClientInterface { // store metadata on IPFS const cid = await this.storage.storeMetadata(metaData); - return overrides - ? this.contract.mintClaim(signerAddress, totalUnits, cid, transferRestriction, overrides) - : this.contract.mintClaim(signerAddress, totalUnits, cid, transferRestriction); + const { request } = await this._publicClient.simulateContract({ + functionName: "mintClaim", + account: operator.account, + args: [operator.account?.address, totalUnits, cid, transferRestriction], + ...this.getContractConfig(), + ...this.getCleanedOverrides(overrides), + }); + + return operator.writeContract(request); }; /** @@ -147,17 +164,17 @@ export default class HypercertClient implements HypercertClientInterface { createAllowlist = async ( allowList: AllowlistEntry[], metaData: HypercertMetadata, - totalUnits: BigNumberish, + totalUnits: bigint, transferRestriction: TransferRestrictions, - overrides?: ethers.Overrides, + overrides?: SupportedOverrides, ) => { this.checkWritable(); - if (!ethers.Signer.isSigner(this._config.operator)) { - throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); + if (!this._walletClient) { + throw new ClientError("Could not connect to wallet; sending transactions not allowed."); } - const signerAddress = await this._config.operator.getAddress(); + const operator = this._walletClient; // validate allowlist const { valid: validAllowlist, errors: allowlistErrors } = validateAllowlist(allowList, totalUnits); @@ -172,7 +189,7 @@ export default class HypercertClient implements HypercertClientInterface { } // create allowlist - const tuples = allowList.map((p) => [p.address, p.units]); + const tuples = allowList.map((p) => [p.address, p.units.toString()]); const tree = StandardMerkleTree.of(tuples, ["address", "uint256"]); const cidMerkle = await this.storage.storeData(JSON.stringify(tree.dump())); @@ -181,9 +198,15 @@ export default class HypercertClient implements HypercertClientInterface { // store metadata on IPFS const cid = await this.storage.storeMetadata(metaData); - return overrides - ? this.contract.createAllowlist(signerAddress, totalUnits, tree.root, cid, transferRestriction, overrides) - : this.contract.createAllowlist(signerAddress, totalUnits, tree.root, cid, transferRestriction); + const { request } = await this._publicClient.simulateContract({ + functionName: "createAllowlist", + account: operator.account, + args: [operator.account?.address, totalUnits, tree.root, cid, transferRestriction], + ...this.getContractConfig(), + ...this.getCleanedOverrides(overrides), + }); + + return operator.writeContract(request); }; /** @@ -194,29 +217,40 @@ export default class HypercertClient implements HypercertClientInterface { * @param fractions - Fractions of the Hypercert claim to split * @returns Contract transaction */ - splitClaimUnits = async (claimId: BigNumberish, fractions: BigNumberish[], overrides?: ethers.Overrides) => { + splitClaimUnits = async (claimId: bigint, fractions: bigint[], overrides?: SupportedOverrides) => { this.checkWritable(); - // check if claim exists and is owned by the signer - if (!ethers.Signer.isSigner(this._config.operator)) { - throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); + if (!this._walletClient) { + throw new ClientError("Could not connect to wallet; sending transactions not allowed."); } - const signerAddress = await this._config.operator.getAddress(); + const operator = this._walletClient; - const claimOwner = await this._contract.ownerOf(claimId); - if (claimOwner.toLowerCase() !== signerAddress.toLowerCase()) - throw new ClientError("Claim is not owned by the signer", { signer: signerAddress, claimOwner }); + const readContract = getContract({ + ...this.getContractConfig(), + publicClient: this._publicClient, + }); + + const claimOwner = await readContract.read.ownerOf([claimId]); + const totalUnits = (await readContract.read.unitsOf([claimId])) as bigint; + + if ((claimOwner as `0x${string}`).toLowerCase() !== operator.account?.address.toLowerCase()) + throw new ClientError("Claim is not owned by the signer", { signer: operator.account?.address, claimOwner }); // check if the sum of the fractions is equal to the total units - const totalUnits = await this._contract["unitsOf(uint256)"](claimId); - const sumFractions = fractions.reduce((a, b) => BigNumber.from(a).add(b), BigNumber.from(0)); - if (!BigNumber.from(sumFractions).eq(totalUnits)) + const sumFractions = fractions.reduce((a, b) => a + b, 0n); + if (sumFractions != totalUnits) throw new ClientError("Sum of fractions is not equal to the total units", { totalUnits, sumFractions }); - return overrides - ? this.contract.splitFraction(signerAddress, claimId, fractions, overrides) - : this.contract.splitFraction(signerAddress, claimId, fractions); + const { request } = await this._publicClient.simulateContract({ + functionName: "splitFraction", + account: operator.account, + args: [operator.account.address, claimId, fractions], + ...this.getContractConfig(), + ...this.getCleanedOverrides(overrides), + }); + + return operator.writeContract(request); }; /** @@ -225,28 +259,39 @@ export default class HypercertClient implements HypercertClientInterface { * @param claimIds - Hypercert claim ids * @returns Contract transaction */ - mergeClaimUnits = async (claimIds: BigNumberish[], overrides?: ethers.Overrides) => { + mergeClaimUnits = async (claimIds: bigint[], overrides?: SupportedOverrides) => { this.checkWritable(); - // check if all claims exist and are owned by the signer - if (!ethers.Signer.isSigner(this._config.operator)) { - throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); + if (!this._walletClient) { + throw new ClientError("Could not connect to wallet; sending transactions not allowed."); } + const operator = this._walletClient; - const signerAddress = await this._config.operator.getAddress(); + const readContract = getContract({ + ...this.getContractConfig(), + publicClient: this._publicClient, + }); - const claims = await Promise.all(claimIds.map(async (id) => ({ id, owner: await this._contract.ownerOf(id) }))); - if (claims.some((c) => c.owner.toLowerCase() !== signerAddress.toLowerCase())) { - const invalidClaimIDs = claims.filter((c) => c.owner !== signerAddress).map((c) => c.id); + const claims = await Promise.all( + claimIds.map(async (id) => ({ id, owner: await readContract.read.ownerOf([id]) })), + ); + if (claims.some((c) => (c.owner as `0x${string}`).toLowerCase() !== operator.account?.address.toLowerCase())) { + const invalidClaimIDs = claims.filter((c) => c.owner !== operator.account?.address).map((c) => c.id); throw new ClientError("One or more claims are not owned by the signer", { - signer: signerAddress, + signer: operator.account?.address, claims: invalidClaimIDs, }); } - return overrides - ? this.contract.mergeFractions(signerAddress, claimIds, overrides) - : this.contract.mergeFractions(signerAddress, claimIds); + const { request } = await this._publicClient.simulateContract({ + functionName: "mergeFractions", + account: operator.account, + args: [operator.account?.address, claimIds], + ...this.getContractConfig(), + ...this.getCleanedOverrides(overrides), + }); + + return operator.writeContract(request); }; /** @@ -255,22 +300,34 @@ export default class HypercertClient implements HypercertClientInterface { * @param claimId - Hypercert claim id * @returns Contract transaction */ - burnClaimFraction = async (claimId: BigNumberish, overrides?: ethers.Overrides) => { + burnClaimFraction = async (claimId: bigint, overrides?: SupportedOverrides) => { this.checkWritable(); - // check if claim exists and is owned by the signer - if (!ethers.Signer.isSigner(this._config.operator)) { - throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); + if (!this._walletClient) { + throw new ClientError("Could not connect to wallet; sending transactions not allowed."); } - const signerAddress = await this._config.operator.getAddress(); - const claimOwner = await this._contract.ownerOf(claimId); - if (claimOwner.toLowerCase() !== signerAddress.toLowerCase()) - throw new ClientError("Claim is not owned by the signer", { signer: signerAddress, claimOwner }); + const operator = this._walletClient; + + const readContract = getContract({ + ...this.getContractConfig(), + publicClient: this._publicClient, + }); + + const claimOwner = await readContract.read.ownerOf([claimId]); - return overrides - ? this.contract.burnFraction(signerAddress, claimId, overrides) - : this.contract.burnFraction(signerAddress, claimId); + if ((claimOwner as `0x${string}`).toLowerCase() !== operator.account?.address.toLowerCase()) + throw new ClientError("Claim is not owned by the signer", { signer: operator.account?.address, claimOwner }); + + const { request } = await this._publicClient.simulateContract({ + functionName: "burnFraction", + account: operator.account.address, + args: [operator.account.address, claimId], + ...this.getContractConfig(), + ...this.getCleanedOverrides(overrides), + }); + + return operator.writeContract(request); }; /** @@ -283,32 +340,40 @@ export default class HypercertClient implements HypercertClientInterface { * @returns Contract transaction */ mintClaimFractionFromAllowlist = async ( - claimId: BigNumberish, - units: BigNumberish, - proof: BytesLike[], - root?: BytesLike, - overrides?: ethers.Overrides, - ): Promise => { + claimId: bigint, + units: bigint, + proof: (Hex | ByteArray)[], + root?: Hex | ByteArray, + overrides?: SupportedOverrides, + ) => { this.checkWritable(); - if (!ethers.Signer.isSigner(this._config.operator)) { - throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); + if (!this._walletClient) { + throw new ClientError("Could not connect to wallet; sending transactions not allowed."); } - const signerAddress = await this._config.operator.getAddress(); + const operator = this._walletClient; + //verify the proof using the OZ merkle tree library if (root && root.length > 0) { + if (!operator.account?.address) throw new InvalidOrMissingError("No wallet address found, are you connected?"); verifyMerkleProof( root.toString(), - signerAddress, + operator.account?.address, units, proof.map((p) => p.toString()), ); } - return overrides - ? this.contract.mintClaimFromAllowlist(signerAddress, proof, claimId, units, overrides) - : this.contract.mintClaimFromAllowlist(signerAddress, proof, claimId, units); + const { request } = await this._publicClient.simulateContract({ + functionName: "mintClaimFromAllowlist", + account: operator.account, + args: [operator.account?.address, proof, claimId, units], + ...this.getContractConfig(), + ...this.getCleanedOverrides(overrides), + }); + + return operator.writeContract(request); }; /** @@ -322,37 +387,61 @@ export default class HypercertClient implements HypercertClientInterface { * @returns A Promise that resolves to the transaction receipt */ batchMintClaimFractionsFromAllowlists = async ( - claimIds: BigNumberish[], - units: BigNumberish[], - proofs: BytesLike[][], - roots?: BytesLike[], - overrides?: ethers.Overrides, - ): Promise => { + claimIds: bigint[], + units: bigint[], + proofs: (Hex | ByteArray)[][], + roots?: (Hex | ByteArray)[], + overrides?: SupportedOverrides, + ) => { this.checkWritable(); - if (!ethers.Signer.isSigner(this._config.operator)) { - throw new InvalidOrMissingError("Invalid operator: not a signer", { operator: this._config.operator }); + if (!this._walletClient) { + throw new ClientError("Could not connect to wallet; sending transactions not allowed."); } - const signerAddress = await this._config.operator.getAddress(); + const operator = this._walletClient; //verify the proof using the OZ merkle tree library if (roots && roots.length > 0) { + if (!operator.account?.address) throw new InvalidOrMissingError("No wallet address found, are you connected?"); + verifyMerkleProofs( roots.map((r) => r.toString()), - signerAddress, + operator.account?.address, units, proofs.map((p) => p.map((p) => p.toString())), ); } - return overrides - ? this.contract.batchMintClaimsFromAllowlists(signerAddress, proofs, claimIds, units, overrides) - : this.contract.batchMintClaimsFromAllowlists(signerAddress, proofs, claimIds, units); + const { request } = await this._publicClient.simulateContract({ + functionName: "batchMintClaimsFromAllowlists", + account: operator.account, + args: [operator.account?.address, proofs, claimIds, units], + ...this.getContractConfig(), + ...this.getCleanedOverrides(overrides), + }); + + return operator.writeContract(request); + }; + + private getContractConfig = () => { + return getContract({ + address: this.config.contractAddress as `0x${string}`, + abi: parseAbi(HypercertMinterAbi), + }); + }; + + private getCleanedOverrides = (overrides?: SupportedOverrides) => { + const _overrides = { + value: overrides?.value, + gas: overrides?.gasLimit, + gasPrice: overrides?.gasPrice, + }; + + return Object.fromEntries(Object.entries(_overrides).filter(([_, value]) => value !== undefined)); }; private checkWritable = () => { - //TODO add check on ContractRunner when migrating to ethers v6 if (this.readonly) throw new ClientError("Client is readonly", { client: this }); return true; diff --git a/sdk/src/constants.ts b/sdk/src/constants.ts index da4383b5..0ec67d33 100644 --- a/sdk/src/constants.ts +++ b/sdk/src/constants.ts @@ -2,7 +2,7 @@ * Constants */ -import { Deployment, SupportedChainIds } from "./types/index.js"; +import { Deployment, SupportedChainIds } from "./types"; // Goerli is default if nothing specified const DEFAULT_CHAIN_ID = 5; @@ -10,28 +10,20 @@ const DEFAULT_CHAIN_ID = 5; const DEFAULT_GRAPH_BASE_URL = "https://api.thegraph.com/subgraphs/name/hypercerts-admin"; // These are the deployments we manage -const DEPLOYMENTS: { [key in SupportedChainIds]: Deployment } = { +const DEPLOYMENTS: { [key in SupportedChainIds]: Partial } = { 5: { - chainId: 5, - chainName: "goerli", contractAddress: "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", graphUrl: `${DEFAULT_GRAPH_BASE_URL}/hypercerts-testnet`, } as const, 10: { - chainId: 10, - chainName: "optimism-mainnet", contractAddress: "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", graphUrl: `${DEFAULT_GRAPH_BASE_URL}/hypercerts-optimism-mainnet`, } as const, 42220: { - chainId: 42220, - chainName: "celo-mainnet", contractAddress: "0x16ba53b74c234c870c61efc04cd418b8f2865959", graphUrl: `${DEFAULT_GRAPH_BASE_URL}/hypercerts-celo`, }, 11155111: { - chainId: 11155111, - chainName: "sepolia", contractAddress: "0xa16DFb32Eb140a6f3F2AC68f41dAd8c7e83C4941", graphUrl: `${DEFAULT_GRAPH_BASE_URL}/hypercerts-sepolia`, } as const, diff --git a/sdk/src/evaluations/eas.ts b/sdk/src/evaluations/eas.ts deleted file mode 100644 index 3a7923b1..00000000 --- a/sdk/src/evaluations/eas.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { Offchain, SchemaEncoder, SignedOffchainAttestation } from "@ethereum-attestation-service/eas-sdk"; -import { TypedDataSigner } from "@ethersproject/abstract-signer"; -import { ethers } from "ethers"; - -import { EAS_SCHEMAS } from "../constants.js"; -import { - DuplicateEvaluation, - EvaluationData, - HypercertClientConfig, - InvalidOrMissingError, - MalformedDataError, - SimpleTextEvaluation, -} from "../types/index.js"; -import { validateDuplicateEvaluationData, validateSimpleTextEvaluationData } from "../validator/index.js"; - -/** - * The EasEvaluator class provides methods for signing off-chain attestations of evaluations. - * Schemas are stored on-chain in the Ethereum Attestation Service (EAS) contract. - */ -export default class EasEvaluator { - /** - * The Offchain instance used for signing off-chain attestations. - */ - offChain: Offchain; - - /** - * The TypedDataSigner instance used for signing typed data. - */ - signer?: ethers.Signer & TypedDataSigner; - - readonly = true; - - /** - * Creates a new EasEvaluator instance. - * @param {EasEvaluatorConfig} config - The configuration options for the EasEvaluator instance. - */ - constructor(config: Partial) { - const { easContractAddress, chainId, operator } = config; - - if (!easContractAddress || !chainId || !operator) { - const missingValue = !easContractAddress ? "easContractAddress" : !chainId ? "chainId" : "operator"; - - throw new InvalidOrMissingError(`Invalid or missing config value: ${missingValue}`, { easConfig: config }); - } - - //TODO when expanding the Evaluator functionallity, we should review if readonly makes sense - if (ethers.Signer.isSigner(config.operator)) { - this.signer = config.operator as ethers.Signer & TypedDataSigner; - this.readonly = false; - } - - this.offChain = new Offchain({ address: easContractAddress, chainId: chainId, version: "0.26" }); - } - - /** - * Gets a signature for an off-chain attestation. - * @param {string} encodedData - The encoded data to sign. - * @param {string} recipient - The address of the recipient of the attestation. - * @param {string} schemaUid - The UID of the schema to use for the attestation. - * @returns {Promise} - The signature for the attestation. - */ - getSignature = async ( - encodedData: string, - recipient: string, - schemaUid: string, - ): Promise => { - if (!this.signer) { - throw new InvalidOrMissingError("No valid signer available.", { signer: this.signer }); - } - - return await this.offChain.signOffchainAttestation( - { - // TODO who will be the recipient? The contract it points to? The creator? - recipient, - // Unix timestamp of when attestation expires. (0 for no expiration) - expirationTime: 0, - // Unix timestamp of current time - time: Date.now(), - revocable: true, - nonce: 0, - schema: schemaUid, - refUID: "0x0000000000000000000000000000000000000000000000000000000000000000", - data: encodedData, - }, - this.signer, - ); - }; - - /** - * Signs an offline evaluation. - * @param {EvaluationData} evaluation - The evaluation data to sign. - * @returns {Promise} - The signature for the evaluation. - * @throws {MalformedDataError} - If the evaluation data is malformed. - */ - signOfflineEvaluation = async (evaluation: EvaluationData) => { - if (isDuplicateEvaluation(evaluation)) { - const validation = validateDuplicateEvaluationData(evaluation); - if (!validation.valid) { - throw new MalformedDataError("Invalid evaluation data", { errors: validation.errors }); - } - - const duplicateSchema = EAS_SCHEMAS["sepolia"].duplicate; - const schemaEncoder = new SchemaEncoder(duplicateSchema.schema); - const recipient = evaluation.realHypercert.contract; - - // Initialize SchemaEncoder with the schema string - // TODO validate schema values - const encodedData = schemaEncoder.encodeData([ - { name: "chainId", value: evaluation.realHypercert.chainId as string, type: "uint256" }, - { name: "contract", value: evaluation.realHypercert.contract as string, type: "address" }, - { name: "claimId", value: evaluation.realHypercert.claimId as string, type: "uint256" }, - ]); - - return this.getSignature(encodedData, recipient, duplicateSchema.uid); - } - - if (isSimpleTextEvaluation(evaluation)) { - const validation = validateSimpleTextEvaluationData(evaluation); - if (!validation.valid) { - throw new MalformedDataError("Invalid evaluation data", { errors: validation.errors }); - } - - const simpleTextSchema = EAS_SCHEMAS["sepolia"].contentHash; - const schemaEncoder = new SchemaEncoder(simpleTextSchema.schema); - const recipient = evaluation.hypercert.contract; - - const contentHash = ethers.utils.id(evaluation.text); - - // Initialize SchemaEncoder with the schema string - // TODO validate schema values - const encodedData = schemaEncoder.encodeData([{ name: "contentHash", value: contentHash, type: "bytes32" }]); - - return this.getSignature(encodedData, recipient, simpleTextSchema.uid); - } - - assertNever(evaluation); - }; -} - -const isDuplicateEvaluation = (evaluation: EvaluationData): evaluation is DuplicateEvaluation => { - return ( - evaluation.type === "duplicate" && - "realHypercert" in evaluation && - "duplicateHypercerts" in evaluation && - "explanation" in evaluation - ); -}; - -const isSimpleTextEvaluation = (evaluation: EvaluationData): evaluation is SimpleTextEvaluation => { - return evaluation.type === "simpleText" && "hypercert" in evaluation && "text" in evaluation; -}; - -const assertNever = (evaluation: never): never => { - throw new Error(`Unexpected evaluation type: ${evaluation}`); -}; diff --git a/sdk/src/evaluations/index.ts b/sdk/src/evaluations/index.ts index 9092b0b7..33d501d8 100644 --- a/sdk/src/evaluations/index.ts +++ b/sdk/src/evaluations/index.ts @@ -1,20 +1,10 @@ -import type { TypedDataSigner } from "@ethersproject/abstract-signer"; -import { ethers } from "ethers"; import { isAddress } from "ethers/lib/utils.js"; +//eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import { CIDString } from "nft.storage"; -import { DEFAULT_CHAIN_ID } from "../constants.js"; import HypercertsStorage from "../storage.js"; -import { - EASEvaluation, - EvaluationSource, - HypercertClientConfig, - HypercertEvaluationSchema, - MalformedDataError, -} from "../types/index.js"; -import EasEvaluator from "./eas.js"; - -const EASContractAddress = "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"; // Sepolia v0.26 +import { HypercertClientConfig, HypercertEvaluationSchema, MalformedDataError } from "../types"; export interface EvaluatorInterface { /** @@ -26,28 +16,17 @@ export interface EvaluatorInterface { } export default class HypercertEvaluator implements EvaluatorInterface { - signer?: ethers.Signer & TypedDataSigner; - storage: HypercertsStorage; - eas: EasEvaluator; - readonly = true; - constructor( - config = { - chainId: DEFAULT_CHAIN_ID, - easContractAddress: EASContractAddress, - operator: new ethers.VoidSigner(""), - } as Partial, - ) { + constructor(config: Partial) { //TODO when expanding the Evaluator functionallity, we should review if readonly makes sense - if (ethers.Signer.isSigner(config.operator)) { - this.signer = config.operator as ethers.Signer & TypedDataSigner; + if (config?.walletClient?.account) { this.readonly = false; } + this.storage = new HypercertsStorage(config); - this.eas = new EasEvaluator(config); } submitEvaluation = async (evaluation: HypercertEvaluationSchema): Promise => { @@ -55,22 +34,6 @@ export default class HypercertEvaluator implements EvaluatorInterface { throw new MalformedDataError(`Invalid creator address: ${evaluation.creator}`); } - if (isEasEvaluation(evaluation.evaluationSource)) { - const signedData = await this.eas.signOfflineEvaluation(evaluation.evaluationData); - const evaluationData = { ...evaluation.evaluationData, signedData }; - - return this.storage.storeData({ ...evaluation, evaluationData }); - } - throw new Error(`Unexpected evaluation source: ${evaluation.evaluationSource.toString()}`); }; } - -const isEasEvaluation = (evaluationSource: EvaluationSource): evaluationSource is EASEvaluation => { - return ( - evaluationSource.type === "EAS" && - "chainId" in evaluationSource && - "contract" in evaluationSource && - "uid" in evaluationSource - ); -}; diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 4bbdfcd6..f1b6cf4c 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -1,9 +1,9 @@ import type { HypercertMinter, IHypercertToken } from "@hypercerts-org/contracts"; import { execute } from "../.graphclient"; -import HypercertClient from "./client.js"; -import HypercertsStorage from "./storage.js"; -import { DEPLOYMENTS } from "./constants.js"; +import HypercertClient from "./client"; +import HypercertsStorage from "./storage"; +import { DEPLOYMENTS } from "./constants"; /** * Protocol diff --git a/sdk/src/indexer.ts b/sdk/src/indexer.ts index 793e77ab..5fea7ba7 100644 --- a/sdk/src/indexer.ts +++ b/sdk/src/indexer.ts @@ -1,6 +1,6 @@ import { getBuiltGraphSDK, Sdk as GraphClient } from "../.graphclient"; -import { defaultQueryParams } from "./indexer/utils.js"; -import { HypercertIndexerInterface, QueryParams } from "./types/index.js"; +import { defaultQueryParams } from "./indexer/utils"; +import { HypercertIndexerInterface, QueryParams } from "./types"; /** * A class that provides indexing functionality for Hypercerts. diff --git a/sdk/src/storage.ts b/sdk/src/storage.ts index 8dd23c2a..a5d1bbb0 100644 --- a/sdk/src/storage.ts +++ b/sdk/src/storage.ts @@ -1,5 +1,9 @@ import axios from "axios"; +//eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import { CIDString, NFTStorage } from "nft.storage"; +//eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import { Blob, File, Web3Storage } from "web3.storage"; import { validateMetaData } from "./validator/index.js"; @@ -11,7 +15,7 @@ import { StorageError, } from "./types/index.js"; import logger from "./utils/logger.js"; -import { getConfig } from "./utils/config.js"; +import { getNftStorageToken, getWeb3StorageToken } from "./utils/config.js"; const getCid = (cidOrIpfsUri: string) => cidOrIpfsUri.replace("ipfs://", ""); @@ -31,13 +35,14 @@ export default class HypercertsStorage implements HypercertStorageInterface { * @param overrides The configuration overrides for the storage. */ constructor(overrides: Partial) { - const { nftStorageToken, web3StorageToken } = getConfig(overrides); + const { nftStorageToken } = getNftStorageToken(overrides); + const { web3StorageToken } = getWeb3StorageToken(overrides); - if (!nftStorageToken || nftStorageToken === "") { + if (!nftStorageToken) { logger.warn(`NFT Storage API key is missing or invalid: ${nftStorageToken}}`); } - if (!web3StorageToken || web3StorageToken === "") { + if (!web3StorageToken) { logger.warn(`Web3 Storage API key is missing or invalid: ${web3StorageToken}`); } @@ -45,8 +50,8 @@ export default class HypercertsStorage implements HypercertStorageInterface { logger.warn("HypercertsStorage is read only", "storage"); this.readonly = true; } else { - this.nftStorageClient = new NFTStorage({ token: nftStorageToken }); - this.web3StorageClient = new Web3Storage({ token: web3StorageToken }); + this.nftStorageClient = new NFTStorage({ token: nftStorageToken || "" }); + this.web3StorageClient = new Web3Storage({ web3StorageToken }); this.readonly = false; } } diff --git a/sdk/src/types/client.ts b/sdk/src/types/client.ts index 7d803a0c..94a94c7b 100644 --- a/sdk/src/types/client.ts +++ b/sdk/src/types/client.ts @@ -1,22 +1,25 @@ import { PartialTypedDataConfig } from "@ethereum-attestation-service/eas-sdk"; -import { HypercertMinter } from "@hypercerts-org/contracts"; -import { BigNumberish, BytesLike, ContractTransaction, ethers } from "ethers"; +//eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import { CIDString } from "nft.storage"; -import HypercertIndexer from "../indexer.js"; -import { AllowlistEntry, TransferRestrictions } from "./hypercerts.js"; -import { HypercertMetadata } from "./metadata.js"; +import HypercertIndexer from "../indexer"; +import { AllowlistEntry, TransferRestrictions } from "./hypercerts"; +import { HypercertMetadata } from "./metadata"; + +import { ByteArray, Chain, Hex, PublicClient, WalletClient, WriteContractReturnType } from "viem"; export type SupportedChainIds = 5 | 10 | 42220 | 11155111; +export type SupportedOverrides = { + value?: bigint; + gasPrice?: bigint; + gasLimit?: bigint; +}; /** * Represents a deployment of a contract on a specific network. */ -export type Deployment = { - /** The ID of the network on which the contract is deployed. */ - chainId: number; - /** The name of the network on which the contract is deployed. */ - chainName: string; +export type Deployment = Chain & { /** The address of the deployed contract. */ contractAddress: string; /** The url to the subgraph that indexes the contract events. Override for localized testing */ @@ -29,8 +32,9 @@ export type Deployment = { export type HypercertClientConfig = Deployment & HypercertStorageConfig & HypercertEvaluatorConfig & { - /** The provider is inherently read-only */ - operator: ethers.providers.Provider | ethers.Signer; + /** The PublicClient is inherently read-only */ + publicClient: PublicClient; + walletClient: WalletClient; /** Force the use of overridden values */ unsafeForceOverrideConfig?: boolean; }; @@ -110,8 +114,6 @@ export interface HypercertClientState { storage: HypercertStorageInterface; /** The indexer used by the client. */ indexer: HypercertIndexer; - /** The contract used by the client. */ - contract: HypercertMinter; } /** @@ -127,9 +129,9 @@ export interface HypercertClientMethods { */ mintClaim: ( metaData: HypercertMetadata, - totalUnits: BigNumberish, + totalUnits: bigint, transferRestriction: TransferRestrictions, - ) => Promise; + ) => Promise; /** * Creates a new allowlist and mints a new claim with the allowlist. @@ -142,9 +144,9 @@ export interface HypercertClientMethods { createAllowlist: ( allowList: AllowlistEntry[], metaData: HypercertMetadata, - totalUnits: BigNumberish, + totalUnits: bigint, transferRestriction: TransferRestrictions, - ) => Promise; + ) => Promise; /** * Splits a claim into multiple fractions. @@ -152,21 +154,21 @@ export interface HypercertClientMethods { * @param fractions The number of units for each fraction. * @returns A Promise that resolves to the transaction receipt */ - splitClaimUnits: (claimId: BigNumberish, fractions: BigNumberish[]) => Promise; + splitClaimUnits: (claimId: bigint, fractions: bigint[]) => Promise; /** * Merges multiple claim fractions into a single claim. * @param claimIds The IDs of the claim fractions to merge. * @returns A Promise that resolves to the transaction receipt */ - mergeClaimUnits: (claimIds: BigNumberish[]) => Promise; + mergeClaimUnits: (claimIds: bigint[]) => Promise; /** * Burns a claim fraction. * @param claimId The ID of the claim fraction to burn. * @returns A Promise that resolves to the transaction receipt */ - burnClaimFraction: (claimId: BigNumberish) => Promise; + burnClaimFraction: (claimId: bigint) => Promise; /** * Mints a claim fraction from an allowlist. @@ -176,10 +178,10 @@ export interface HypercertClientMethods { * @returns A Promise that resolves to the transaction receipt */ mintClaimFractionFromAllowlist: ( - claimId: BigNumberish, - units: BigNumberish, - proof: BytesLike[], - ) => Promise; + claimId: bigint, + units: bigint, + proof: (Hex | ByteArray)[], + ) => Promise; /** * Batch mints a claim fraction from an allowlist @@ -192,8 +194,8 @@ export interface HypercertClientMethods { * @returns A Promise that resolves to the transaction receipt */ batchMintClaimFractionsFromAllowlists: ( - claimIds: BigNumberish[], - units: BigNumberish[], - proofs: BytesLike[][], - ) => Promise; + claimIds: bigint[], + units: bigint[], + proofs: (Hex | ByteArray)[][], + ) => Promise; } diff --git a/sdk/src/types/hypercerts.ts b/sdk/src/types/hypercerts.ts index 31df75cb..9851d633 100644 --- a/sdk/src/types/hypercerts.ts +++ b/sdk/src/types/hypercerts.ts @@ -1,5 +1,3 @@ -import { BigNumberish } from "ethers"; - /** * Transfer restrictions for Hypercerts matching the definitions in the Hypercerts protocol * @dev AllowAll: All transfers are allowed @@ -21,5 +19,5 @@ export type TransferRestrictions = (typeof TransferRestrictions)[keyof typeof Tr */ export type AllowlistEntry = { address: string; - units: BigNumberish; + units: bigint; }; diff --git a/sdk/src/utils/adapters.ts b/sdk/src/utils/adapters.ts new file mode 100644 index 00000000..ed1e3fcf --- /dev/null +++ b/sdk/src/utils/adapters.ts @@ -0,0 +1,41 @@ +import { providers } from "ethers"; +import { PublicClient, HttpTransport, WalletClient } from "viem"; +import logger from "./logger.js"; +import { Signer, TypedDataSigner } from "@ethersproject/abstract-signer"; + +export function publicClientToProvider(publicClient: PublicClient) { + const { chain, transport } = publicClient; + if (!chain) { + logger.warn("No chain found in public client, stopping signature request."); + return; + } + const network = { + chainId: chain.id, + name: chain.name, + ensAddress: chain.contracts?.ensRegistry?.address, + }; + if (transport.type === "fallback") + return new providers.FallbackProvider( + (transport.transports as ReturnType[]).map( + ({ value }) => new providers.JsonRpcProvider(value?.url, network), + ), + ); + return new providers.JsonRpcProvider(transport.url, network); +} + +export function walletClientToSigner(walletClient: WalletClient) { + const { account, chain, transport } = walletClient; + if (!chain) { + logger.warn("No chain found in public client, stopping signature request."); + return; + } + const network = { + chainId: chain.id, + name: chain.name, + ensAddress: chain.contracts?.ensRegistry?.address, + }; + const provider = new providers.Web3Provider(transport, network); + const signer = provider.getSigner(account?.address); + + return signer as Signer & TypedDataSigner; +} diff --git a/sdk/src/utils/config.ts b/sdk/src/utils/config.ts index a9dfb228..ebfbf315 100644 --- a/sdk/src/utils/config.ts +++ b/sdk/src/utils/config.ts @@ -1,7 +1,6 @@ -import { ethers } from "ethers"; -import { isAddress } from "ethers/lib/utils.js"; +import { sepolia, goerli, optimism, celo, Chain } from "viem/chains"; -import { DEFAULT_CHAIN_ID, DEPLOYMENTS } from "../constants.js"; +import { DEPLOYMENTS } from "../constants"; import { ConfigurationError, Deployment, @@ -9,8 +8,9 @@ import { InvalidOrMissingError, SupportedChainIds, UnsupportedChainError, -} from "../types/index.js"; +} from "../types"; import logger from "./logger.js"; +import { createPublicClient, http, isAddress } from "viem"; /** * Returns the configuration for the Hypercert client, based on the given overrides. @@ -20,89 +20,95 @@ import logger from "./logger.js"; */ export const getConfig = (overrides: Partial) => { // Get the chainId, first from overrides, then environment variables, then the constant - const { chainId } = getChainConfig(overrides); + const chain = getChainConfig(overrides); + if (!chain) { + logger.warn("[getConfig]: No default config for chain found"); + } - let baseDeployment: Deployment & { unsafeForceOverrideConfig?: boolean }; + let baseDeployment: (Partial & { unsafeForceOverrideConfig?: boolean }) | undefined; if (overrides.unsafeForceOverrideConfig) { - if (!overrides.chainName || !overrides.contractAddress || !overrides.graphUrl) { - throw new UnsupportedChainError( - `attempted to override with chainId=${chainId}, but requires chainName, graphUrl, and contractAddress to be set`, - { chainID: chainId?.toString() || "undefined" }, + if (!overrides.id || !overrides.contractAddress || !overrides.graphUrl) { + throw new InvalidOrMissingError( + `attempted to override with chainId=${overrides.id}, but requires chainName, graphUrl, and contractAddress to be set`, + { + chainID: overrides.id?.toString(), + graphUrl: overrides.graphUrl, + contractAddress: overrides.contractAddress, + }, ); } baseDeployment = { - chainId: chainId, - chainName: overrides.chainName, + ...chain, + id: overrides.id, contractAddress: overrides.contractAddress, graphUrl: overrides.graphUrl, unsafeForceOverrideConfig: overrides.unsafeForceOverrideConfig, }; } else { - if (!chainId || [5, 10, 42220, 11155111].indexOf(chainId) === -1) { - throw new UnsupportedChainError(`chainId=${chainId} is not yet supported`, { - chainID: chainId?.toString() || "undefined", - }); - } - - baseDeployment = DEPLOYMENTS[chainId as SupportedChainIds]; + //TODO doo many casts + baseDeployment = overrides.id + ? (DEPLOYMENTS[overrides.id as SupportedChainIds] as Partial & { + unsafeForceOverrideConfig?: boolean; + }) + : chain?.id + ? (DEPLOYMENTS[chain.id as SupportedChainIds] as Partial & { unsafeForceOverrideConfig?: boolean }) + : undefined; if (!baseDeployment) { - throw new UnsupportedChainError(`Default config for chainId=${chainId} is missing in SDK`, { - chainID: chainId, + throw new UnsupportedChainError(`Default config for chainId=${overrides.id} is missing in SDK`, { + chainID: overrides.id, }); } + + baseDeployment = { ...chain, ...baseDeployment }; } - const config = { + const config: Partial = { // Start with the hardcoded values ...baseDeployment, // Let the user override from environment variables - ...getChainConfig(overrides), - ...getOperator(overrides), + ...getWalletClient(overrides), + ...getPublicClient(overrides), ...getContractAddress(overrides), ...getGraphUrl(overrides), ...getNftStorageToken(overrides), ...getWeb3StorageToken(overrides), ...getEasContractAddress(overrides), - } as HypercertClientConfig; + }; + + const missingKeys = []; for (const [key, value] of Object.entries(config)) { if (!value) { - logger.warn(`Cannot get chain config. ${key} is possibly undefined`); + missingKeys.push(key); } } + if (missingKeys.length > 0) logger.warn(`Missing properties in config: ${missingKeys.join(", ")}`); + return config; }; const getChainConfig = (overrides: Partial) => { - const chainId = - overrides?.chainId ?? (process.env.DEFAULT_CHAIN_ID ? parseInt(process.env.DEFAULT_CHAIN_ID) : DEFAULT_CHAIN_ID); - let chainName: string; - - switch (chainId) { - case 5: - chainName = "goerli"; - break; - case 10: - chainName = "optimism-mainnet"; - break; - case 42220: - chainName = "celo"; - break; - case 11155111: - chainName = "sepolia"; - break; - default: - chainName = overrides?.chainName ?? ""; - if (!chainName) { - throw new UnsupportedChainError(`chainId=${chainId} is not yet supported`, { - chainID: chainId?.toString() || "undefined", - }); - } + const chainId = overrides?.id + ? overrides.id + : process.env.DEFAULT_CHAIN_ID + ? parseInt(process.env.DEFAULT_CHAIN_ID) + : undefined; + + if (!chainId) { + throw new ConfigurationError("No chainId specified in config or environment variables"); } - return { chainId, chainName }; + const chain = getDefaultChain(chainId); + + if (!chain) { + throw new UnsupportedChainError(`No default config for chainId=${chainId} found in SDK`, { + chainID: chainId?.toString(), + }); + } + + return chain; }; const getContractAddress = (overrides: Partial) => { @@ -134,12 +140,12 @@ const getGraphUrl = (overrides: Partial) => { return { graphUrl }; } - const { chainId } = getChainConfig(overrides); + const chain = getChainConfig(overrides); - graphUrl = DEPLOYMENTS[chainId as keyof typeof DEPLOYMENTS].graphUrl ?? process.env.GRAPH_URL; + graphUrl = DEPLOYMENTS[chain?.id as keyof typeof DEPLOYMENTS].graphUrl ?? process.env.GRAPH_URL; if (!graphUrl) { - throw new UnsupportedChainError(`chainId=${chainId} is not yet supported`, { - chainID: chainId?.toString() || "undefined", + throw new UnsupportedChainError(`No Graph URL found in deployments or env vars`, { + chainID: chain?.toString(), }); } try { @@ -151,42 +157,33 @@ const getGraphUrl = (overrides: Partial) => { return { graphUrl }; }; -const getOperator = (overrides: Partial) => { - let operator: ethers.Signer | ethers.providers.Provider; - - if ( - overrides.operator && - !ethers.providers.Provider.isProvider(overrides.operator) && - !ethers.Signer.isSigner(overrides.operator) - ) { - throw new InvalidOrMissingError("Invalid operator.", { operator: overrides.operator }); - } - - if (ethers.Signer.isSigner(overrides.operator)) { - operator = overrides.operator; - } else if (ethers.providers.Provider.isProvider(overrides.operator)) { - operator = overrides.operator; - operator.on("network", (newNetwork, oldNetwork) => { - // When a Provider makes its initial connection, it emits a "network" - // event with a null oldNetwork along with the newNetwork. So, if the - // oldNetwork exists, it represents a changing network - - if (typeof window === "undefined") return; - if (oldNetwork && window.location) { - window.location.reload(); - } - }); - } else if (process.env.PRIVATE_KEY) { - const provider = ethers.getDefaultProvider(DEFAULT_CHAIN_ID); - operator = new ethers.Wallet(process.env.PRIVATE_KEY, provider); - } else { - operator = ethers.getDefaultProvider(DEFAULT_CHAIN_ID); +const getWalletClient = (overrides: Partial) => { + const walletClient = overrides.walletClient; + + if (!walletClient) { + logger.warn("No wallet client found", "getWalletClient", walletClient); + } + + return { walletClient }; +}; + +const getPublicClient = (overrides: Partial) => { + const chain = getChainConfig(overrides); + let publicClient; + + publicClient = createPublicClient({ + chain: chain, + transport: http(), + }); + + if (overrides.publicClient) { + publicClient = overrides.publicClient; } - return { operator }; + return { publicClient }; }; -const getNftStorageToken = (overrides: Partial) => { +export const getNftStorageToken = (overrides: Partial) => { if (overrides.nftStorageToken) { return { nftStorageToken: overrides.nftStorageToken }; } @@ -202,7 +199,7 @@ const getNftStorageToken = (overrides: Partial) => { return {}; }; -const getWeb3StorageToken = (overrides: Partial) => { +export const getWeb3StorageToken = (overrides: Partial) => { if (overrides.web3StorageToken) { return { web3StorageToken: overrides.web3StorageToken }; } @@ -225,3 +222,15 @@ const getEasContractAddress = (overrides: Partial) => { return { easContractAddress: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e" }; }; + +const getDefaultChain = (chainId: number) => { + const _chains = [sepolia, goerli, optimism, celo]; + + for (const chain of Object.values(_chains)) { + if ("id" in chain) { + if (chain.id === chainId) { + return chain as Chain; + } + } + } +}; diff --git a/sdk/src/validator/index.ts b/sdk/src/validator/index.ts index b24244ce..2a9a8e25 100644 --- a/sdk/src/validator/index.ts +++ b/sdk/src/validator/index.ts @@ -1,7 +1,5 @@ import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; import Ajv from "ajv"; -import { BigNumber, BigNumberish } from "ethers"; -import { isAddress } from "ethers/lib/utils.js"; import claimDataSchema from "../resources/schema/claimdata.json"; import evaluationSchema from "../resources/schema/evaluation.json"; @@ -14,6 +12,7 @@ import { MintingError, SimpleTextEvaluation, } from "../types/index.js"; +import { isAddress } from "viem"; const ajv = new Ajv({ allErrors: true }); // options can be passed, e.g. {allErrors: true} ajv.addSchema(metaDataSchema, "metaData"); @@ -88,16 +87,16 @@ const validateClaimData = (data: HypercertClaimdata): ValidationResult => { * @param units The total number of units in the allowlist. * @returns A `ValidationResult` object indicating whether the data is valid and any errors that were found. */ -const validateAllowlist = (data: AllowlistEntry[], units: BigNumberish) => { +const validateAllowlist = (data: AllowlistEntry[], units: bigint) => { const errors: Record = {}; - const totalUnits = data.reduce((acc, curr) => acc.add(curr.units), BigNumber.from(0)); - if (!totalUnits.eq(units)) { + const totalUnits = data.reduce((acc, curr) => acc + BigInt(curr.units.toString()), 0n); + if (totalUnits != units) { errors[ "units" ] = `Total units in allowlist must match total units [expected: ${units}, got: ${totalUnits.toString()}]`; } - if (totalUnits.eq(0)) { + if (totalUnits == 0n) { errors["units"] = "Total units in allowlist must be greater than 0"; } @@ -167,7 +166,7 @@ const validateSimpleTextEvaluationData = (data: SimpleTextEvaluation): Validatio * @param proof The Merkle proof to verify. * @throws {MintingError} If the Merkle proof verification fails. */ -function verifyMerkleProof(root: string, signerAddress: string, units: BigNumberish, proof: string[]): void { +function verifyMerkleProof(root: string, signerAddress: string, units: bigint, proof: string[]): void { if (!isAddress(signerAddress)) { throw new MintingError("Invalid address", { signerAddress }); } @@ -187,7 +186,7 @@ function verifyMerkleProof(root: string, signerAddress: string, units: BigNumber * @throws {MintingError} If the Merkle proof verification fails. * @notice Wrapper around `verifyMerkleProof` to batch verify multiple proofs */ -function verifyMerkleProofs(roots: string[], signerAddress: string, units: BigNumberish[], proofs: string[][]) { +function verifyMerkleProofs(roots: string[], signerAddress: string, units: bigint[], proofs: string[][]) { if (roots.length !== units.length || units.length !== proofs.length) { throw new MintingError("Invalid input", { roots, units, proofs }); } diff --git a/sdk/test/client.test.ts b/sdk/test/client.test.ts index 8540404b..297c490b 100644 --- a/sdk/test/client.test.ts +++ b/sdk/test/client.test.ts @@ -1,13 +1,9 @@ import { expect } from "chai"; -import { MockProvider } from "ethereum-waffle"; -import { ethers } from "ethers"; import sinon from "sinon"; import { HypercertClient, HypercertMetadata, TransferRestrictions } from "../src/index.js"; import { AllowlistEntry, ClientError, UnsupportedChainError } from "../src/types/index.js"; - -const provider = new MockProvider(); -sinon.stub(provider, "on"); +import { publicClient, walletClient } from "./helpers.js"; describe("HypercertClient setup tests", () => { afterAll(() => { @@ -15,35 +11,33 @@ describe("HypercertClient setup tests", () => { }); it("should be able to create a new read only instance when missing storage keys", () => { - sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: null }); - sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN: null }); - sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: null }); - sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN: null }); + const readOnlyClient = new HypercertClient({ + id: 5, + publicClient, + }); - const client = new HypercertClient({ operator: provider }); - - expect(client).to.be.an.instanceOf(HypercertClient); - expect(client.readonly).to.be.true; + expect(readOnlyClient).to.be.an.instanceOf(HypercertClient); + expect(readOnlyClient.readonly).to.be.true; }); it("should be able to create a new instance", () => { - const operator = ethers.Wallet.createRandom(); - - const config = { chainId: 5, operator, nftStorageToken: "test", web3StorageToken: "test" }; + const config = { id: 5, publicClient, walletClient, nftStorageToken: "test", web3StorageToken: "test" }; const client = new HypercertClient(config); expect(client).to.be.an.instanceOf(HypercertClient); + + //TODO currently only publicClient added as a test, also add other flows expect(client.readonly).to.be.false; }); it("should throw an error when the chainId is not supported", () => { try { - new HypercertClient({ operator: provider, chainId: 1337 }); + new HypercertClient({ id: 1337 }); expect.fail("Should throw UnsupportedChainError"); } catch (e) { expect(e).to.be.instanceOf(UnsupportedChainError); const error = e as UnsupportedChainError; - expect(error.message).to.eq("chainId=1337 is not yet supported"); + expect(error.message).to.eq("No default config for chainId=1337 found in SDK"); expect(Number(error.payload?.chainID)).to.eq(1337); } }); @@ -54,12 +48,12 @@ describe("HypercertClient setup tests", () => { sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: null }); sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN: null }); - const client = new HypercertClient({ operator: provider }); + const client = new HypercertClient({ id: 5 }); // mintClaim try { const metaData = { name: "test" } as HypercertMetadata; - const totalUnits = 1; + const totalUnits = 1n; const transferRestrictions = TransferRestrictions.AllowAll; await client.mintClaim(metaData, totalUnits, transferRestrictions); @@ -74,9 +68,9 @@ describe("HypercertClient setup tests", () => { // createAllowlist try { - const allowlist: AllowlistEntry[] = [{ address: "0x0000000", units: 100 }]; + const allowlist: AllowlistEntry[] = [{ address: "0x0000000", units: 100n }]; const metaData = { name: "test" } as HypercertMetadata; - const totalUnits = 1; + const totalUnits = 1n; const transferRestrictions = TransferRestrictions.AllowAll; await client.createAllowlist(allowlist, metaData, totalUnits, transferRestrictions); @@ -91,8 +85,8 @@ describe("HypercertClient setup tests", () => { // splitClaimUnits try { - const claimId = 1; - const fractions = [100, 200]; + const claimId = 1n; + const fractions = [100n, 200n]; await client.splitClaimUnits(claimId, fractions); expect.fail("Should throw ClientError"); @@ -106,7 +100,7 @@ describe("HypercertClient setup tests", () => { // mergeClaimUnits try { - const claimIds = [1, 2]; + const claimIds = [1n, 2n]; await client.mergeClaimUnits(claimIds); expect.fail("Should throw ClientError"); @@ -120,7 +114,7 @@ describe("HypercertClient setup tests", () => { // burnClaimFraction try { - const claimId = 1; + const claimId = 1n; await client.burnClaimFraction(claimId); expect.fail("Should throw ClientError"); @@ -134,10 +128,10 @@ describe("HypercertClient setup tests", () => { // mintClaimFractionFromAllowlist try { - const claimId = 1; - const units = 100; - const proof = ["0x1", "0x2", "0x3"]; - const root = "0x4"; + const claimId = 1n; + const units = 100n; + const proof = ["0x1", "0x2", "0x3"] as `0x${string}`[]; + const root = "0x4" as `0x${string}`; await client.mintClaimFractionFromAllowlist(claimId, units, proof, root); expect.fail("Should throw ClientError"); @@ -151,13 +145,10 @@ describe("HypercertClient setup tests", () => { // batchMintClaimFractionsFromAllowlist try { - const claimIds = [1, 2]; - const units = [100, 200]; - const proofs = [ - ["0x1", "0x2", "0x3"], - ["0x4", "0x5", "0x6"], - ]; - const roots = ["0x7", "0x8"]; + const claimIds = [1n, 2n]; + const units = [100n, 200n]; + const proofs = [["0x1", "0x2", "0x3"] as `0x${string}`[], ["0x4", "0x5", "0x6"] as `0x${string}`[]]; + const roots = ["0x7", "0x8"] as `0x${string}`[]; await client.batchMintClaimFractionsFromAllowlists(claimIds, units, proofs, roots); expect.fail("Should throw ClientError"); diff --git a/sdk/test/client/allowlist.minting.test.ts b/sdk/test/client/allowlist.minting.test.ts index b2b9eb3c..b9881375 100644 --- a/sdk/test/client/allowlist.minting.test.ts +++ b/sdk/test/client/allowlist.minting.test.ts @@ -1,59 +1,56 @@ -import { MockContract, MockProvider, deployMockContract } from "ethereum-waffle"; -import { BigNumber, ethers } from "ethers"; import sinon from "sinon"; import { expect } from "@jest/globals"; -import { HypercertClient } from "../../src/index.js"; +import { HypercertClient } from "../../src"; import HypercertsStorage from "../../src/storage.js"; -import { MalformedDataError, MintingError, TransferRestrictions } from "../../src/types/index.js"; -import { getAllowlist, getFormattedMetadata } from "../helpers.js"; -import { HypercertMinter, HypercertMinterAbi } from "@hypercerts-org/contracts"; +import { MalformedDataError, MintingError, TransferRestrictions } from "../../src/types"; +import { getAllowlist, getFormattedMetadata, publicClient, walletClient } from "../helpers"; +import { HypercertMinterAbi } from "@hypercerts-org/contracts"; +import { encodeFunctionResult, isHex, parseAbi, stringToHex } from "viem"; + const mockCorrectMetadataCid = "testCID1234fkreigdm2flneb4khd7eixodagst5nrndptgezrjux7gohxcngjn67x6u"; describe("Allows for minting claims from an allowlist", () => { const metaDataStub = sinon.stub(HypercertsStorage.prototype, "storeMetadata").resolves(mockCorrectMetadataCid); const dataStub = sinon.stub(HypercertsStorage.prototype, "storeData").resolves(mockCorrectMetadataCid); + const wallet = walletClient; + const userAddress = wallet.account.address; + const client = new HypercertClient({ + id: 5, + walletClient, + publicClient, + }); - const setUp = async () => { - const provider = new MockProvider(); - const [user, other, admin] = provider.getWallets(); - const stub = sinon.stub(provider, "on"); + const readSpy = sinon.stub(publicClient, "request"); + let writeSpy = sinon.stub(walletClient, "writeContract"); - const minter = await deployMockContract(user, HypercertMinterAbi); + const mintClaimFromAllowlistResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "mintClaimFromAllowlist", + result: [], + }); - const client = new HypercertClient({ - chainId: 5, - operator: user, - }); + const batchMintClaimFromAllowlistResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "batchMintClaimsFromAllowlists", + result: [], + }); - sinon.replaceGetter(client, "contract", () => minter as unknown as HypercertMinter); - - return { - client, - provider, - users: { user, other, admin }, - minter, - stub, - }; - }; - - let _client: HypercertClient; - let _provider: MockProvider; - let _users: { user: ethers.Wallet; other: ethers.Wallet; admin: ethers.Wallet }; - let _minter: MockContract; - let _stub: sinon.SinonStub; - - beforeAll(async () => { - const { client, provider, users, minter, stub } = await setUp(); - _client = client; - _provider = provider; - _users = users; - _minter = minter; - _stub = stub; + const mintClaimResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "createAllowlist", + result: [], }); - beforeEach(() => { - _provider.clearCallHistory(); + beforeEach(async () => { + readSpy.resetBehavior(); + readSpy.resetHistory(); + + writeSpy.resetBehavior(); + writeSpy.resetHistory(); + + metaDataStub.resetHistory(); + dataStub.resetHistory(); }); afterAll(() => { @@ -65,22 +62,24 @@ describe("Allows for minting claims from an allowlist", () => { const { allowlist, totalUnits } = getAllowlist(); const metaData = getFormattedMetadata(); - await _minter.mock.createAllowlist.returns(); - const res = await _client.createAllowlist(allowlist, metaData, totalUnits, TransferRestrictions.FromCreatorOnly); + writeSpy = writeSpy.resolves(mintClaimResult); - sinon.assert.calledOnce(metaDataStub); - sinon.assert.calledOnce(dataStub); + const hash = await client.createAllowlist(allowlist, metaData, totalUnits, TransferRestrictions.FromCreatorOnly); - expect(res.chainId).toBe(1337); - expect(_provider.callHistory.length).toBe(2); + expect(isHex(hash)).toBeTruthy(); + expect(metaDataStub.callCount).toBe(1); + expect(dataStub.callCount).toBe(1); + expect(readSpy.callCount).toBe(0); + expect(writeSpy.callCount).toBe(1); }); it("should not create an allowlist if the total units mismatch", async () => { const { allowlist, totalUnits } = getAllowlist(); const metaData = getFormattedMetadata(); + let hash; try { - await _client.createAllowlist(allowlist, metaData, totalUnits.add(1), TransferRestrictions.FromCreatorOnly); + hash = await client.createAllowlist(allowlist, metaData, totalUnits + 1n, TransferRestrictions.FromCreatorOnly); } catch (e) { expect(e instanceof MalformedDataError).toBeTruthy(); @@ -91,28 +90,40 @@ describe("Allows for minting claims from an allowlist", () => { }); } - expect(_provider.callHistory.length).toBe(0); - expect.assertions(4); + expect(hash).toBeUndefined(); + expect(metaDataStub.callCount).toBe(0); + expect(dataStub.callCount).toBe(0); + expect(readSpy.callCount).toBe(0); + expect(writeSpy.callCount).toBe(0); + expect.assertions(8); }); it("should not create an allowlist if the allowlist is empty", async () => { - const { allowlist, totalUnits } = getAllowlist({ size: 1 }); + const { allowlist, totalUnits } = getAllowlist(); const metaData = getFormattedMetadata(); - allowlist[0].units = BigNumber.from(0); + let hash; + + allowlist[0].units = 0n; try { - await _client.createAllowlist(allowlist, metaData, totalUnits, TransferRestrictions.FromCreatorOnly); + hash = await client.createAllowlist(allowlist, metaData, totalUnits, TransferRestrictions.FromCreatorOnly); } catch (e) { expect(e instanceof MalformedDataError).toBeTruthy(); const error = e as MalformedDataError; expect(error.message).toBe("Allowlist validation failed"); - expect(error.payload).toEqual({ units: "Total units in allowlist must be greater than 0" }); + expect(error.payload).toEqual({ + units: "Total units in allowlist must match total units [expected: 10, got: 9]", + }); } - expect(_provider.callHistory.length).toBe(0); - expect.assertions(4); + expect(hash).toBeUndefined(); + expect(metaDataStub.callCount).toBe(0); + expect(dataStub.callCount).toBe(0); + expect(readSpy.callCount).toBe(0); + expect(writeSpy.callCount).toBe(0); + expect.assertions(8); }); }); @@ -120,41 +131,53 @@ describe("Allows for minting claims from an allowlist", () => { it("should allow to mint a claim from an allowlist without the root", async () => { const { allowlist, merkleTree } = getAllowlist({ size: 1 }); - await _minter.mock.mintClaimFromAllowlist.returns(); + writeSpy = writeSpy.resolves(mintClaimFromAllowlistResult); - await _client.mintClaimFractionFromAllowlist( - 1, + const hash = await client.mintClaimFractionFromAllowlist( + 1n, allowlist[0].units, - merkleTree.getProof([allowlist[0].address, allowlist[0].units.toString()]), + merkleTree.getProof([allowlist[0].address, allowlist[0].units.toString()]) as `0x${string}`[], ); - expect(_provider.callHistory.length).toBe(2); + expect(isHex(hash)).toBeTruthy(); + expect(metaDataStub.callCount).toBe(0); + expect(dataStub.callCount).toBe(0); + expect(readSpy.callCount).toBe(0); + expect(writeSpy.callCount).toBe(1); + expect.assertions(5); }); it("should allow to mint a claim from an allowlist with a correct root", async () => { - const { allowlist, merkleTree } = getAllowlist({ size: 1, address: _users.user.address as `0x${string}` }); + const { allowlist, merkleTree } = getAllowlist({ size: 1, address: userAddress }); - await _minter.mock.mintClaimFromAllowlist.returns(); + writeSpy = writeSpy.resolves(mintClaimFromAllowlistResult); - await _client.mintClaimFractionFromAllowlist( - 1, + const hash = await client.mintClaimFractionFromAllowlist( + 1n, allowlist[0].units, - merkleTree.getProof([allowlist[0].address, allowlist[0].units.toString()]), - merkleTree.root, + merkleTree.getProof([allowlist[0].address, allowlist[0].units.toString()]) as `0x${string}`[], + merkleTree.root as `0x${string}`, ); - expect(_provider.callHistory.length).toBe(2); + expect(isHex(hash)).toBeTruthy(); + expect(metaDataStub.callCount).toBe(0); + expect(dataStub.callCount).toBe(0); + expect(readSpy.callCount).toBe(0); + expect(writeSpy.callCount).toBe(1); + expect.assertions(5); }); it("should not allow to mint a claim from an allowlist with an incorrect root", async () => { - const { allowlist, merkleTree } = getAllowlist({ size: 1, address: _users.user.address as `0x${string}` }); + const { allowlist, merkleTree } = getAllowlist({ size: 1, address: userAddress }); + + const mockRoot = stringToHex("MOCK_ROOT", { size: 32 }); - const mockRoot = ethers.utils.formatBytes32String("MOCK_ROOT"); + let hash; try { - await _client.mintClaimFractionFromAllowlist( - 1, + hash = await client.mintClaimFractionFromAllowlist( + 1n, allowlist[0].units, - merkleTree.getProof([allowlist[0].address, allowlist[0].units.toString()]), + merkleTree.getProof([allowlist[0].address, allowlist[0].units.toString()]) as `0x${string}`[], mockRoot, ); } catch (e) { @@ -168,17 +191,21 @@ describe("Allows for minting claims from an allowlist", () => { }); } - expect(_provider.callHistory.length).toBe(0); - expect.assertions(4); + expect(hash).toBeUndefined(); + expect(metaDataStub.callCount).toBe(0); + expect(dataStub.callCount).toBe(0); + expect(readSpy.callCount).toBe(0); + expect(writeSpy.callCount).toBe(0); + expect.assertions(8); }); }); describe("Batch mint fractions", () => { it("should allow to batch mint a claim from an allowlist without the root", async () => { const firstList = getAllowlist({ size: 1 }); - const secondList = getAllowlist({ size: 1, units: 42 }); + const secondList = getAllowlist({ size: 1, units: 42n }); - await _minter.mock.batchMintClaimsFromAllowlists.returns(); + writeSpy = writeSpy.resolves(batchMintClaimFromAllowlistResult); const firstProofs = firstList.merkleTree.getProof([ firstList.allowlist[0].address, @@ -188,20 +215,25 @@ describe("Allows for minting claims from an allowlist", () => { secondList.allowlist[0].address, secondList.allowlist[0].units.toString(), ]); - await _client.batchMintClaimFractionsFromAllowlists( - [1, 2], + const hash = await client.batchMintClaimFractionsFromAllowlists( + [1n, 2n], [firstList.allowlist[0].units, secondList.allowlist[0].units], - [firstProofs, secondProofs], + [firstProofs, secondProofs] as `0x${string}`[][], ); - expect(_provider.callHistory.length).toBe(2); + expect(isHex(hash)).toBeTruthy(); + expect(metaDataStub.callCount).toBe(0); + expect(dataStub.callCount).toBe(0); + expect(readSpy.callCount).toBe(0); + expect(writeSpy.callCount).toBe(1); + expect.assertions(5); }); it("should allow to mint a claim from an allowlist with a correct root", async () => { - const firstList = getAllowlist({ size: 1, address: _users.user.address as `0x${string}` }); - const secondList = getAllowlist({ size: 1, units: 42, address: _users.user.address as `0x${string}` }); + const firstList = getAllowlist({ size: 1, address: userAddress }); + const secondList = getAllowlist({ size: 1, units: 42n, address: userAddress }); - await _minter.mock.batchMintClaimsFromAllowlists.returns(); + writeSpy = writeSpy.resolves(batchMintClaimFromAllowlistResult); const firstProofs = firstList.merkleTree.getProof([ firstList.allowlist[0].address, @@ -211,21 +243,26 @@ describe("Allows for minting claims from an allowlist", () => { secondList.allowlist[0].address, secondList.allowlist[0].units.toString(), ]); - await _client.batchMintClaimFractionsFromAllowlists( - [1, 2], + const hash = await client.batchMintClaimFractionsFromAllowlists( + [1n, 2n], [firstList.allowlist[0].units, secondList.allowlist[0].units], - [firstProofs, secondProofs], - [firstList.merkleTree.root, secondList.merkleTree.root], + [firstProofs, secondProofs] as `0x${string}`[][], + [firstList.merkleTree.root, secondList.merkleTree.root] as `0x${string}`[], ); - expect(_provider.callHistory.length).toBe(2); + expect(isHex(hash)).toBeTruthy(); + expect(metaDataStub.callCount).toBe(0); + expect(dataStub.callCount).toBe(0); + expect(readSpy.callCount).toBe(0); + expect(writeSpy.callCount).toBe(1); + expect.assertions(5); }); it("should not allow to mint a claim from an allowlist with an incorrect root", async () => { - const firstList = getAllowlist({ size: 1, address: _users.user.address as `0x${string}` }); - const secondList = getAllowlist({ size: 1, units: 42, address: _users.user.address as `0x${string}` }); + const firstList = getAllowlist({ size: 1, address: userAddress }); + const secondList = getAllowlist({ size: 1, units: 42n, address: userAddress }); - await _minter.mock.batchMintClaimsFromAllowlists.returns(); + writeSpy = writeSpy.resolves(batchMintClaimFromAllowlistResult); const firstProofs = firstList.merkleTree.getProof([ firstList.allowlist[0].address, @@ -236,13 +273,14 @@ describe("Allows for minting claims from an allowlist", () => { secondList.allowlist[0].units.toString(), ]); - const mockRoot = ethers.utils.formatBytes32String("MOCK_ROOT"); + const mockRoot = stringToHex("MOCK_ROOT", { size: 32 }); + let hash; try { - await _client.batchMintClaimFractionsFromAllowlists( - [1, 2], + hash = await client.batchMintClaimFractionsFromAllowlists( + [1n, 2n], [firstList.allowlist[0].units, secondList.allowlist[0].units], - [firstProofs, secondProofs], - [firstList.merkleTree.root, mockRoot], + [firstProofs, secondProofs] as `0x${string}`[][], + [firstList.merkleTree.root as `0x${string}`, mockRoot], ); } catch (e) { expect(e instanceof MintingError).toBeTruthy(); @@ -255,8 +293,12 @@ describe("Allows for minting claims from an allowlist", () => { }); } - // Signer getAddress - expect(_provider.callHistory.length).toBe(1); + expect(hash).toBeUndefined(); + expect(metaDataStub.callCount).toBe(0); + expect(dataStub.callCount).toBe(0); + expect(readSpy.callCount).toBe(0); + expect(writeSpy.callCount).toBe(0); + expect.assertions(8); }); }); }); diff --git a/sdk/test/client/burn.test.ts b/sdk/test/client/burn.test.ts index c0d83887..f5c1de5a 100644 --- a/sdk/test/client/burn.test.ts +++ b/sdk/test/client/burn.test.ts @@ -1,66 +1,80 @@ -import { MockProvider, deployMockContract } from "ethereum-waffle"; -import { BigNumber, Wallet } from "ethers"; +import HypercertClient from "../../src/client"; +import { HypercertMinterAbi } from "@hypercerts-org/contracts"; +import { walletClient, publicClient } from "../helpers"; +import { encodeFunctionResult, isHex, parseAbi } from "viem"; import sinon from "sinon"; +import { faker } from "@faker-js/faker"; +import { ClientError } from "../../src"; -import HypercertClient from "../../src/client.js"; -import { ClientError } from "../../src/types/errors.js"; -import { HypercertMinterAbi } from "@hypercerts-org/contracts"; describe("burn fraction tokens in HypercertClient", () => { - let stub: sinon.SinonStub; - let provider: MockProvider; - let user: Wallet; - let other: Wallet; - const fractionId = BigNumber.from("9868188640707215440437863615521278132232"); + const wallet = walletClient; + const userAddress = wallet.account.address; + const client = new HypercertClient({ + id: 5, + walletClient, + publicClient, + }); + + const fractionId = 9868188640707215440437863615521278132232n; - beforeAll(() => { - provider = new MockProvider(); - [user, other] = provider.getWallets(); + let readSpy = sinon.stub(publicClient, "request"); + let writeSpy = sinon.stub(walletClient, "writeContract"); - stub = sinon.stub(provider, "on"); + const burnFractionResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "burnFraction", + result: [], }); - beforeEach(() => { - provider.clearCallHistory(); + + beforeEach(async () => { + readSpy.resetBehavior(); + readSpy.resetHistory(); + + writeSpy.resetBehavior(); + writeSpy.resetHistory(); }); afterAll(() => { - stub.restore(); + sinon.restore(); }); it("allows for a hypercert fraction to be burned", async () => { - const userAddress = await user.getAddress(); - const mockMinter = await deployMockContract(user, HypercertMinterAbi); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock["burnFraction(address,uint256)"].withArgs(userAddress, fractionId).returns(); - - const client = new HypercertClient({ - chainId: 5, - operator: user, - contractAddress: mockMinter.address, + const ownerOfResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "ownerOf", + result: [userAddress], }); + readSpy = readSpy.withArgs(sinon.match({ method: "eth_call" })).resolves(ownerOfResult); + + writeSpy = writeSpy.resolves(burnFractionResult); + expect(client.readonly).toBe(false); - await client.burnClaimFraction(fractionId); + const hash = await client.burnClaimFraction(fractionId); //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(5); + expect(isHex(hash)).toBeTruthy(); + expect(readSpy.callCount).toBe(1); + expect(writeSpy.callCount).toBe(1); }); it("throws on burning fraction not owned by signer", async () => { - const otherUser = await other.getAddress(); - const mockMinter = await deployMockContract(user, HypercertMinterAbi); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(otherUser); - - const client = new HypercertClient({ - chainId: 5, - operator: user, - contractAddress: mockMinter.address, + const ownerOfResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "ownerOf", + result: [faker.finance.ethereumAddress()], }); + readSpy = readSpy.withArgs(sinon.match({ method: "eth_call" })).resolves(ownerOfResult); + + writeSpy = writeSpy.resolves(burnFractionResult); + expect(client.readonly).toBe(false); + let hash; try { - await client.burnClaimFraction(fractionId); + hash = await client.burnClaimFraction(fractionId); } catch (e) { console.log(e); expect(e instanceof ClientError).toBeTruthy(); @@ -70,34 +84,40 @@ describe("burn fraction tokens in HypercertClient", () => { } //TODO determine underlying calls and mock those out. Some are provider simulation calls - // Owner - expect(provider.callHistory.length).toBe(3); - expect.assertions(4); + expect(hash).toBeUndefined(); + expect(readSpy.callCount).toBe(2); + expect(writeSpy.callCount).toBe(0); + expect.assertions(6); }); it("allows for a hypercert fraction to be burned with override params", async () => { - const userAddress = await user.getAddress(); - const mockMinter = await deployMockContract(user, HypercertMinterAbi); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock["burnFraction(address,uint256)"].withArgs(userAddress, fractionId).returns(); - - const client = new HypercertClient({ - chainId: 5, - operator: user, - contractAddress: mockMinter.address, + const ownerOfResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "ownerOf", + result: [userAddress], }); + readSpy = readSpy.withArgs(sinon.match({ method: "eth_call" })).resolves(ownerOfResult); + + writeSpy = writeSpy.resolves(burnFractionResult); + expect(client.readonly).toBe(false); + let hash; + try { - await client.burnClaimFraction(fractionId, { gasLimit: "FALSE_VALUE" }); + hash = await client.burnClaimFraction(fractionId, { gasLimit: "FALSE_VALUE" as unknown as bigint }); + expect.fail("should have thrown on incorrect gasLimit value"); } catch (e) { - expect((e as Error).message).toMatch(/invalid BigNumber string/); + expect((e as Error).message).toMatch(/Cannot convert FALSE_VALUE to a BigInt/); } - await client.burnClaimFraction(fractionId, { gasLimit: "12300000" }); + await client.burnClaimFraction(fractionId, { gasLimit: 12300000n }); //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(6); + expect(hash).toBeUndefined(); + expect(readSpy.callCount).toBe(4); + expect(writeSpy.callCount).toBe(1); + expect.assertions(5); }); }); diff --git a/sdk/test/client/minting.test.ts b/sdk/test/client/minting.test.ts index 3cd43c1a..cb71bfb4 100644 --- a/sdk/test/client/minting.test.ts +++ b/sdk/test/client/minting.test.ts @@ -1,59 +1,46 @@ import { expect } from "chai"; -import { MockContract, MockProvider, deployMockContract } from "ethereum-waffle"; -import { ethers } from "ethers"; import sinon from "sinon"; +import { encodeFunctionResult, isHex, parseAbi } from "viem"; -import HypercertClient from "../../src/client.js"; -import { HypercertMetadata, HypercertsStorage, formatHypercertData } from "../../src/index.js"; -import { MalformedDataError } from "../../src/types/errors.js"; -import { TransferRestrictions } from "../../src/types/hypercerts.js"; -import { getRawInputData } from "../helpers.js"; -import { HypercertMinter, HypercertMinterAbi } from "@hypercerts-org/contracts"; -const mockCorrectMetadataCid = "testCID1234fkreigdm2flneb4khd7eixodagst5nrndptgezrjux7gohxcngjn67x6u"; +import HypercertClient from "../../src/client"; +import { HypercertMetadata, formatHypercertData } from "../../src"; +import { MalformedDataError } from "../../src/types/errors"; +import { TransferRestrictions } from "../../src/types/hypercerts"; +import { getRawInputData, publicClient, walletClient } from "../helpers"; +import { HypercertMinterAbi } from "@hypercerts-org/contracts"; + +//eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import { CIDString, NFTStorage } from "nft.storage"; describe("mintClaim in HypercertClient", () => { - const metaDataStub = sinon.stub(HypercertsStorage.prototype, "storeMetadata").resolves(mockCorrectMetadataCid); - - const setUp = async () => { - const provider = new MockProvider(); - const [user, other, admin] = provider.getWallets(); - const stub = sinon.stub(provider, "on"); - - const minter = await deployMockContract(user, HypercertMinterAbi); - - const client = new HypercertClient({ - chainId: 5, - operator: user, - }); - - sinon.replaceGetter(client, "contract", () => minter as unknown as HypercertMinter); - - return { - client, - provider, - users: { user, other, admin }, - minter, - stub, - }; - }; - - let _client: HypercertClient; - let _provider: MockProvider; - let _users: { user: ethers.Wallet; other: ethers.Wallet; admin: ethers.Wallet }; - let _minter: MockContract; - let _stub: sinon.SinonStub; - - beforeAll(async () => { - const { client, provider, users, minter, stub } = await setUp(); - _client = client; - _provider = provider; - _users = users; - _minter = minter; - _stub = stub; + const mockCorrectMetadataCid = "testCID1234fkreigdm2flneb4khd7eixodagst5nrndptgezrjux7gohxcngjn67x6u" as CIDString; + + const storeBlobMock = sinon.stub(NFTStorage, "storeBlob").resolves(mockCorrectMetadataCid); + + const client = new HypercertClient({ + id: 5, + walletClient, + publicClient, + }); + + const readSpy = sinon.stub(publicClient, "request"); + let writeSpy = sinon.stub(walletClient, "writeContract"); + + const mintClaimResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "mintClaim", + result: [], }); - beforeEach(() => { - _provider.clearCallHistory(); + beforeEach(async () => { + readSpy.resetBehavior(); + readSpy.resetHistory(); + + writeSpy.resetBehavior(); + writeSpy.resetHistory(); + + storeBlobMock.resetHistory(); }); afterAll(() => { @@ -61,49 +48,59 @@ describe("mintClaim in HypercertClient", () => { }); it("mints a hypercerts", async () => { - expect(_client.readonly).to.be.false; + expect(client.readonly).to.be.false; const rawData = getRawInputData(); const { data: formattedData } = formatHypercertData(rawData); - await _minter.mock.mintClaim.returns(); + writeSpy = writeSpy.resolves(mintClaimResult); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await _client.mintClaim(formattedData!, 1000, TransferRestrictions.AllowAll); + const hash = await client.mintClaim(formattedData!, 1000n, TransferRestrictions.AllowAll); - sinon.assert.calledOnce(metaDataStub); - expect(_provider.callHistory.length).to.equal(2); - }, 10000); + expect(isHex(hash)).to.be.true; + expect(readSpy.callCount).to.equal(0); + expect(writeSpy.callCount).to.equal(1); + expect(storeBlobMock.callCount).to.equal(1); + }); it("throws on malformed metadata", async () => { try { - await _client.mintClaim({} as HypercertMetadata, 1000, TransferRestrictions.AllowAll); + await client.mintClaim({} as HypercertMetadata, 1000n, TransferRestrictions.AllowAll); expect.fail("Should throw MalformedDataError"); } catch (e) { expect(e).to.be.instanceOf(MalformedDataError); const error = e as MalformedDataError; expect(error.message).to.equal("Metadata validation failed"); } - expect(_provider.callHistory.length).to.equal(0); + expect(writeSpy.callCount).to.equal(0); }); it("mints a hypercerts with override params", async () => { const rawData = getRawInputData(); - await _minter.mock.mintClaim.returns(); const { data: formattedData } = formatHypercertData(rawData); + writeSpy = writeSpy.resolves(mintClaimResult); + + let hash; + try { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await _client.mintClaim(formattedData!, 1000, TransferRestrictions.AllowAll, { gasPrice: "FALSE_VALUE" }); + hash = await client.mintClaim(formattedData!, 1000n, TransferRestrictions.AllowAll, { + gasPrice: "FALSE_VALUE" as unknown as bigint, + }); expect.fail("Should throw Error"); } catch (e) { - expect((e as Error).message).to.match(/.*invalid BigNumber string.*/); + expect((e as Error).message).to.match(/.Cannot convert FALSE_VALUE to a BigInt/); } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await _client.mintClaim(formattedData!, 1000, TransferRestrictions.AllowAll, { gasPrice: "100" }); + hash = await client.mintClaim(formattedData!, 1000n, TransferRestrictions.AllowAll, { gasPrice: 100n }); - expect(_provider.callHistory.length).to.equal(2); - }, 10000); + expect(isHex(hash)).to.be.true; + expect(readSpy.callCount).to.equal(0); + expect(writeSpy.callCount).to.equal(1); + expect(storeBlobMock.callCount).to.equal(2); + }); }); diff --git a/sdk/test/client/split.merge.test.ts b/sdk/test/client/split.merge.test.ts index fec89bf8..071d249f 100644 --- a/sdk/test/client/split.merge.test.ts +++ b/sdk/test/client/split.merge.test.ts @@ -1,252 +1,235 @@ -import { MockProvider, deployMockContract } from "ethereum-waffle"; -import { BigNumber, Wallet } from "ethers"; import sinon from "sinon"; -import HypercertClient from "../../src/client.js"; -import { ClientError } from "../../src/types/errors.js"; +import HypercertClient from "../../src/client"; import { HypercertMinterAbi } from "@hypercerts-org/contracts"; +import { publicClient, walletClient } from "../helpers"; +import { encodeFunctionResult, isHex, parseAbi } from "viem"; describe("splitClaimUnits in HypercertClient", () => { - let stub: sinon.SinonStub; - let provider: MockProvider; - let wallet: Wallet; - const fractionId = BigNumber.from("9868188640707215440437863615521278132232"); + const wallet = walletClient; + const userAddress = wallet.account.address; - beforeAll(() => { - provider = new MockProvider(); - wallet = provider.getWallets()[0]; + let readSpy = sinon.stub(publicClient, "request"); + let writeSpy = sinon.stub(walletClient, "writeContract"); - stub = sinon.stub(provider, "on"); + const client = new HypercertClient({ + id: 5, + walletClient, + publicClient, }); - beforeEach(() => { - provider.clearCallHistory(); - }); - - afterAll(() => { - stub.restore(); - }); - - it("allows for a hypercert fractions to be splitted over value", async () => { - const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(300); - await mockMinter.mock["splitFraction(address,uint256,uint256[])"] - .withArgs(userAddress, fractionId, [100, 200]) - .returns(); - - const signer = wallet.connect(provider); - - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); - - expect(client.readonly).toBe(false); - await client.splitClaimUnits(fractionId, [100, 200]); + const fractionId = 9868188640707215440437863615521278132232n; - //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(7); - }, 10000); - - it("allows for a hypercert fractions to be splitted over value with override params", async () => { - const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(300); - await mockMinter.mock["splitFraction(address,uint256,uint256[])"] - .withArgs(userAddress, fractionId, [100, 200]) - .returns(); - - const signer = wallet.connect(provider); - - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); - expect(client.readonly).toBe(false); - - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - try { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await client.splitClaimUnits(fractionId, [100, 200], { gasLimit: "FALSE_VALUE" }); - } catch (e) { - expect((e as Error).message).toMatch(/invalid BigNumber string/); - } - - await client.splitClaimUnits(fractionId, [100, 200], { gasLimit: "12300000" }); - - //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(9); - }, 10000); - - it("throws on splitting with incorrect new total value", async () => { - const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(42); - - const signer = wallet.connect(provider); - - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); - expect(client.readonly).toBe(false); - - try { - await client.splitClaimUnits(fractionId, [100, 200]); - } catch (e) { - expect(e instanceof ClientError).toBeTruthy(); - - const error = e as ClientError; - expect(error.message).toBe("Sum of fractions is not equal to the total units"); - } - - //TODO determine underlying calls and mock those out. Some are provider simulation calls - // Owner - // UnitsOf - expect(provider.callHistory.length).toBe(5); - expect.assertions(4); + const ownerOfResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "ownerOf", + result: [userAddress], }); - it("throws on splitting fractions not owned by signer", async () => { - const otherUser = await provider.getWallets()[1].getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(otherUser); - - const signer = wallet.connect(provider); - - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); - expect(client.readonly).toBe(false); - - try { - await client.splitClaimUnits(fractionId, [100, 200]); - } catch (e) { - expect(e instanceof ClientError).toBeTruthy(); - - const error = e as ClientError; - expect(error.message).toBe("Claim is not owned by the signer"); - } + const unitsOfResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "unitsOf", + result: [300n], + }); - //TODO determine underlying calls and mock those out. Some are provider simulation calls - // Owner - expect(provider.callHistory.length).toBe(3); - expect.assertions(4); + const splitFractionResult = encodeFunctionResult({ + abi: parseAbi(HypercertMinterAbi), + functionName: "splitFraction", + result: [], }); -}); -describe("mergeClaimUnits in HypercertClient", () => { - let stub: sinon.SinonStub; - let provider: MockProvider; - let wallet: Wallet; - const fractionId = BigNumber.from("9868188640707215440437863615521278132232"); + beforeEach(async () => { + readSpy.resetBehavior(); + readSpy.resetHistory(); - beforeAll(() => { - provider = new MockProvider(); - wallet = provider.getWallets()[0]; - stub = sinon.stub(provider, "on"); - }); - beforeEach(() => { - provider.clearCallHistory(); + writeSpy.resetBehavior(); + writeSpy.resetHistory(); }); afterAll(() => { - stub.restore(); + sinon.restore(); }); - it("allows for hypercert fractions to merge value", async () => { - const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock.ownerOf.withArgs(fractionId.add(1)).returns(userAddress); - await mockMinter.mock["mergeFractions(address,uint256[])"] - .withArgs(userAddress, [fractionId, fractionId.add(1)]) - .returns(); - - const signer = wallet.connect(provider); - - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); - expect(client.readonly).toBe(false); - - await client.mergeClaimUnits([fractionId, fractionId.add(1)]); + it("allows for a hypercert fractions to be splitted over value", async () => { + readSpy = readSpy.onFirstCall().resolves(ownerOfResult).onSecondCall().resolves(unitsOfResult); + writeSpy = writeSpy.resolves(splitFractionResult); - //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(7); - }, 10000); - - it("allows for hypercert fractions to merge value with override params", async () => { - const userAddress = await wallet.getAddress(); - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock.ownerOf.withArgs(fractionId.add(1)).returns(userAddress); - await mockMinter.mock["mergeFractions(address,uint256[])"] - .withArgs(userAddress, [fractionId, fractionId.add(1)]) - .returns(); - - const signer = wallet.connect(provider); - - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); expect(client.readonly).toBe(false); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - try { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await client.mergeClaimUnits([fractionId, fractionId.add(1)], { gasLimit: "FALSE_VALUE" }); - } catch (e) { - expect((e as Error).message).toMatch(/invalid BigNumber string/); - } - - await client.mergeClaimUnits([fractionId, fractionId.add(1)], { gasLimit: "12300000" }); + const hash = await client.splitClaimUnits(fractionId, [100n, 200n]); //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(9); - }, 10000); - - it("throws on splitting fractions not owned by signer", async () => { - const userAddress = await wallet.getAddress(); - const otherUser = await provider.getWallets()[1].getAddress(); - - const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); - await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); - await mockMinter.mock.ownerOf.withArgs(fractionId.add(1)).returns(otherUser); + expect(isHex(hash)).toBeTruthy(); + expect(readSpy.callCount).toBe(2); + expect(writeSpy.callCount).toBe(1); + expect.assertions(4); + }); - const signer = wallet.connect(provider); + it("allows for a hypercert fractions to be splitted over value with override params", async () => { + readSpy = readSpy + .onFirstCall() + .resolves(ownerOfResult) + .onSecondCall() + .resolves(unitsOfResult) + .onThirdCall() + .resolves(ownerOfResult) + .onCall(3) + .resolves(unitsOfResult); + + writeSpy = writeSpy.resolves(splitFractionResult); - const client = new HypercertClient({ - chainId: 5, - operator: signer, - contractAddress: mockMinter.address, - }); expect(client.readonly).toBe(false); try { - await client.mergeClaimUnits([fractionId, fractionId.add(1)]); + await client.splitClaimUnits(fractionId, [100n, 200n], { gasLimit: "FALSE_VALUE" as unknown as bigint }); } catch (e) { - expect(e instanceof ClientError).toBeTruthy(); - - const error = e as ClientError; - expect(error.message).toBe("One or more claims are not owned by the signer"); + expect((e as Error).message).toMatch(/Cannot convert FALSE_VALUE to a BigInt/); } + const hash = await client.splitClaimUnits(fractionId, [100n, 200n], { gasLimit: 12300000n }); + //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(provider.callHistory.length).toBe(5); + expect(isHex(hash)).toBeTruthy(); + expect(readSpy.callCount).toBe(4); + expect(writeSpy.callCount).toBe(1); + expect.assertions(5); }); + + // it("throws on splitting with incorrect new total value", async () => { + // const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); + // await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); + // await mockMinter.mock["unitsOf(uint256)"].withArgs(fractionId).returns(42); + + // const client = new HypercertClient({ + // chainId: 5, + // operator: walletClient, + // contractAddress: mockMinter.address, + // }); + // expect(client.readonly).toBe(false); + + // try { + // await client.splitClaimUnits(fractionId, [100n, 200n]); + // } catch (e) { + // expect(e instanceof ClientError).toBeTruthy(); + + // const error = e as ClientError; + // expect(error.message).toBe("Sum of fractions is not equal to the total units"); + // } + + // //TODO determine underlying calls and mock those out. Some are provider simulation calls + // // Owner + // // UnitsOf + // expect(provider.callHistory.length).toBe(5); + // expect.assertions(4); + // }); + + // it("throws on splitting fractions not owned by signer", async () => { + // const otherUser = await provider.getWallets()[1].getAddress(); + // const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); + // await mockMinter.mock.ownerOf.withArgs(fractionId).returns(otherUser); + + // const client = new HypercertClient({ + // chainId: 5, + // operator: walletClient, + // contractAddress: mockMinter.address, + // }); + // expect(client.readonly).toBe(false); + + // try { + // await client.splitClaimUnits(fractionId, [100n, 200n]); + // } catch (e) { + // expect(e instanceof ClientError).toBeTruthy(); + + // const error = e as ClientError; + // expect(error.message).toBe("Claim is not owned by the signer"); + // } + + // //TODO determine underlying calls and mock those out. Some are provider simulation calls + // // Owner + // expect(provider.callHistory.length).toBe(3); + // expect.assertions(4); + // }); }); + +// describe("mergeClaimUnits in HypercertClient", () => { +// const provider = testClient; +// const wallet = walletClient; +// const fractionId = 9868188640707215440437863615521278132232n; +// const userAddress = wallet.account.address; + +// it("allows for hypercert fractions to merge value", async () => { +// const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); +// await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); +// await mockMinter.mock.ownerOf.withArgs(fractionId + 1n).returns(userAddress); +// await mockMinter.mock["mergeFractions(address,uint256[])"] +// .withArgs(userAddress, [fractionId, fractionId + 1n]) +// .returns(); + +// const client = new HypercertClient({ +// chainId: 5, +// operator: walletClient, +// contractAddress: mockMinter.address, +// }); +// expect(client.readonly).toBe(false); + +// await client.mergeClaimUnits([fractionId, fractionId + 1n]); + +// //TODO determine underlying calls and mock those out. Some are provider simulation calls +// expect(provider.callHistory.length).toBe(7); +// }, 10000); + +// it("allows for hypercert fractions to merge value with override params", async () => { +// const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); +// await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); +// await mockMinter.mock.ownerOf.withArgs(fractionId + 1n).returns(userAddress); +// await mockMinter.mock["mergeFractions(address,uint256[])"] +// .withArgs(userAddress, [fractionId, fractionId + 1n]) +// .returns(); + +// const client = new HypercertClient({ +// chainId: 5, +// operator: walletClient, +// contractAddress: mockMinter.address, +// }); +// expect(client.readonly).toBe(false); + +// try { +// await client.mergeClaimUnits([fractionId, fractionId + 1n], { gasLimit: "FALSE_VALUE" as unknown as bigint }); +// } catch (e) { +// expect((e as Error).message).toMatch(/invalid BigNumber string/); +// } + +// await client.mergeClaimUnits([fractionId, fractionId + 1n], { gasLimit: 12300000n }); + +// //TODO determine underlying calls and mock those out. Some are provider simulation calls +// expect(provider.callHistory.length).toBe(9); +// }, 10000); + +// it("throws on splitting fractions not owned by signer", async () => { +// const otherUser = await provider.getWallets()[1].getAddress(); + +// const mockMinter = await deployMockContract(wallet, HypercertMinterAbi); +// await mockMinter.mock.ownerOf.withArgs(fractionId).returns(userAddress); +// await mockMinter.mock.ownerOf.withArgs(fractionId + 1n).returns(otherUser); + +// const client = new HypercertClient({ +// chainId: 5, +// operator: walletClient, +// contractAddress: mockMinter.address, +// }); +// expect(client.readonly).toBe(false); + +// try { +// await client.mergeClaimUnits([fractionId, fractionId + 1n]); +// } catch (e) { +// expect(e instanceof ClientError).toBeTruthy(); + +// const error = e as ClientError; +// expect(error.message).toBe("One or more claims are not owned by the signer"); +// } + +// //TODO determine underlying calls and mock those out. Some are provider simulation calls +// expect(provider.callHistory.length).toBe(5); +// }); +// }); diff --git a/sdk/test/evaluations/easEvaluator.test.ts b/sdk/test/evaluations/easEvaluator.test.ts deleted file mode 100644 index 048ec024..00000000 --- a/sdk/test/evaluations/easEvaluator.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { MockProvider } from "ethereum-waffle"; -import sinon from "sinon"; - -import { EAS_SCHEMAS } from "../../src/constants.js"; -import EasEvaluator from "../../src/evaluations/eas.js"; -import { HypercertClientConfig } from "../../src/index.js"; -import { DuplicateEvaluation, SimpleTextEvaluation } from "../../src/types/evaluation.js"; - -describe("EasEvaluator", () => { - let stub: sinon.SinonStub; - const provider = new MockProvider(); - - beforeAll(() => { - stub = sinon.stub(provider, "on"); - }); - const [wallet] = provider.getWallets(); - const signer = wallet.connect(provider); - - afterAll(() => { - stub.restore(); - }); - - const config = { - chainId: 5, - easContractAddress: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e", - operator: signer, - } as Partial; - const easEvaluator = new EasEvaluator(config); - - describe("getSignature", () => { - it("should return a signature", async () => { - const encodedData = "0x1234567890abcdef"; - const recipient = "0x0987654321098765432109876543210987654321"; - const schema = EAS_SCHEMAS["sepolia"].duplicate; - - const signature = await easEvaluator.getSignature(encodedData, recipient, schema.uid); - - expect(signature).toBeDefined(); - expect(signature.message.schema).toEqual(schema.uid); - expect(Object.keys(signature)).toEqual( - expect.arrayContaining(["domain", "message", "primaryType", "signature", "types", "uid"]), - ); - }); - }); - - describe("signOfflineEvaluation", () => { - it("should sign a duplicate evaluation", async () => { - const evaluation = { - type: "duplicate", - realHypercert: { - chainId: "0x1", - contract: "0x1234567890123456789012345678901234567890", - claimId: "1", - }, - duplicateHypercerts: [ - { - chainId: "0x1", - contract: "0x0987654321098765432109876543210987654321", - claimId: "2", - }, - ], - explanation: "explanation", - } as DuplicateEvaluation; - - const signature = await easEvaluator.signOfflineEvaluation(evaluation); - - expect(signature).toBeDefined(); - expect(signature?.message.schema).toEqual(EAS_SCHEMAS["sepolia"].duplicate.uid); - expect(signature).toContainKeys(["domain", "message", "primaryType", "signature", "types", "uid"]); - }); - - it("should sign a simple text evaluation", async () => { - const evaluation = { - type: "simpleText", - hypercert: { - chainId: "0x1", - contract: "0x0987654321098765432109876543210987654321", - claimId: "2", - }, - text: "text", - } as SimpleTextEvaluation; - - const signature = await easEvaluator.signOfflineEvaluation(evaluation); - - expect(signature).toBeDefined(); - expect(signature?.message.schema).toEqual(EAS_SCHEMAS["sepolia"].contentHash.uid); - expect(signature).toContainKeys(["domain", "message", "primaryType", "signature", "types", "uid"]); - }); - }); -}); diff --git a/sdk/test/evaluations/evaluator.test.ts b/sdk/test/evaluations/evaluator.test.ts index b3ca52c7..2533be55 100644 --- a/sdk/test/evaluations/evaluator.test.ts +++ b/sdk/test/evaluations/evaluator.test.ts @@ -1,30 +1,17 @@ import { expect } from "@jest/globals"; -import { providers } from "ethers"; -import { Wallet, ethers } from "ethers"; -import { CIDString } from "nft.storage"; import sinon from "sinon"; import HypercertEvaluator from "../../src/evaluations/index.js"; -import { InvalidOrMissingError, MalformedDataError, StorageError } from "../../src/types/errors.js"; +import { MalformedDataError, StorageError } from "../../src/types/errors.js"; import { HypercertEvaluationSchema } from "../../src/types/evaluation.js"; -import { getEvaluationData } from "../helpers.js"; +import { getEvaluationData, publicClient, walletClient } from "../helpers.js"; describe("HypercertEvaluator", () => { - let stubSubscription: sinon.SinonStub; - let stubStorage: sinon.SinonStub; - let signer: Wallet; - let evaluator: HypercertEvaluator; - const mockCid = "bafybeibxm2nsadl3fnxv2sxcxmxaco2jl53wpeorjdzidjwf5aqdg7wa6u"; - - beforeAll(() => { - stubSubscription = sinon.stub(providers.JsonRpcProvider.prototype, "on"); - signer = ethers.Wallet.createRandom(); - evaluator = new HypercertEvaluator({ - chainId: 5, - easContractAddress: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e", - operator: signer, - }); - stubStorage = sinon.stub(evaluator.storage, "storeData").resolves(mockCid); + const signer = walletClient.account; + const evaluator = new HypercertEvaluator({ + id: 5, + easContractAddress: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e", + publicClient, }); beforeEach(() => { @@ -32,42 +19,13 @@ describe("HypercertEvaluator", () => { }); afterAll(() => { - // reloadEnv(); - - stubStorage.restore(); - stubSubscription.restore(); + sinon.restore(); }); describe("submitEvaluation", () => { - it("should submit an EAS evaluation", async () => { - const evaluation: HypercertEvaluationSchema = getEvaluationData({ creator: await signer.getAddress() }); - - const result: CIDString = await evaluator.submitEvaluation(evaluation); - - console.log(result); - - expect(result).toEqual("bafybeibxm2nsadl3fnxv2sxcxmxaco2jl53wpeorjdzidjwf5aqdg7wa6u"); - sinon.assert.calledOnce(stubStorage); - }); - - it("should throw an error for missing signer", async () => { - try { - new HypercertEvaluator({ - chainId: 5, - easContractAddress: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e", - }); - } catch (e) { - expect(e).toBeInstanceOf(InvalidOrMissingError); - const error = e as InvalidOrMissingError; - expect(error.message).toEqual("Invalid or missing config value: operator"); - } - - expect.assertions(2); - }); - it("should throw an error for unexpected evaluation source", async () => { const evaluation = { - creator: await signer.getAddress(), + creator: signer.address, evaluationSource: { type: "invalid", }, @@ -110,20 +68,20 @@ describe("HypercertEvaluator", () => { sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: null }); sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN: null }); - const evaluation: HypercertEvaluationSchema = getEvaluationData({ creator: await signer.getAddress() }); + const evaluation: HypercertEvaluationSchema = getEvaluationData({ creator: signer.address }); const readonlyEvaluator = new HypercertEvaluator({ - chainId: 5, + id: 5, easContractAddress: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e", - operator: signer, + publicClient, }); try { await readonlyEvaluator.submitEvaluation(evaluation); } catch (e) { - expect(e).toBeInstanceOf(StorageError); - const error = e as StorageError; - expect(error.message).toEqual("Web3.storage client is not configured"); + const error = e as Error; + expect(error).toBeInstanceOf(Error); + expect(error.message).toMatch(/Unexpected evaluation source/); } expect.assertions(2); diff --git a/sdk/test/helpers.ts b/sdk/test/helpers.ts index ccc5b712..57a05564 100644 --- a/sdk/test/helpers.ts +++ b/sdk/test/helpers.ts @@ -1,15 +1,53 @@ import { faker } from "@faker-js/faker"; import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; -import { BigNumber, BigNumberish, ContractReceipt, ContractTransaction } from "ethers"; -import { HypercertMetadata } from "../src/index.js"; -import { - AllowlistEntry, - DuplicateEvaluation, - HypercertEvaluationSchema, - SimpleTextEvaluation, -} from "../src/types/index.js"; -import { formatHypercertData } from "../src/utils/formatter.js"; +import { HypercertMetadata } from "../src"; +import { AllowlistEntry, DuplicateEvaluation, HypercertEvaluationSchema, SimpleTextEvaluation } from "../src/types"; +import { formatHypercertData } from "../src/utils/formatter"; +import { Chain, foundry } from "viem/chains"; +import { PublicClient, createPublicClient, createTestClient, createWalletClient, http } from "viem"; +import * as HypercertMinter from "./resources/HypercertMinter.json"; + +export const pool = Number(process.env.VITEST_POOL_ID ?? 1); +export const anvil = { + ...foundry, // We are using a mainnet fork for testing. + id: foundry.id, + rpcUrls: { + // These rpc urls are automatically used in the transports. + default: { + // Note how we append the worker id to the local rpc urls. + http: [`http://127.0.0.1:8545/${pool}`], + webSocket: [`ws://127.0.0.1:8545/${pool}`], + }, + public: { + // Note how we append the worker id to the local rpc urls. + http: [`http://127.0.0.1:8545/${pool}`], + webSocket: [`ws://127.0.0.1:8545/${pool}`], + }, + }, +} as const satisfies Chain; + +export const testClient = createTestClient({ + chain: anvil, + mode: "anvil", + transport: http(), +}); + +export const publicClient: PublicClient = createPublicClient({ + chain: anvil, + batch: { + multicall: true, + }, + transport: http(), +}); + +export const walletClient = createWalletClient({ + chain: anvil, + transport: http(), + account: faker.finance.ethereumAddress() as `0x${string}`, +}); + +export const HypercertMinterByteCode = HypercertMinter.bytecode as `0x${string}`; export type TestDataType = Parameters[0]; @@ -19,12 +57,12 @@ export type TestDataType = Parameters[0]; */ const getAllowlist = ({ size = 10, - units = 1, + units = 1n, address, }: { size?: number; address?: `0x${string}`; - units?: BigNumberish; + units?: bigint; } = {}) => { //generate allowlist array based on possible overrides const allowlist: AllowlistEntry[] = []; @@ -43,7 +81,7 @@ const getAllowlist = ({ const merkleTree = StandardMerkleTree.of(mappedAllowlist, ["address", "uint256"]); - const totalUnits = allowlist.reduce((acc, entry) => acc.add(entry.units), BigNumber.from(0)); + const totalUnits = allowlist.reduce((acc, entry) => acc + BigInt(entry.units), 0n); return { allowlist, merkleTree, totalUnits }; }; @@ -78,42 +116,6 @@ const getFormattedMetadata = (overrides?: Partial): HypercertMetad return formattedData as HypercertMetadata; }; -const mockContractResponse = (): Promise => { - // mock transaction receipt - const receipt: ContractReceipt = { - to: "0x0", - from: "0x0", - contractAddress: "0x0", - transactionIndex: 0, - gasUsed: BigNumber.from(0), - logsBloom: "0x0", - blockHash: "0x0", - transactionHash: "0x0", - logs: [], - blockNumber: 0, - confirmations: 0, - cumulativeGasUsed: BigNumber.from(0), - effectiveGasPrice: BigNumber.from(0), - byzantium: true, - type: 0, - status: 1, - }; - - const transaction: ContractTransaction = { - gasLimit: BigNumber.from(0), - data: "0x0", - value: BigNumber.from(0), - chainId: 1337, - hash: "0x0", - confirmations: 1, - from: "0x0", - nonce: 0, - wait: () => Promise.resolve(receipt), - }; - - return Promise.resolve(transaction); -}; - const getEvaluationData = (overrides?: Partial): HypercertEvaluationSchema => { const mockData: HypercertEvaluationSchema = { creator: "0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff", @@ -139,10 +141,8 @@ const getEvaluationData = (overrides?: Partial): Hype explanation: "These hypercerts are duplicates", }, evaluationSource: { - type: "EAS", - chainId: "0x1", - contract: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e", - uid: "0x1234567890abcdef", + type: "IPFS", + cid: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e", }, }; @@ -193,7 +193,6 @@ export { getAllowlist, getFormattedMetadata, getRawInputData, - mockContractResponse, getEvaluationData, getDuplicateEvaluationData, getSimpleTextEvaluationData, diff --git a/sdk/test/indexer.test.ts b/sdk/test/indexer.test.ts index fb80767a..71c12b13 100644 --- a/sdk/test/indexer.test.ts +++ b/sdk/test/indexer.test.ts @@ -1,6 +1,6 @@ import { expect } from "chai"; -import HypercertsIndexer from "../src/indexer.js"; +import HypercertsIndexer from "../src/indexer"; describe("HypercertsIndexer", () => { it("should be able to create a new instance without valid graphName", () => { diff --git a/sdk/test/resources/HypercertMinter.json b/sdk/test/resources/HypercertMinter.json new file mode 100644 index 00000000..16629732 --- /dev/null +++ b/sdk/test/resources/HypercertMinter.json @@ -0,0 +1,1139 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "HypercertMinter", + "sourceName": "src/protocol/HypercertMinter.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyClaimed", + "type": "error" + }, + { + "inputs": [], + "name": "ArraySize", + "type": "error" + }, + { + "inputs": [], + "name": "DoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "Invalid", + "type": "error" + }, + { + "inputs": [], + "name": "NotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "NotApprovedOrOwner", + "type": "error" + }, + { + "inputs": [], + "name": "TransfersNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "TypeMismatch", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + } + ], + "name": "AllowlistCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256[]", + "name": "claimIDs", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "fromTokenIDs", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "toTokenIDs", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "BatchValueTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "claimID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalUnits", + "type": "uint256" + } + ], + "name": "ClaimStored", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "leaf", + "type": "bytes32" + } + ], + "name": "LeafClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "claimID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fromTokenID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "ValueTransfer", + "type": "event" + }, + { + "inputs": [], + "name": "__SemiFungible1155_init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "_tokenIDs", + "type": "uint256[]" + } + ], + "name": "batchBurnFraction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32[][]", + "name": "proofs", + "type": "bytes32[][]" + }, + { + "internalType": "uint256[]", + "name": "claimIDs", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "units", + "type": "uint256[]" + } + ], + "name": "batchMintClaimsFromAllowlists", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "name": "burnBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenID", + "type": "uint256" + } + ], + "name": "burnFraction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "_uri", + "type": "string" + }, + { + "internalType": "enum IHypercertToken.TransferRestrictions", + "name": "restrictions", + "type": "uint8" + } + ], + "name": "createAllowlist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "hasBeenClaimed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + }, + { + "internalType": "uint256", + "name": "claimID", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "leaf", + "type": "bytes32" + } + ], + "name": "isAllowedToClaim", + "outputs": [ + { + "internalType": "bool", + "name": "isAllowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "_fractionIDs", + "type": "uint256[]" + } + ], + "name": "mergeFractions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_uri", + "type": "string" + }, + { + "internalType": "enum IHypercertToken.TransferRestrictions", + "name": "restrictions", + "type": "uint8" + } + ], + "name": "mintClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + }, + { + "internalType": "uint256", + "name": "claimID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + } + ], + "name": "mintClaimFromAllowlist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "fractions", + "type": "uint256[]" + }, + { + "internalType": "string", + "name": "_uri", + "type": "string" + }, + { + "internalType": "enum IHypercertToken.TransferRestrictions", + "name": "restrictions", + "type": "uint8" + } + ], + "name": "mintClaimWithFractions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + } + ], + "name": "readTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenID", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_newFractions", + "type": "uint256[]" + } + ], + "name": "splitFraction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + } + ], + "name": "unitsOf", + "outputs": [ + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + } + ], + "name": "unitsOf", + "outputs": [ + { + "internalType": "uint256", + "name": "units", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenID", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "_uri", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e7565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e5576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051615dcb6200011f60003960008181610b1601528181610bac01528181610f6701528181610ffd01526110f80152615dcb6000f3fe6080604052600436106102695760003560e01c8063715018a611610153578063b316962f116100cb578063f242432a1161007f578063f5298aca11610064578063f5298aca14610732578063f6b1229314610752578063fda4823c1461077257600080fd5b8063f242432a146106f2578063f2fde38b1461071257600080fd5b8063e985e9c5116100b0578063e985e9c514610669578063eb568a14146106b2578063f1169062146106d257600080fd5b8063b316962f14610629578063c7b26c541461064957600080fd5b80638fc202dd1161012257806399f771a71161010757806399f771a7146105ad578063a21ed980146105cd578063a22cb4651461060957600080fd5b80638fc202dd14610578578063993de1841461058d57600080fd5b8063715018a61461051b5780638129fc1c146105305780638456cb59146105455780638da5cb5b1461055a57600080fd5b80633f4ba83a116101e657806352d1902d116101b55780636352211e1161019a5780636352211e1461048c5780636b20c454146104db5780636ebd893f146104fb57600080fd5b806352d1902d1461045e5780635c975abb1461047357600080fd5b80633f4ba83a146103e95780633f71e944146103fe5780634e1273f41461041e5780634f1ef2861461044b57600080fd5b80631a2e98241161023d5780632eb2c2d6116102225780632eb2c2d6146103895780633659cfe6146103a95780633e11eefe146103c957600080fd5b80631a2e9824146103475780631e75a8b51461036757600080fd5b8062fdd58e1461026e57806301ffc9a7146102a157806306fdde03146102d15780630e89341c14610327575b600080fd5b34801561027a57600080fd5b5061028e610289366004614d0a565b610792565b6040519081526020015b60405180910390f35b3480156102ad57600080fd5b506102c16102bc366004614d62565b610840565b6040519015158152602001610298565b3480156102dd57600080fd5b5061031a6040518060400160405280600f81526020017f4879706572636572744d696e746572000000000000000000000000000000000081525081565b6040516102989190614dcf565b34801561033357600080fd5b5061031a610342366004614de2565b610923565b34801561035357600080fd5b5061028e610362366004614d0a565b61092e565b34801561037357600080fd5b50610387610382366004614f26565b610941565b005b34801561039557600080fd5b506103876103a436600461504e565b610a6a565b3480156103b557600080fd5b506103876103c43660046150f8565b610b0c565b3480156103d557600080fd5b506102c16103e4366004615113565b610ca9565b3480156103f557600080fd5b50610387610cd0565b34801561040a57600080fd5b5061031a610419366004614de2565b610ce2565b34801561042a57600080fd5b5061043e610439366004615164565b610e1f565b604051610298919061526a565b61038761045936600461527d565b610f5d565b34801561046a57600080fd5b5061028e6110eb565b34801561047f57600080fd5b506101cd5460ff166102c1565b34801561049857600080fd5b506104c36104a7366004614de2565b600090815261019260205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610298565b3480156104e757600080fd5b506103876104f63660046152c1565b6111b1565b34801561050757600080fd5b50610387610516366004615335565b6111c8565b34801561052757600080fd5b506103876111e2565b34801561053c57600080fd5b506103876111f4565b34801561055157600080fd5b50610387611355565b34801561056657600080fd5b5060fb546001600160a01b03166104c3565b34801561058457600080fd5b50610387611365565b34801561059957600080fd5b506103876105a836600461538f565b611408565b3480156105b957600080fd5b5061028e6105c8366004614de2565b61142f565b3480156105d957600080fd5b506102c16105e83660046153f4565b6101b060209081526000928352604080842090915290825290205460ff1681565b34801561061557600080fd5b50610387610624366004615416565b611444565b34801561063557600080fd5b50610387610644366004615452565b61144f565b34801561065557600080fd5b506103876106643660046154c4565b6114e4565b34801561067557600080fd5b506102c1610684366004615517565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205460ff1690565b3480156106be57600080fd5b506103876106cd36600461554a565b611529565b3480156106de57600080fd5b506103876106ed36600461558e565b61153b565b3480156106fe57600080fd5b5061038761070d366004615639565b6115ce565b34801561071e57600080fd5b5061038761072d3660046150f8565b611669565b34801561073e57600080fd5b5061038761074d36600461569e565b6116f6565b34801561075e57600080fd5b5061038761076d366004614d0a565b611708565b34801561077e57600080fd5b5061038761078d3660046156d1565b61171a565b60006001600160a01b0383166108155760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201527f616c6964206f776e65720000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b5060008181526065602090815260408083206001600160a01b03861684529091529020545b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fd9b67a260000000000000000000000000000000000000000000000000000000014806108d357507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061083a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461083a565b606061083a826117cc565b600061093a83836117ea565b9392505050565b610949611822565b336001600160a01b0387161461097257604051631eb49d6d60e11b815260040160405180910390fd5b846109af85858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061187692505050565b146109e6576040517f6dac6a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109f4878686866118f5565b60008181526101ff602052604090208054919250839160ff19166001836002811115610a2257610a22615739565b0217905550807f19789dde2d660b739733377add05f87576a360d2d4adea587c2592264f7f6d4e8488604051610a59929190615768565b60405180910390a250505050505050565b6001600160a01b038516331480610a865750610a868533610684565b610af85760405162461bcd60e51b815260206004820152602e60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201527f6572206f7220617070726f766564000000000000000000000000000000000000606482015260840161080c565b610b05858585858561196f565b5050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610baa5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161080c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c057f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614610c815760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161080c565b610c8a81611c24565b60408051600080825260208201909252610ca691839190611c2c565b50565b60008281526101af6020526040812054610cc7908690869085611dcc565b95945050505050565b610cd8611de4565b610ce0611e3e565b565b6fffffffffffffffffffffffffffffffff19811660009081526101ff602052604081205460609160ff90911690816002811115610d2157610d21615739565b03610d6157505060408051808201909152600881527f416c6c6f77416c6c0000000000000000000000000000000000000000000000006020820152919050565b6001816002811115610d7557610d75615739565b03610db557505060408051808201909152600b81527f446973616c6c6f77416c6c0000000000000000000000000000000000000000006020820152919050565b6002816002811115610dc957610dc9615739565b03610e0957505060408051808201909152600f81527f46726f6d43726561746f724f6e6c7900000000000000000000000000000000006020820152919050565b5050604080516020810190915260008152919050565b60608151835114610e985760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d617463680000000000000000000000000000000000000000000000606482015260840161080c565b6000835167ffffffffffffffff811115610eb457610eb4614e47565b604051908082528060200260200182016040528015610edd578160200160208202803683370190505b50905060005b8451811015610f5557610f28858281518110610f0157610f0161578a565b6020026020010151858381518110610f1b57610f1b61578a565b6020026020010151610792565b828281518110610f3a57610f3a61578a565b6020908102919091010152610f4e816157e8565b9050610ee3565b509392505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610ffb5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161080c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166110567f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b0316146110d25760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161080c565b6110db82611c24565b6110e782826001611c2c565b5050565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461118b5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161080c565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b90565b6111b9611822565b6111c38383611e91565b505050565b6111d0611822565b6111dc8484848461211f565b50505050565b6111ea611de4565b610ce06000612667565b600054610100900460ff16158080156112145750600054600160ff909116105b8061122e5750303b15801561122e575060005460ff166001145b6112a05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161080c565b6000805460ff1916600117905580156112e057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6112e8611365565b6112f06126d1565b8015610ca657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b61135d611de4565b610ce0612744565b600054610100900460ff166113d05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b6113e860405180602001604052806000815250612782565b6113f06127f6565b6113f8612861565b6114006128d4565b610ce06127f6565b611410611822565b61141c84848484612947565b611427858383612ad0565b505050505050565b6000818152610194602052604081205461083a565b6110e7338383612ba8565b611457611822565b6000611464868685612c9c565b9050611471818587612d6d565b60008181526101ff60205260409020805483919060ff1916600183600281111561149d5761149d615739565b0217905550807f19789dde2d660b739733377add05f87576a360d2d4adea587c2592264f7f6d4e84876040516114d4929190615768565b60405180910390a2505050505050565b6114ec611822565b6111c383838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612e5392505050565b611531611822565b6110e78282611e91565b611543611822565b8260005b818110156115b5576115ad8888838181106115645761156461578a565b90506020028101906115769190615802565b8888858181106115885761158861578a565b905060200201358787868181106115a1576115a161578a565b90506020020135612947565b600101611547565b506115c38886868686613167565b505050505050505050565b6001600160a01b0385163314806115ea57506115ea8533610684565b61165c5760405162461bcd60e51b815260206004820152602e60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201527f6572206f7220617070726f766564000000000000000000000000000000000000606482015260840161080c565b610b0585858585856133a2565b611671611de4565b6001600160a01b0381166116ed5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161080c565b610ca681612667565b6116fe611822565b6111c3838361358d565b611710611822565b6110e7828261358d565b611722611822565b336001600160a01b0385161461174b57604051631eb49d6d60e11b815260040160405180910390fd5b600061175885858561365c565b60008181526101ff602052604090208054919250839160ff1916600183600281111561178657611786615739565b0217905550807f19789dde2d660b739733377add05f87576a360d2d4adea587c2592264f7f6d4e84866040516117bd929190615768565b60405180910390a25050505050565b606061083a6fffffffffffffffffffffffffffffffff198316613741565b600081815261019260205260408120546001600160a01b0384811691160361083a575060009081526101946020526040902054919050565b6101cd5460ff1615610ce05760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161080c565b8051600090815b818110156118ee578381815181106118975761189761578a565b60200260200101516000036118bf57604051631eb49d6d60e11b815260040160405180910390fd5b8381815181106118d1576118d161578a565b6020026020010151836118e4919061586a565b925060010161187d565b5050919050565b600061193d8561193786868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061187692505050565b8461365c565b60008181526101956020526040902054909150611967908690611960908461586a565b868661211f565b949350505050565b81518351146119e65760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d61746368000000000000000000000000000000000000000000000000606482015260840161080c565b6001600160a01b038416611a625760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161080c565b33611a71818787878787613820565b60005b8451811015611bb0576000858281518110611a9157611a9161578a565b602002602001015190506000858381518110611aaf57611aaf61578a565b60209081029190910181015160008481526065835260408082206001600160a01b038e168352909352919091205490915081811015611b565760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201527f72207472616e7366657200000000000000000000000000000000000000000000606482015260840161080c565b60008381526065602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290611b9590849061586a565b9250508190555050505080611ba9906157e8565b9050611a74565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051611c0092919061587d565b60405180910390a4611c16818787878787613968565b6114278187878787876139d2565b610ca6611de4565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611c5f576111c383613bdf565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611cb9575060408051601f3d908101601f19168201909252611cb6918101906158a2565b60015b611d2b5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f742055555053000000000000000000000000000000000000606482015260840161080c565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114611dc05760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c65555549440000000000000000000000000000000000000000000000606482015260840161080c565b506111c3838383613cb5565b600082611dda868685613cda565b1495945050505050565b60fb546001600160a01b03163314610ce05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161080c565b611e46613d26565b6101cd805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382163314801590611eb15750611eaf8233610684565b155b15611ee8576040517fe433766c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008167ffffffffffffffff811115611f0557611f05614e47565b604051908082528060200260200182016040528015611f2e578160200160208202803683370190505b50905060008267ffffffffffffffff811115611f4c57611f4c614e47565b604051908082528060200260200182016040528015611f75578160200160208202803683370190505b50905060008367ffffffffffffffff811115611f9357611f93614e47565b604051908082528060200260200182016040528015611fbc578160200160208202803683370190505b50905060008467ffffffffffffffff811115611fda57611fda614e47565b604051908082528060200260200182016040528015612003578160200160208202803683370190505b50905060005b858110156120cd5760008782815181106120255761202561578a565b602090810291909101810151600081815261019490925260408220805492905591506fffffffffffffffffffffffffffffffff19821687848151811061206d5761206d61578a565b6020026020010181815250508085848151811061208c5761208c61578a565b60200260200101818152505060018484815181106120ac576120ac61578a565b602002602001018181525050505080806120c5906157e8565b915050612009565b506120d9878783613d79565b7f088515a3c7b4e71520602d818f4dec002fadefde30c55e13f390c8d96046990a8487858560405161210e94939291906158bb565b60405180910390a150505050505050565b60fd81118061212e5750600281105b15612165576040517f3ada02e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121a182828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061187692505050565b60008481526101946020526040902054146121cf57604051631eb49d6d60e11b815260040160405180910390fd5b600083815261019460205260408120546fffffffffffffffffffffffffffffffff198516916121ff600185615913565b905060008167ffffffffffffffff81111561221c5761221c614e47565b604051908082528060200260200182016040528015612245578160200160208202803683370190505b50905060008267ffffffffffffffff81111561226357612263614e47565b60405190808252806020026020018201604052801561228c578160200160208202803683370190505b50905060008367ffffffffffffffff8111156122aa576122aa614e47565b6040519080825280602002602001820160405280156122d3578160200160208202803683370190505b50905060008467ffffffffffffffff8111156122f1576122f1614e47565b60405190808252806020026020018201604052801561231a578160200160208202803683370190505b50905060008567ffffffffffffffff81111561233857612338614e47565b604051908082528060200260200182016040528015612361578160200160208202803683370190505b50905060008a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052508451949550938593508b9250821090506123b1576123b161578a565b60200260200101519050816000815181106123ce576123ce61578a565b60200260200101518289815181106123e8576123e861578a565b60200260200101818152505080826000815181106124085761240861578a565b60200260200101818152505060005b888110156125235760008b8152610195602052604090205461243890614023565b8a88828151811061244b5761244b61578a565b6020026020010181815250508d87828151811061246a5761246a61578a565b60200260200101818152505061019560008c815260200190815260200160002060008154612497906157e8565b91829055506124a6908c61586a565b8682815181106124b8576124b861578a565b60200260200101818152505060018582815181106124d8576124d861578a565b6020026020010181815250508281815181106124f6576124f661578a565b60200260200101518482815181106125105761251061578a565b6020908102919091010152600101612417565b5050506125656125303390565b60008d8152610192602090815260408083205481519283019091529181526001600160a01b039091169087908790869061402d565b60005b868110156125ed578181815181106125825761258261578a565b6020026020010151886125959190615913565b97508181815181106125a9576125a961578a565b602002602001015161019460008684815181106125c8576125c861578a565b6020026020010151815260200190815260200160002081905550806001019050612568565b5060008b8152610194602090815260408083208a90558051918201905290815261261c908d908590859061415d565b7f088515a3c7b4e71520602d818f4dec002fadefde30c55e13f390c8d96046990a8585858460405161265194939291906158bb565b60405180910390a1505050505050505050505050565b60fb80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff1661273c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ce0614373565b61274c611822565b6101cd805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611e743390565b600054610100900460ff166127ed5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ca6816143eb565b600054610100900460ff16610ce05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b600054610100900460ff166128cc5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ce061445f565b600054610100900460ff1661293f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ce06144e6565b60008281526101af60209081526040805133818401528082018590528151808203830181526060820183528051908401206080808301919091528251808303909101815260a090910182528051908301208584526101b083528184208185529092529091205460ff16156129e7576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526101af6020526040902054612a05908690869084611dcc565b1580612a36575060008381526101b160209081526040808320546101b290925290912054612a3490849061586a565b115b15612a6d576040517f6dac6a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526101b060209081526040808320848452825291829020805460ff1916600117905581518581529081018390527f51483c8cc684284e9ba3215822230838b766f1698bcc7e922a31e02c3c203bd7910160405180910390a15050505050565b6000612adb8361455a565b612af857604051631eb49d6d60e11b815260040160405180910390fd5b60008381526101956020526040902054612b1190614023565b5060008281526101956020908152604080832080546001808201909255860181018085526101948452828520869055825193840190925292825291612b599186918491614590565b6040805184815260006020820152908101829052606081018390527f5e65fcde72b913ac2870f9df6ea5b6bca757862f44636cb368ed5e339fc524fb9060800160405180910390a19392505050565b816001600160a01b0316836001600160a01b031603612c2f5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c660000000000000000000000000000000000000000000000606482015260840161080c565b6001600160a01b03838116600081815260666020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000612caa610191546146d7565b608061019160008154612cbc906157e8565b9182905550901b60008181526101936020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a1617905561019490915290208490559050612d1d81836146e5565b604080518281526000602082018190529182916001600160a01b038816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a49392505050565b811580612d78575080155b15612daf576040517f6dac6a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526101af602052604090205415612df6576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526101af602090815260408083208590556101b182529182902083905581518581529081018490527f233c854c30aaaad173f2dd900c76d53c64e556d1d009d71466ec1afcb7b5844d91015b60405180910390a1505050565b60fd81511180612e64575060028151105b15612e9b576040517f3ada02e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018251612eab9190615913565b90506000828281518110612ec157612ec161578a565b602002602001015190506000808367ffffffffffffffff811115612ee757612ee7614e47565b604051908082528060200260200182016040528015612f10578160200160208202803683370190505b50905060008467ffffffffffffffff811115612f2e57612f2e614e47565b604051908082528060200260200182016040528015612f57578160200160208202803683370190505b50905060008567ffffffffffffffff811115612f7557612f75614e47565b604051908082528060200260200182016040528015612f9e578160200160208202803683370190505b50905060008667ffffffffffffffff811115612fbc57612fbc614e47565b604051908082528060200260200182016040528015612fe5578160200160208202803683370190505b50905060005b878110156130aa5760008982815181106130075761300761578a565b60200260200101519050808683815181106130245761302461578a565b602002602001018181525050878583815181106130435761304361578a565b60200260200101818152505060018383815181106130635761306361578a565b6020026020010181815250506101946000828152602001908152602001600020548483815181106130965761309661578a565b602090810291909101015250600101612feb565b506130c8338a8686866040518060200160405280600081525061402d565b60005b87811015613136578281815181106130e5576130e561578a565b6020026020010151866130f8919061586a565b955061019460008683815181106131115761311161578a565b60200260200101518152602001908152602001600020600090558060010190506130cb565b50600086815261019460205260408120805487929061315690849061586a565b909155506115c39050898583613d79565b6060838067ffffffffffffffff81111561318357613183614e47565b6040519080825280602002602001820160405280156131ac578160200160208202803683370190505b50915060008167ffffffffffffffff8111156131ca576131ca614e47565b6040519080825280602002602001820160405280156131f3578160200160208202803683370190505b50905060008267ffffffffffffffff81111561321157613211614e47565b60405190808252806020026020018201604052801561323a578160200160208202803683370190505b50905060005b8381101561333957600089898381811061325c5761325c61578a565b90506020020135905061326e8161455a565b61328b57604051631eb49d6d60e11b815260040160405180910390fd5b600081815261019560205260409020546132a490614023565b600081815261019560205260409020805460018082019092558201018888848181106132d2576132d261578a565b90506020020135610194600083815260200190815260200160002081905550808784815181106133045761330461578a565b60200260200101818152505060018584815181106133245761332461578a565b60209081029190910101525050600101613240565b506133558985846040518060200160405280600081525061415d565b7f088515a3c7b4e71520602d818f4dec002fadefde30c55e13f390c8d96046990a888883878a8a60405161338e96959493929190615971565b60405180910390a150505095945050505050565b6001600160a01b03841661341e5760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161080c565b33600061342a85614742565b9050600061343785614742565b9050613447838989858589613820565b60008681526065602090815260408083206001600160a01b038c168452909152902054858110156134e05760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201527f72207472616e7366657200000000000000000000000000000000000000000000606482015260840161080c565b60008781526065602090815260408083206001600160a01b038d8116855292528083208985039055908a1682528120805488929061351f90849061586a565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461357f848a8a86868a613968565b6115c3848a8a8a8a8a61478d565b6001600160a01b03821633148015906135ad57506135ab8233610684565b155b156135e4576040517fe433766c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152610194602052604081208054919055613604838360016148e8565b7f5e65fcde72b913ac2870f9df6ea5b6bca757862f44636cb368ed5e339fc524fb6fffffffffffffffffffffffffffffffff198316604080519182526020820185905260009082015260608101839052608001612e46565b60008260000361367f57604051631eb49d6d60e11b815260040160405180910390fd5b61368a848484612c9c565b6000818152610195602052604081208054929350909182906136ab906157e8565b91829055506136ba908361586a565b9050836101946000838152602001908152602001600020819055506136f18582600160405180602001604052806000815250614590565b6040805183815260006020820152908101829052606081018590527f5e65fcde72b913ac2870f9df6ea5b6bca757862f44636cb368ed5e339fc524fb9060800160405180910390a1509392505050565b600081815260ca602052604081208054606092919061375f906159cd565b80601f016020809104026020016040519081016040528092919081815260200182805461378b906159cd565b80156137d85780601f106137ad576101008083540402835291602001916137d8565b820191906000526020600020905b8154815290600101906020018083116137bb57829003601f168201915b5050505050905060008151116137f6576137f183614ab9565b61093a565b60c98160405160200161380a929190615a20565b6040516020818303038152906040529392505050565b6001600160a01b03851615611427576001600160a01b0384161561142757825160005b8181101561395e5760006138808683815181106138625761386261578a565b60200260200101516fffffffffffffffffffffffffffffffff191690565b60008181526101ff602052604090205490915060ff1660018160028111156138aa576138aa615739565b036138e1576040517fab064ad300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028160028111156138f5576138f5615739565b14801561391d5750600082815261019360205260409020546001600160a01b038a8116911614155b15613954576040517fab064ad300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600101613843565b5050505050505050565b825160005b8181101561395e5785610192600087848151811061398d5761398d61578a565b6020026020010151815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555080600101905061396d565b6001600160a01b0384163b15611427576040517fbc197c810000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063bc197c8190613a2f9089908990889088908890600401615aa7565b6020604051808303816000875af1925050508015613a6a575060408051601f3d908101601f19168201909252613a6791810190615b05565b60015b613b1f57613a76615b22565b806308c379a003613aaf5750613a8a615b3d565b80613a955750613ab1565b8060405162461bcd60e51b815260040161080c9190614dcf565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d4552433131353560448201527f526563656976657220696d706c656d656e746572000000000000000000000000606482015260840161080c565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c810000000000000000000000000000000000000000000000000000000014613bd65760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a6563746560448201527f6420746f6b656e73000000000000000000000000000000000000000000000000606482015260840161080c565b50505050505050565b6001600160a01b0381163b613c5c5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161080c565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b613cbe83614b4d565b600082511180613ccb5750805b156111c3576111dc8383614b8d565b600081815b84811015613d1d57613d0982878784818110613cfd57613cfd61578a565b90506020020135614c8f565b915080613d15816157e8565b915050613cdf565b50949350505050565b6101cd5460ff16610ce05760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161080c565b6001600160a01b038316613df55760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161080c565b8051825114613e6c5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d61746368000000000000000000000000000000000000000000000000606482015260840161080c565b6000339050613e8f81856000868660405180602001604052806000815250613820565b60005b8351811015613fac576000848281518110613eaf57613eaf61578a565b602002602001015190506000848381518110613ecd57613ecd61578a565b60209081029190910181015160008481526065835260408082206001600160a01b038c168352909352919091205490915081811015613f735760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c60448201527f616e636500000000000000000000000000000000000000000000000000000000606482015260840161080c565b60009283526065602090815260408085206001600160a01b038b1686529091529092209103905580613fa4816157e8565b915050613e92565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051613ffd92919061587d565b60405180910390a46111dc81856000868660405180602001604052806000815250613968565b806111c381615be5565b835160005b8181101561395e57600086828151811061404e5761404e61578a565b60200260200101519050600086838151811061406c5761406c61578a565b6020026020010151905061407f8261455a565b1561409d57604051631eb49d6d60e11b815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff1981166fffffffffffffffffffffffffffffffff198316146140fc576040517fb4902a1300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038916331480159061411c575061411a8933610684565b155b15614153576040517fe433766c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600101614032565b6001600160a01b0384166141d95760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161080c565b81518351146142505760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d61746368000000000000000000000000000000000000000000000000606482015260840161080c565b3361426081600087878787613820565b60005b84518110156142fc5783818151811061427e5761427e61578a565b60200260200101516065600087848151811061429c5761429c61578a565b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b0316815260200190815260200160002060008282546142e4919061586a565b909155508190506142f4816157e8565b915050614263565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161434d92919061587d565b60405180910390a461436481600087878787613968565b610b05816000878787876139d2565b600054610100900460ff166143de5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b6101cd805460ff19169055565b600054610100900460ff166144565760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ca681614cbe565b600054610100900460ff166144ca5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b60408051602081019091526000815260c990610ca69082615c5a565b600054610100900460ff166145515760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ce033612667565b60006fffffffffffffffffffffffffffffffff1982168214801561083a5750506fffffffffffffffffffffffffffffffff161590565b6001600160a01b03841661460c5760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161080c565b33600061461885614742565b9050600061462585614742565b905061463683600089858589613820565b60008681526065602090815260408083206001600160a01b038b1684529091528120805487929061466890849061586a565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46146c883600089858589613968565b613bd68360008989898961478d565b608081901c6111c381615be5565b600082815260ca602052604090206146fd8282615c5a565b50817f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b61472984610923565b6040516147369190614dcf565b60405180910390a25050565b6040805160018082528183019092526060916000919060208083019080368337019050509050828160008151811061477c5761477c61578a565b602090810291909101015292915050565b6001600160a01b0384163b15611427576040517ff23a6e610000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063f23a6e61906147ea9089908990889088908890600401615d1a565b6020604051808303816000875af1925050508015614825575060408051601f3d908101601f1916820190925261482291810190615b05565b60015b61483157613a76615b22565b7fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e610000000000000000000000000000000000000000000000000000000014613bd65760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a6563746560448201527f6420746f6b656e73000000000000000000000000000000000000000000000000606482015260840161080c565b6001600160a01b0383166149645760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161080c565b33600061497084614742565b9050600061497d84614742565b905061499d83876000858560405180602001604052806000815250613820565b60008581526065602090815260408083206001600160a01b038a16845290915290205484811015614a355760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c60448201527f616e636500000000000000000000000000000000000000000000000000000000606482015260840161080c565b60008681526065602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a90529092908816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613bd684886000868660405180602001604052806000815250613968565b606060678054614ac8906159cd565b80601f0160208091040260200160405190810160405280929190818152602001828054614af4906159cd565b8015614b415780601f10614b1657610100808354040283529160200191614b41565b820191906000526020600020905b815481529060010190602001808311614b2457829003601f168201915b50505050509050919050565b614b5681613bdf565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b614c0c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161080c565b600080846001600160a01b031684604051614c279190615d52565b600060405180830381855af49150503d8060008114614c62576040519150601f19603f3d011682016040523d82523d6000602084013e614c67565b606091505b5091509150610cc78282604051806060016040528060278152602001615d6f60279139614cca565b6000818310614cab57600082815260208490526040902061093a565b600083815260208390526040902061093a565b60676110e78282615c5a565b60608315614cd957508161093a565b61093a8383815115613a955781518083602001fd5b80356001600160a01b0381168114614d0557600080fd5b919050565b60008060408385031215614d1d57600080fd5b614d2683614cee565b946020939093013593505050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114610ca657600080fd5b600060208284031215614d7457600080fd5b813561093a81614d34565b60005b83811015614d9a578181015183820152602001614d82565b50506000910152565b60008151808452614dbb816020860160208601614d7f565b601f01601f19169290920160200192915050565b60208152600061093a6020830184614da3565b600060208284031215614df457600080fd5b5035919050565b60008083601f840112614e0d57600080fd5b50813567ffffffffffffffff811115614e2557600080fd5b6020830191508360208260051b8501011115614e4057600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff82111715614e9c57614e9c614e47565b6040525050565b600082601f830112614eb457600080fd5b813567ffffffffffffffff811115614ece57614ece614e47565b604051614ee56020601f19601f8501160182614e76565b818152846020838601011115614efa57600080fd5b816020850160208301376000918101602001919091529392505050565b803560038110614d0557600080fd5b60008060008060008060a08789031215614f3f57600080fd5b614f4887614cee565b955060208701359450604087013567ffffffffffffffff80821115614f6c57600080fd5b614f788a838b01614dfb565b90965094506060890135915080821115614f9157600080fd5b50614f9e89828a01614ea3565b925050614fad60808801614f17565b90509295509295509295565b600067ffffffffffffffff821115614fd357614fd3614e47565b5060051b60200190565b600082601f830112614fee57600080fd5b81356020614ffb82614fb9565b6040516150088282614e76565b83815260059390931b850182019282810191508684111561502857600080fd5b8286015b84811015615043578035835291830191830161502c565b509695505050505050565b600080600080600060a0868803121561506657600080fd5b61506f86614cee565b945061507d60208701614cee565b9350604086013567ffffffffffffffff8082111561509a57600080fd5b6150a689838a01614fdd565b945060608801359150808211156150bc57600080fd5b6150c889838a01614fdd565b935060808801359150808211156150de57600080fd5b506150eb88828901614ea3565b9150509295509295909350565b60006020828403121561510a57600080fd5b61093a82614cee565b6000806000806060858703121561512957600080fd5b843567ffffffffffffffff81111561514057600080fd5b61514c87828801614dfb565b90989097506020870135966040013595509350505050565b6000806040838503121561517757600080fd5b823567ffffffffffffffff8082111561518f57600080fd5b818501915085601f8301126151a357600080fd5b813560206151b082614fb9565b6040516151bd8282614e76565b83815260059390931b85018201928281019150898411156151dd57600080fd5b948201945b83861015615202576151f386614cee565b825294820194908201906151e2565b9650508601359250508082111561521857600080fd5b5061522585828601614fdd565b9150509250929050565b600081518084526020808501945080840160005b8381101561525f57815187529582019590820190600101615243565b509495945050505050565b60208152600061093a602083018461522f565b6000806040838503121561529057600080fd5b61529983614cee565b9150602083013567ffffffffffffffff8111156152b557600080fd5b61522585828601614ea3565b6000806000606084860312156152d657600080fd5b6152df84614cee565b9250602084013567ffffffffffffffff808211156152fc57600080fd5b61530887838801614fdd565b9350604086013591508082111561531e57600080fd5b5061532b86828701614fdd565b9150509250925092565b6000806000806060858703121561534b57600080fd5b61535485614cee565b935060208501359250604085013567ffffffffffffffff81111561537757600080fd5b61538387828801614dfb565b95989497509550505050565b6000806000806000608086880312156153a757600080fd5b6153b086614cee565b9450602086013567ffffffffffffffff8111156153cc57600080fd5b6153d888828901614dfb565b9699909850959660408101359660609091013595509350505050565b6000806040838503121561540757600080fd5b50508035926020909101359150565b6000806040838503121561542957600080fd5b61543283614cee565b91506020830135801515811461544757600080fd5b809150509250929050565b600080600080600060a0868803121561546a57600080fd5b61547386614cee565b94506020860135935060408601359250606086013567ffffffffffffffff81111561549d57600080fd5b6154a988828901614ea3565b9250506154b860808701614f17565b90509295509295909350565b6000806000604084860312156154d957600080fd5b6154e284614cee565b9250602084013567ffffffffffffffff8111156154fe57600080fd5b61550a86828701614dfb565b9497909650939450505050565b6000806040838503121561552a57600080fd5b61553383614cee565b915061554160208401614cee565b90509250929050565b6000806040838503121561555d57600080fd5b61556683614cee565b9150602083013567ffffffffffffffff81111561558257600080fd5b61522585828601614fdd565b60008060008060008060006080888a0312156155a957600080fd5b6155b288614cee565b9650602088013567ffffffffffffffff808211156155cf57600080fd5b6155db8b838c01614dfb565b909850965060408a01359150808211156155f457600080fd5b6156008b838c01614dfb565b909650945060608a013591508082111561561957600080fd5b506156268a828b01614dfb565b989b979a50959850939692959293505050565b600080600080600060a0868803121561565157600080fd5b61565a86614cee565b945061566860208701614cee565b93506040860135925060608601359150608086013567ffffffffffffffff81111561569257600080fd5b6150eb88828901614ea3565b6000806000606084860312156156b357600080fd5b6156bc84614cee565b95602085013595506040909401359392505050565b600080600080608085870312156156e757600080fd5b6156f085614cee565b935060208501359250604085013567ffffffffffffffff81111561571357600080fd5b61571f87828801614ea3565b92505061572e60608601614f17565b905092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60408152600061577b6040830185614da3565b90508260208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060001982036157fb576157fb6157b9565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261583757600080fd5b83018035915067ffffffffffffffff82111561585257600080fd5b6020019150600581901b3603821315614e4057600080fd5b8082018082111561083a5761083a6157b9565b604081526000615890604083018561522f565b8281036020840152610cc7818561522f565b6000602082840312156158b457600080fd5b5051919050565b6080815260006158ce608083018761522f565b82810360208401526158e0818761522f565b905082810360408401526158f4818661522f565b90508281036060840152615908818561522f565b979650505050505050565b8181038181111561083a5761083a6157b9565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561595857600080fd5b8260051b80836020870137939093016020019392505050565b60808152600061598560808301888a615926565b8281036020840152615997818861522f565b905082810360408401526159ab818761522f565b905082810360608401526159c0818587615926565b9998505050505050505050565b600181811c908216806159e157607f821691505b602082108103615a1a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b6000808454615a2e816159cd565b60018281168015615a465760018114615a5b57615a8a565b60ff1984168752821515830287019450615a8a565b8860005260208060002060005b85811015615a815781548a820152908401908201615a68565b50505082870194505b505050508351615a9e818360208801614d7f565b01949350505050565b60006001600160a01b03808816835280871660208401525060a06040830152615ad360a083018661522f565b8281036060840152615ae5818661522f565b90508281036080840152615af98185614da3565b98975050505050505050565b600060208284031215615b1757600080fd5b815161093a81614d34565b600060033d11156111ae5760046000803e5060005160e01c90565b600060443d1015615b4b5790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff8160248401118184111715615b9957505050505090565b8285019150815181811115615bb15750505050505090565b843d8701016020828501011115615bcb5750505050505090565b615bda60208286010187614e76565b509095945050505050565b60006fffffffffffffffffffffffffffffffff808316818103615c0a57615c0a6157b9565b6001019392505050565b601f8211156111c357600081815260208120601f850160051c81016020861015615c3b5750805b601f850160051c820191505b8181101561142757828155600101615c47565b815167ffffffffffffffff811115615c7457615c74614e47565b615c8881615c8284546159cd565b84615c14565b602080601f831160018114615cbd5760008415615ca55750858301515b600019600386901b1c1916600185901b178555611427565b600085815260208120601f198616915b82811015615cec57888601518255948401946001909101908401615ccd565b5085821015615d0a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261590860a0830184614da3565b60008251615d64818460208701614d7f565b919091019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212206a8b3623a80eaae2b993831da1aa86618c2f46c3b3bc6495004ca88cd836a9d364736f6c63430008110033", + "deployedBytecode": "0x6080604052600436106102695760003560e01c8063715018a611610153578063b316962f116100cb578063f242432a1161007f578063f5298aca11610064578063f5298aca14610732578063f6b1229314610752578063fda4823c1461077257600080fd5b8063f242432a146106f2578063f2fde38b1461071257600080fd5b8063e985e9c5116100b0578063e985e9c514610669578063eb568a14146106b2578063f1169062146106d257600080fd5b8063b316962f14610629578063c7b26c541461064957600080fd5b80638fc202dd1161012257806399f771a71161010757806399f771a7146105ad578063a21ed980146105cd578063a22cb4651461060957600080fd5b80638fc202dd14610578578063993de1841461058d57600080fd5b8063715018a61461051b5780638129fc1c146105305780638456cb59146105455780638da5cb5b1461055a57600080fd5b80633f4ba83a116101e657806352d1902d116101b55780636352211e1161019a5780636352211e1461048c5780636b20c454146104db5780636ebd893f146104fb57600080fd5b806352d1902d1461045e5780635c975abb1461047357600080fd5b80633f4ba83a146103e95780633f71e944146103fe5780634e1273f41461041e5780634f1ef2861461044b57600080fd5b80631a2e98241161023d5780632eb2c2d6116102225780632eb2c2d6146103895780633659cfe6146103a95780633e11eefe146103c957600080fd5b80631a2e9824146103475780631e75a8b51461036757600080fd5b8062fdd58e1461026e57806301ffc9a7146102a157806306fdde03146102d15780630e89341c14610327575b600080fd5b34801561027a57600080fd5b5061028e610289366004614d0a565b610792565b6040519081526020015b60405180910390f35b3480156102ad57600080fd5b506102c16102bc366004614d62565b610840565b6040519015158152602001610298565b3480156102dd57600080fd5b5061031a6040518060400160405280600f81526020017f4879706572636572744d696e746572000000000000000000000000000000000081525081565b6040516102989190614dcf565b34801561033357600080fd5b5061031a610342366004614de2565b610923565b34801561035357600080fd5b5061028e610362366004614d0a565b61092e565b34801561037357600080fd5b50610387610382366004614f26565b610941565b005b34801561039557600080fd5b506103876103a436600461504e565b610a6a565b3480156103b557600080fd5b506103876103c43660046150f8565b610b0c565b3480156103d557600080fd5b506102c16103e4366004615113565b610ca9565b3480156103f557600080fd5b50610387610cd0565b34801561040a57600080fd5b5061031a610419366004614de2565b610ce2565b34801561042a57600080fd5b5061043e610439366004615164565b610e1f565b604051610298919061526a565b61038761045936600461527d565b610f5d565b34801561046a57600080fd5b5061028e6110eb565b34801561047f57600080fd5b506101cd5460ff166102c1565b34801561049857600080fd5b506104c36104a7366004614de2565b600090815261019260205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610298565b3480156104e757600080fd5b506103876104f63660046152c1565b6111b1565b34801561050757600080fd5b50610387610516366004615335565b6111c8565b34801561052757600080fd5b506103876111e2565b34801561053c57600080fd5b506103876111f4565b34801561055157600080fd5b50610387611355565b34801561056657600080fd5b5060fb546001600160a01b03166104c3565b34801561058457600080fd5b50610387611365565b34801561059957600080fd5b506103876105a836600461538f565b611408565b3480156105b957600080fd5b5061028e6105c8366004614de2565b61142f565b3480156105d957600080fd5b506102c16105e83660046153f4565b6101b060209081526000928352604080842090915290825290205460ff1681565b34801561061557600080fd5b50610387610624366004615416565b611444565b34801561063557600080fd5b50610387610644366004615452565b61144f565b34801561065557600080fd5b506103876106643660046154c4565b6114e4565b34801561067557600080fd5b506102c1610684366004615517565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205460ff1690565b3480156106be57600080fd5b506103876106cd36600461554a565b611529565b3480156106de57600080fd5b506103876106ed36600461558e565b61153b565b3480156106fe57600080fd5b5061038761070d366004615639565b6115ce565b34801561071e57600080fd5b5061038761072d3660046150f8565b611669565b34801561073e57600080fd5b5061038761074d36600461569e565b6116f6565b34801561075e57600080fd5b5061038761076d366004614d0a565b611708565b34801561077e57600080fd5b5061038761078d3660046156d1565b61171a565b60006001600160a01b0383166108155760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201527f616c6964206f776e65720000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b5060008181526065602090815260408083206001600160a01b03861684529091529020545b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fd9b67a260000000000000000000000000000000000000000000000000000000014806108d357507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061083a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461083a565b606061083a826117cc565b600061093a83836117ea565b9392505050565b610949611822565b336001600160a01b0387161461097257604051631eb49d6d60e11b815260040160405180910390fd5b846109af85858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061187692505050565b146109e6576040517f6dac6a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109f4878686866118f5565b60008181526101ff602052604090208054919250839160ff19166001836002811115610a2257610a22615739565b0217905550807f19789dde2d660b739733377add05f87576a360d2d4adea587c2592264f7f6d4e8488604051610a59929190615768565b60405180910390a250505050505050565b6001600160a01b038516331480610a865750610a868533610684565b610af85760405162461bcd60e51b815260206004820152602e60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201527f6572206f7220617070726f766564000000000000000000000000000000000000606482015260840161080c565b610b05858585858561196f565b5050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610baa5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161080c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c057f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614610c815760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161080c565b610c8a81611c24565b60408051600080825260208201909252610ca691839190611c2c565b50565b60008281526101af6020526040812054610cc7908690869085611dcc565b95945050505050565b610cd8611de4565b610ce0611e3e565b565b6fffffffffffffffffffffffffffffffff19811660009081526101ff602052604081205460609160ff90911690816002811115610d2157610d21615739565b03610d6157505060408051808201909152600881527f416c6c6f77416c6c0000000000000000000000000000000000000000000000006020820152919050565b6001816002811115610d7557610d75615739565b03610db557505060408051808201909152600b81527f446973616c6c6f77416c6c0000000000000000000000000000000000000000006020820152919050565b6002816002811115610dc957610dc9615739565b03610e0957505060408051808201909152600f81527f46726f6d43726561746f724f6e6c7900000000000000000000000000000000006020820152919050565b5050604080516020810190915260008152919050565b60608151835114610e985760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d617463680000000000000000000000000000000000000000000000606482015260840161080c565b6000835167ffffffffffffffff811115610eb457610eb4614e47565b604051908082528060200260200182016040528015610edd578160200160208202803683370190505b50905060005b8451811015610f5557610f28858281518110610f0157610f0161578a565b6020026020010151858381518110610f1b57610f1b61578a565b6020026020010151610792565b828281518110610f3a57610f3a61578a565b6020908102919091010152610f4e816157e8565b9050610ee3565b509392505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610ffb5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161080c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166110567f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b0316146110d25760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161080c565b6110db82611c24565b6110e782826001611c2c565b5050565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461118b5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161080c565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b90565b6111b9611822565b6111c38383611e91565b505050565b6111d0611822565b6111dc8484848461211f565b50505050565b6111ea611de4565b610ce06000612667565b600054610100900460ff16158080156112145750600054600160ff909116105b8061122e5750303b15801561122e575060005460ff166001145b6112a05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161080c565b6000805460ff1916600117905580156112e057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6112e8611365565b6112f06126d1565b8015610ca657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b61135d611de4565b610ce0612744565b600054610100900460ff166113d05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b6113e860405180602001604052806000815250612782565b6113f06127f6565b6113f8612861565b6114006128d4565b610ce06127f6565b611410611822565b61141c84848484612947565b611427858383612ad0565b505050505050565b6000818152610194602052604081205461083a565b6110e7338383612ba8565b611457611822565b6000611464868685612c9c565b9050611471818587612d6d565b60008181526101ff60205260409020805483919060ff1916600183600281111561149d5761149d615739565b0217905550807f19789dde2d660b739733377add05f87576a360d2d4adea587c2592264f7f6d4e84876040516114d4929190615768565b60405180910390a2505050505050565b6114ec611822565b6111c383838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612e5392505050565b611531611822565b6110e78282611e91565b611543611822565b8260005b818110156115b5576115ad8888838181106115645761156461578a565b90506020028101906115769190615802565b8888858181106115885761158861578a565b905060200201358787868181106115a1576115a161578a565b90506020020135612947565b600101611547565b506115c38886868686613167565b505050505050505050565b6001600160a01b0385163314806115ea57506115ea8533610684565b61165c5760405162461bcd60e51b815260206004820152602e60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201527f6572206f7220617070726f766564000000000000000000000000000000000000606482015260840161080c565b610b0585858585856133a2565b611671611de4565b6001600160a01b0381166116ed5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161080c565b610ca681612667565b6116fe611822565b6111c3838361358d565b611710611822565b6110e7828261358d565b611722611822565b336001600160a01b0385161461174b57604051631eb49d6d60e11b815260040160405180910390fd5b600061175885858561365c565b60008181526101ff602052604090208054919250839160ff1916600183600281111561178657611786615739565b0217905550807f19789dde2d660b739733377add05f87576a360d2d4adea587c2592264f7f6d4e84866040516117bd929190615768565b60405180910390a25050505050565b606061083a6fffffffffffffffffffffffffffffffff198316613741565b600081815261019260205260408120546001600160a01b0384811691160361083a575060009081526101946020526040902054919050565b6101cd5460ff1615610ce05760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015260640161080c565b8051600090815b818110156118ee578381815181106118975761189761578a565b60200260200101516000036118bf57604051631eb49d6d60e11b815260040160405180910390fd5b8381815181106118d1576118d161578a565b6020026020010151836118e4919061586a565b925060010161187d565b5050919050565b600061193d8561193786868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061187692505050565b8461365c565b60008181526101956020526040902054909150611967908690611960908461586a565b868661211f565b949350505050565b81518351146119e65760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d61746368000000000000000000000000000000000000000000000000606482015260840161080c565b6001600160a01b038416611a625760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161080c565b33611a71818787878787613820565b60005b8451811015611bb0576000858281518110611a9157611a9161578a565b602002602001015190506000858381518110611aaf57611aaf61578a565b60209081029190910181015160008481526065835260408082206001600160a01b038e168352909352919091205490915081811015611b565760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201527f72207472616e7366657200000000000000000000000000000000000000000000606482015260840161080c565b60008381526065602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290611b9590849061586a565b9250508190555050505080611ba9906157e8565b9050611a74565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051611c0092919061587d565b60405180910390a4611c16818787878787613968565b6114278187878787876139d2565b610ca6611de4565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611c5f576111c383613bdf565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611cb9575060408051601f3d908101601f19168201909252611cb6918101906158a2565b60015b611d2b5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f742055555053000000000000000000000000000000000000606482015260840161080c565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114611dc05760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c65555549440000000000000000000000000000000000000000000000606482015260840161080c565b506111c3838383613cb5565b600082611dda868685613cda565b1495945050505050565b60fb546001600160a01b03163314610ce05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161080c565b611e46613d26565b6101cd805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382163314801590611eb15750611eaf8233610684565b155b15611ee8576040517fe433766c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008167ffffffffffffffff811115611f0557611f05614e47565b604051908082528060200260200182016040528015611f2e578160200160208202803683370190505b50905060008267ffffffffffffffff811115611f4c57611f4c614e47565b604051908082528060200260200182016040528015611f75578160200160208202803683370190505b50905060008367ffffffffffffffff811115611f9357611f93614e47565b604051908082528060200260200182016040528015611fbc578160200160208202803683370190505b50905060008467ffffffffffffffff811115611fda57611fda614e47565b604051908082528060200260200182016040528015612003578160200160208202803683370190505b50905060005b858110156120cd5760008782815181106120255761202561578a565b602090810291909101810151600081815261019490925260408220805492905591506fffffffffffffffffffffffffffffffff19821687848151811061206d5761206d61578a565b6020026020010181815250508085848151811061208c5761208c61578a565b60200260200101818152505060018484815181106120ac576120ac61578a565b602002602001018181525050505080806120c5906157e8565b915050612009565b506120d9878783613d79565b7f088515a3c7b4e71520602d818f4dec002fadefde30c55e13f390c8d96046990a8487858560405161210e94939291906158bb565b60405180910390a150505050505050565b60fd81118061212e5750600281105b15612165576040517f3ada02e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121a182828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061187692505050565b60008481526101946020526040902054146121cf57604051631eb49d6d60e11b815260040160405180910390fd5b600083815261019460205260408120546fffffffffffffffffffffffffffffffff198516916121ff600185615913565b905060008167ffffffffffffffff81111561221c5761221c614e47565b604051908082528060200260200182016040528015612245578160200160208202803683370190505b50905060008267ffffffffffffffff81111561226357612263614e47565b60405190808252806020026020018201604052801561228c578160200160208202803683370190505b50905060008367ffffffffffffffff8111156122aa576122aa614e47565b6040519080825280602002602001820160405280156122d3578160200160208202803683370190505b50905060008467ffffffffffffffff8111156122f1576122f1614e47565b60405190808252806020026020018201604052801561231a578160200160208202803683370190505b50905060008567ffffffffffffffff81111561233857612338614e47565b604051908082528060200260200182016040528015612361578160200160208202803683370190505b50905060008a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052508451949550938593508b9250821090506123b1576123b161578a565b60200260200101519050816000815181106123ce576123ce61578a565b60200260200101518289815181106123e8576123e861578a565b60200260200101818152505080826000815181106124085761240861578a565b60200260200101818152505060005b888110156125235760008b8152610195602052604090205461243890614023565b8a88828151811061244b5761244b61578a565b6020026020010181815250508d87828151811061246a5761246a61578a565b60200260200101818152505061019560008c815260200190815260200160002060008154612497906157e8565b91829055506124a6908c61586a565b8682815181106124b8576124b861578a565b60200260200101818152505060018582815181106124d8576124d861578a565b6020026020010181815250508281815181106124f6576124f661578a565b60200260200101518482815181106125105761251061578a565b6020908102919091010152600101612417565b5050506125656125303390565b60008d8152610192602090815260408083205481519283019091529181526001600160a01b039091169087908790869061402d565b60005b868110156125ed578181815181106125825761258261578a565b6020026020010151886125959190615913565b97508181815181106125a9576125a961578a565b602002602001015161019460008684815181106125c8576125c861578a565b6020026020010151815260200190815260200160002081905550806001019050612568565b5060008b8152610194602090815260408083208a90558051918201905290815261261c908d908590859061415d565b7f088515a3c7b4e71520602d818f4dec002fadefde30c55e13f390c8d96046990a8585858460405161265194939291906158bb565b60405180910390a1505050505050505050505050565b60fb80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff1661273c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ce0614373565b61274c611822565b6101cd805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611e743390565b600054610100900460ff166127ed5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ca6816143eb565b600054610100900460ff16610ce05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b600054610100900460ff166128cc5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ce061445f565b600054610100900460ff1661293f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ce06144e6565b60008281526101af60209081526040805133818401528082018590528151808203830181526060820183528051908401206080808301919091528251808303909101815260a090910182528051908301208584526101b083528184208185529092529091205460ff16156129e7576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526101af6020526040902054612a05908690869084611dcc565b1580612a36575060008381526101b160209081526040808320546101b290925290912054612a3490849061586a565b115b15612a6d576040517f6dac6a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526101b060209081526040808320848452825291829020805460ff1916600117905581518581529081018390527f51483c8cc684284e9ba3215822230838b766f1698bcc7e922a31e02c3c203bd7910160405180910390a15050505050565b6000612adb8361455a565b612af857604051631eb49d6d60e11b815260040160405180910390fd5b60008381526101956020526040902054612b1190614023565b5060008281526101956020908152604080832080546001808201909255860181018085526101948452828520869055825193840190925292825291612b599186918491614590565b6040805184815260006020820152908101829052606081018390527f5e65fcde72b913ac2870f9df6ea5b6bca757862f44636cb368ed5e339fc524fb9060800160405180910390a19392505050565b816001600160a01b0316836001600160a01b031603612c2f5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c660000000000000000000000000000000000000000000000606482015260840161080c565b6001600160a01b03838116600081815260666020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000612caa610191546146d7565b608061019160008154612cbc906157e8565b9182905550901b60008181526101936020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a1617905561019490915290208490559050612d1d81836146e5565b604080518281526000602082018190529182916001600160a01b038816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a49392505050565b811580612d78575080155b15612daf576040517f6dac6a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526101af602052604090205415612df6576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526101af602090815260408083208590556101b182529182902083905581518581529081018490527f233c854c30aaaad173f2dd900c76d53c64e556d1d009d71466ec1afcb7b5844d91015b60405180910390a1505050565b60fd81511180612e64575060028151105b15612e9b576040517f3ada02e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018251612eab9190615913565b90506000828281518110612ec157612ec161578a565b602002602001015190506000808367ffffffffffffffff811115612ee757612ee7614e47565b604051908082528060200260200182016040528015612f10578160200160208202803683370190505b50905060008467ffffffffffffffff811115612f2e57612f2e614e47565b604051908082528060200260200182016040528015612f57578160200160208202803683370190505b50905060008567ffffffffffffffff811115612f7557612f75614e47565b604051908082528060200260200182016040528015612f9e578160200160208202803683370190505b50905060008667ffffffffffffffff811115612fbc57612fbc614e47565b604051908082528060200260200182016040528015612fe5578160200160208202803683370190505b50905060005b878110156130aa5760008982815181106130075761300761578a565b60200260200101519050808683815181106130245761302461578a565b602002602001018181525050878583815181106130435761304361578a565b60200260200101818152505060018383815181106130635761306361578a565b6020026020010181815250506101946000828152602001908152602001600020548483815181106130965761309661578a565b602090810291909101015250600101612feb565b506130c8338a8686866040518060200160405280600081525061402d565b60005b87811015613136578281815181106130e5576130e561578a565b6020026020010151866130f8919061586a565b955061019460008683815181106131115761311161578a565b60200260200101518152602001908152602001600020600090558060010190506130cb565b50600086815261019460205260408120805487929061315690849061586a565b909155506115c39050898583613d79565b6060838067ffffffffffffffff81111561318357613183614e47565b6040519080825280602002602001820160405280156131ac578160200160208202803683370190505b50915060008167ffffffffffffffff8111156131ca576131ca614e47565b6040519080825280602002602001820160405280156131f3578160200160208202803683370190505b50905060008267ffffffffffffffff81111561321157613211614e47565b60405190808252806020026020018201604052801561323a578160200160208202803683370190505b50905060005b8381101561333957600089898381811061325c5761325c61578a565b90506020020135905061326e8161455a565b61328b57604051631eb49d6d60e11b815260040160405180910390fd5b600081815261019560205260409020546132a490614023565b600081815261019560205260409020805460018082019092558201018888848181106132d2576132d261578a565b90506020020135610194600083815260200190815260200160002081905550808784815181106133045761330461578a565b60200260200101818152505060018584815181106133245761332461578a565b60209081029190910101525050600101613240565b506133558985846040518060200160405280600081525061415d565b7f088515a3c7b4e71520602d818f4dec002fadefde30c55e13f390c8d96046990a888883878a8a60405161338e96959493929190615971565b60405180910390a150505095945050505050565b6001600160a01b03841661341e5760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161080c565b33600061342a85614742565b9050600061343785614742565b9050613447838989858589613820565b60008681526065602090815260408083206001600160a01b038c168452909152902054858110156134e05760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201527f72207472616e7366657200000000000000000000000000000000000000000000606482015260840161080c565b60008781526065602090815260408083206001600160a01b038d8116855292528083208985039055908a1682528120805488929061351f90849061586a565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461357f848a8a86868a613968565b6115c3848a8a8a8a8a61478d565b6001600160a01b03821633148015906135ad57506135ab8233610684565b155b156135e4576040517fe433766c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152610194602052604081208054919055613604838360016148e8565b7f5e65fcde72b913ac2870f9df6ea5b6bca757862f44636cb368ed5e339fc524fb6fffffffffffffffffffffffffffffffff198316604080519182526020820185905260009082015260608101839052608001612e46565b60008260000361367f57604051631eb49d6d60e11b815260040160405180910390fd5b61368a848484612c9c565b6000818152610195602052604081208054929350909182906136ab906157e8565b91829055506136ba908361586a565b9050836101946000838152602001908152602001600020819055506136f18582600160405180602001604052806000815250614590565b6040805183815260006020820152908101829052606081018590527f5e65fcde72b913ac2870f9df6ea5b6bca757862f44636cb368ed5e339fc524fb9060800160405180910390a1509392505050565b600081815260ca602052604081208054606092919061375f906159cd565b80601f016020809104026020016040519081016040528092919081815260200182805461378b906159cd565b80156137d85780601f106137ad576101008083540402835291602001916137d8565b820191906000526020600020905b8154815290600101906020018083116137bb57829003601f168201915b5050505050905060008151116137f6576137f183614ab9565b61093a565b60c98160405160200161380a929190615a20565b6040516020818303038152906040529392505050565b6001600160a01b03851615611427576001600160a01b0384161561142757825160005b8181101561395e5760006138808683815181106138625761386261578a565b60200260200101516fffffffffffffffffffffffffffffffff191690565b60008181526101ff602052604090205490915060ff1660018160028111156138aa576138aa615739565b036138e1576040517fab064ad300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028160028111156138f5576138f5615739565b14801561391d5750600082815261019360205260409020546001600160a01b038a8116911614155b15613954576040517fab064ad300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600101613843565b5050505050505050565b825160005b8181101561395e5785610192600087848151811061398d5761398d61578a565b6020026020010151815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555080600101905061396d565b6001600160a01b0384163b15611427576040517fbc197c810000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063bc197c8190613a2f9089908990889088908890600401615aa7565b6020604051808303816000875af1925050508015613a6a575060408051601f3d908101601f19168201909252613a6791810190615b05565b60015b613b1f57613a76615b22565b806308c379a003613aaf5750613a8a615b3d565b80613a955750613ab1565b8060405162461bcd60e51b815260040161080c9190614dcf565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d4552433131353560448201527f526563656976657220696d706c656d656e746572000000000000000000000000606482015260840161080c565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c810000000000000000000000000000000000000000000000000000000014613bd65760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a6563746560448201527f6420746f6b656e73000000000000000000000000000000000000000000000000606482015260840161080c565b50505050505050565b6001600160a01b0381163b613c5c5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161080c565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b613cbe83614b4d565b600082511180613ccb5750805b156111c3576111dc8383614b8d565b600081815b84811015613d1d57613d0982878784818110613cfd57613cfd61578a565b90506020020135614c8f565b915080613d15816157e8565b915050613cdf565b50949350505050565b6101cd5460ff16610ce05760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161080c565b6001600160a01b038316613df55760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161080c565b8051825114613e6c5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d61746368000000000000000000000000000000000000000000000000606482015260840161080c565b6000339050613e8f81856000868660405180602001604052806000815250613820565b60005b8351811015613fac576000848281518110613eaf57613eaf61578a565b602002602001015190506000848381518110613ecd57613ecd61578a565b60209081029190910181015160008481526065835260408082206001600160a01b038c168352909352919091205490915081811015613f735760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c60448201527f616e636500000000000000000000000000000000000000000000000000000000606482015260840161080c565b60009283526065602090815260408085206001600160a01b038b1686529091529092209103905580613fa4816157e8565b915050613e92565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051613ffd92919061587d565b60405180910390a46111dc81856000868660405180602001604052806000815250613968565b806111c381615be5565b835160005b8181101561395e57600086828151811061404e5761404e61578a565b60200260200101519050600086838151811061406c5761406c61578a565b6020026020010151905061407f8261455a565b1561409d57604051631eb49d6d60e11b815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff1981166fffffffffffffffffffffffffffffffff198316146140fc576040517fb4902a1300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038916331480159061411c575061411a8933610684565b155b15614153576040517fe433766c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600101614032565b6001600160a01b0384166141d95760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161080c565b81518351146142505760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d61746368000000000000000000000000000000000000000000000000606482015260840161080c565b3361426081600087878787613820565b60005b84518110156142fc5783818151811061427e5761427e61578a565b60200260200101516065600087848151811061429c5761429c61578a565b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b0316815260200190815260200160002060008282546142e4919061586a565b909155508190506142f4816157e8565b915050614263565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161434d92919061587d565b60405180910390a461436481600087878787613968565b610b05816000878787876139d2565b600054610100900460ff166143de5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b6101cd805460ff19169055565b600054610100900460ff166144565760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ca681614cbe565b600054610100900460ff166144ca5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b60408051602081019091526000815260c990610ca69082615c5a565b600054610100900460ff166145515760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161080c565b610ce033612667565b60006fffffffffffffffffffffffffffffffff1982168214801561083a5750506fffffffffffffffffffffffffffffffff161590565b6001600160a01b03841661460c5760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161080c565b33600061461885614742565b9050600061462585614742565b905061463683600089858589613820565b60008681526065602090815260408083206001600160a01b038b1684529091528120805487929061466890849061586a565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46146c883600089858589613968565b613bd68360008989898961478d565b608081901c6111c381615be5565b600082815260ca602052604090206146fd8282615c5a565b50817f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b61472984610923565b6040516147369190614dcf565b60405180910390a25050565b6040805160018082528183019092526060916000919060208083019080368337019050509050828160008151811061477c5761477c61578a565b602090810291909101015292915050565b6001600160a01b0384163b15611427576040517ff23a6e610000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063f23a6e61906147ea9089908990889088908890600401615d1a565b6020604051808303816000875af1925050508015614825575060408051601f3d908101601f1916820190925261482291810190615b05565b60015b61483157613a76615b22565b7fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e610000000000000000000000000000000000000000000000000000000014613bd65760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a6563746560448201527f6420746f6b656e73000000000000000000000000000000000000000000000000606482015260840161080c565b6001600160a01b0383166149645760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161080c565b33600061497084614742565b9050600061497d84614742565b905061499d83876000858560405180602001604052806000815250613820565b60008581526065602090815260408083206001600160a01b038a16845290915290205484811015614a355760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c60448201527f616e636500000000000000000000000000000000000000000000000000000000606482015260840161080c565b60008681526065602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a90529092908816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4613bd684886000868660405180602001604052806000815250613968565b606060678054614ac8906159cd565b80601f0160208091040260200160405190810160405280929190818152602001828054614af4906159cd565b8015614b415780601f10614b1657610100808354040283529160200191614b41565b820191906000526020600020905b815481529060010190602001808311614b2457829003601f168201915b50505050509050919050565b614b5681613bdf565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b614c0c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161080c565b600080846001600160a01b031684604051614c279190615d52565b600060405180830381855af49150503d8060008114614c62576040519150601f19603f3d011682016040523d82523d6000602084013e614c67565b606091505b5091509150610cc78282604051806060016040528060278152602001615d6f60279139614cca565b6000818310614cab57600082815260208490526040902061093a565b600083815260208390526040902061093a565b60676110e78282615c5a565b60608315614cd957508161093a565b61093a8383815115613a955781518083602001fd5b80356001600160a01b0381168114614d0557600080fd5b919050565b60008060408385031215614d1d57600080fd5b614d2683614cee565b946020939093013593505050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114610ca657600080fd5b600060208284031215614d7457600080fd5b813561093a81614d34565b60005b83811015614d9a578181015183820152602001614d82565b50506000910152565b60008151808452614dbb816020860160208601614d7f565b601f01601f19169290920160200192915050565b60208152600061093a6020830184614da3565b600060208284031215614df457600080fd5b5035919050565b60008083601f840112614e0d57600080fd5b50813567ffffffffffffffff811115614e2557600080fd5b6020830191508360208260051b8501011115614e4057600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff82111715614e9c57614e9c614e47565b6040525050565b600082601f830112614eb457600080fd5b813567ffffffffffffffff811115614ece57614ece614e47565b604051614ee56020601f19601f8501160182614e76565b818152846020838601011115614efa57600080fd5b816020850160208301376000918101602001919091529392505050565b803560038110614d0557600080fd5b60008060008060008060a08789031215614f3f57600080fd5b614f4887614cee565b955060208701359450604087013567ffffffffffffffff80821115614f6c57600080fd5b614f788a838b01614dfb565b90965094506060890135915080821115614f9157600080fd5b50614f9e89828a01614ea3565b925050614fad60808801614f17565b90509295509295509295565b600067ffffffffffffffff821115614fd357614fd3614e47565b5060051b60200190565b600082601f830112614fee57600080fd5b81356020614ffb82614fb9565b6040516150088282614e76565b83815260059390931b850182019282810191508684111561502857600080fd5b8286015b84811015615043578035835291830191830161502c565b509695505050505050565b600080600080600060a0868803121561506657600080fd5b61506f86614cee565b945061507d60208701614cee565b9350604086013567ffffffffffffffff8082111561509a57600080fd5b6150a689838a01614fdd565b945060608801359150808211156150bc57600080fd5b6150c889838a01614fdd565b935060808801359150808211156150de57600080fd5b506150eb88828901614ea3565b9150509295509295909350565b60006020828403121561510a57600080fd5b61093a82614cee565b6000806000806060858703121561512957600080fd5b843567ffffffffffffffff81111561514057600080fd5b61514c87828801614dfb565b90989097506020870135966040013595509350505050565b6000806040838503121561517757600080fd5b823567ffffffffffffffff8082111561518f57600080fd5b818501915085601f8301126151a357600080fd5b813560206151b082614fb9565b6040516151bd8282614e76565b83815260059390931b85018201928281019150898411156151dd57600080fd5b948201945b83861015615202576151f386614cee565b825294820194908201906151e2565b9650508601359250508082111561521857600080fd5b5061522585828601614fdd565b9150509250929050565b600081518084526020808501945080840160005b8381101561525f57815187529582019590820190600101615243565b509495945050505050565b60208152600061093a602083018461522f565b6000806040838503121561529057600080fd5b61529983614cee565b9150602083013567ffffffffffffffff8111156152b557600080fd5b61522585828601614ea3565b6000806000606084860312156152d657600080fd5b6152df84614cee565b9250602084013567ffffffffffffffff808211156152fc57600080fd5b61530887838801614fdd565b9350604086013591508082111561531e57600080fd5b5061532b86828701614fdd565b9150509250925092565b6000806000806060858703121561534b57600080fd5b61535485614cee565b935060208501359250604085013567ffffffffffffffff81111561537757600080fd5b61538387828801614dfb565b95989497509550505050565b6000806000806000608086880312156153a757600080fd5b6153b086614cee565b9450602086013567ffffffffffffffff8111156153cc57600080fd5b6153d888828901614dfb565b9699909850959660408101359660609091013595509350505050565b6000806040838503121561540757600080fd5b50508035926020909101359150565b6000806040838503121561542957600080fd5b61543283614cee565b91506020830135801515811461544757600080fd5b809150509250929050565b600080600080600060a0868803121561546a57600080fd5b61547386614cee565b94506020860135935060408601359250606086013567ffffffffffffffff81111561549d57600080fd5b6154a988828901614ea3565b9250506154b860808701614f17565b90509295509295909350565b6000806000604084860312156154d957600080fd5b6154e284614cee565b9250602084013567ffffffffffffffff8111156154fe57600080fd5b61550a86828701614dfb565b9497909650939450505050565b6000806040838503121561552a57600080fd5b61553383614cee565b915061554160208401614cee565b90509250929050565b6000806040838503121561555d57600080fd5b61556683614cee565b9150602083013567ffffffffffffffff81111561558257600080fd5b61522585828601614fdd565b60008060008060008060006080888a0312156155a957600080fd5b6155b288614cee565b9650602088013567ffffffffffffffff808211156155cf57600080fd5b6155db8b838c01614dfb565b909850965060408a01359150808211156155f457600080fd5b6156008b838c01614dfb565b909650945060608a013591508082111561561957600080fd5b506156268a828b01614dfb565b989b979a50959850939692959293505050565b600080600080600060a0868803121561565157600080fd5b61565a86614cee565b945061566860208701614cee565b93506040860135925060608601359150608086013567ffffffffffffffff81111561569257600080fd5b6150eb88828901614ea3565b6000806000606084860312156156b357600080fd5b6156bc84614cee565b95602085013595506040909401359392505050565b600080600080608085870312156156e757600080fd5b6156f085614cee565b935060208501359250604085013567ffffffffffffffff81111561571357600080fd5b61571f87828801614ea3565b92505061572e60608601614f17565b905092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60408152600061577b6040830185614da3565b90508260208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060001982036157fb576157fb6157b9565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261583757600080fd5b83018035915067ffffffffffffffff82111561585257600080fd5b6020019150600581901b3603821315614e4057600080fd5b8082018082111561083a5761083a6157b9565b604081526000615890604083018561522f565b8281036020840152610cc7818561522f565b6000602082840312156158b457600080fd5b5051919050565b6080815260006158ce608083018761522f565b82810360208401526158e0818761522f565b905082810360408401526158f4818661522f565b90508281036060840152615908818561522f565b979650505050505050565b8181038181111561083a5761083a6157b9565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561595857600080fd5b8260051b80836020870137939093016020019392505050565b60808152600061598560808301888a615926565b8281036020840152615997818861522f565b905082810360408401526159ab818761522f565b905082810360608401526159c0818587615926565b9998505050505050505050565b600181811c908216806159e157607f821691505b602082108103615a1a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b6000808454615a2e816159cd565b60018281168015615a465760018114615a5b57615a8a565b60ff1984168752821515830287019450615a8a565b8860005260208060002060005b85811015615a815781548a820152908401908201615a68565b50505082870194505b505050508351615a9e818360208801614d7f565b01949350505050565b60006001600160a01b03808816835280871660208401525060a06040830152615ad360a083018661522f565b8281036060840152615ae5818661522f565b90508281036080840152615af98185614da3565b98975050505050505050565b600060208284031215615b1757600080fd5b815161093a81614d34565b600060033d11156111ae5760046000803e5060005160e01c90565b600060443d1015615b4b5790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff8160248401118184111715615b9957505050505090565b8285019150815181811115615bb15750505050505090565b843d8701016020828501011115615bcb5750505050505090565b615bda60208286010187614e76565b509095945050505050565b60006fffffffffffffffffffffffffffffffff808316818103615c0a57615c0a6157b9565b6001019392505050565b601f8211156111c357600081815260208120601f850160051c81016020861015615c3b5750805b601f850160051c820191505b8181101561142757828155600101615c47565b815167ffffffffffffffff811115615c7457615c74614e47565b615c8881615c8284546159cd565b84615c14565b602080601f831160018114615cbd5760008415615ca55750858301515b600019600386901b1c1916600185901b178555611427565b600085815260208120601f198616915b82811015615cec57888601518255948401946001909101908401615ccd565b5085821015615d0a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261590860a0830184614da3565b60008251615d64818460208701614d7f565b919091019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212206a8b3623a80eaae2b993831da1aa86618c2f46c3b3bc6495004ca88cd836a9d364736f6c63430008110033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/sdk/test/setup-env.ts b/sdk/test/setup-env.ts index 5b983c4f..ba1080eb 100644 --- a/sdk/test/setup-env.ts +++ b/sdk/test/setup-env.ts @@ -1,9 +1,19 @@ import dotenv from "dotenv"; +import { startProxy } from "@viem/anvil"; +import fetchMock from "jest-fetch-mock"; +fetchMock.enableMocks(); dotenv.config({ path: "./.env" }); const reloadEnv = () => { dotenv.config({ path: "./.env" }); }; +export default async function () { + return await startProxy({ + port: 8545, // By default, the proxy will listen on port 8545. + host: "::", // By default, the proxy will listen on all interfaces. + }); +} + export { reloadEnv }; diff --git a/sdk/test/storage.test.ts b/sdk/test/storage.test.ts index 004815bc..6be0931f 100644 --- a/sdk/test/storage.test.ts +++ b/sdk/test/storage.test.ts @@ -1,7 +1,7 @@ import { expect } from "chai"; import { providers } from "ethers"; import sinon from "sinon"; -import { HypercertMetadata } from "src/index.js"; +import { HypercertMetadata } from "../src/index.js"; import HypercertsStorage from "../src/storage.js"; import { StorageError } from "../src/types/errors.js"; diff --git a/sdk/test/storage/nft.storage.test.ts b/sdk/test/storage/nft.storage.test.ts index 5ba4fc1a..59dd6c1d 100644 --- a/sdk/test/storage/nft.storage.test.ts +++ b/sdk/test/storage/nft.storage.test.ts @@ -1,6 +1,8 @@ import { jest } from "@jest/globals"; import { rest } from "msw"; import { setupServer } from "msw/node"; +//eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import { NFTStorage } from "nft.storage"; import HypercertsStorage from "../../src/storage.js"; diff --git a/sdk/test/types/errors.test.ts b/sdk/test/types/errors.test.ts index 012a88eb..de5e66c5 100644 --- a/sdk/test/types/errors.test.ts +++ b/sdk/test/types/errors.test.ts @@ -8,7 +8,7 @@ import { StorageError, UnknownSchemaError, UnsupportedChainError, -} from "../../src/types/errors.js"; +} from "../../src/types/errors"; describe.only("Error types", () => { it("has ClientError", () => { diff --git a/sdk/test/utils/config.test.ts b/sdk/test/utils/config.test.ts index 1290fa90..4f0f3ad5 100644 --- a/sdk/test/utils/config.test.ts +++ b/sdk/test/utils/config.test.ts @@ -1,9 +1,7 @@ import chai, { expect } from "chai"; import chaiSubset from "chai-subset"; -import { ethers } from "ethers"; import sinon from "sinon"; -import { DEFAULT_CHAIN_ID } from "../../src/constants.js"; import { ConfigurationError, HypercertClientConfig, @@ -12,18 +10,19 @@ import { } from "../../src/types/index.js"; import { getConfig } from "../../src/utils/config.js"; import { reloadEnv } from "../../test/setup-env.js"; +import { walletClient, publicClient } from "../helpers.js"; chai.use(chaiSubset); describe("Config: chainId and chainName", () => { it("should throw an error when the chainId is not supported", () => { try { - getConfig({ chainId: 1337 }); + getConfig({ id: 1337 }); expect.fail("Should throw UnsupportedChainError"); } catch (e) { expect(e instanceof UnsupportedChainError).to.be.true; const error = e as UnsupportedChainError; - expect(error.message).to.eq("chainId=1337 is not yet supported"); + expect(error.message).to.eq("No default config for chainId=1337 found in SDK"); } }); }); @@ -36,23 +35,23 @@ describe("Config: contractAddress", () => { }); it("should return the contract address specified by overrides", () => { - const overrides: Partial = { contractAddress: "0x1234567890123456789012345678901234567890" }; + const overrides: Partial = { + id: 5, + contractAddress: "0x1234567890123456789012345678901234567890", + }; const config = getConfig(overrides); expect(config.contractAddress).to.equal(overrides.contractAddress); }); - it("should return the contract address specified by the CONTRACT_ADDRESS environment variable", () => { - const CONTRACT_ADDRESS = "0x1234567890123456789012345678901234567890"; - sinon.stub(process, "env").value({ CONTRACT_ADDRESS }); - - const config = getConfig({}); - expect(config.contractAddress).to.equal(CONTRACT_ADDRESS); - delete process.env.CONTRACT_ADDRESS; - }); - it("should throw an error when the contract address specified by overrides is invalid", () => { - const overrides: Partial = { contractAddress: "invalid-address" }; - expect(() => getConfig(overrides)).to.throw(InvalidOrMissingError, "Invalid contract address"); + const overrides: Partial = { id: 5, contractAddress: "invalid-address" }; + try { + getConfig(overrides); + } catch (e) { + expect(e instanceof InvalidOrMissingError).to.be.true; + const error = e as InvalidOrMissingError; + expect(error.message).to.eq("Invalid contract address."); + } }); }); @@ -62,13 +61,13 @@ describe("Config: graphUrl", () => { }); it("should return the default graphUrl when no overrides are specified", () => { - const result = getConfig({}); + const result = getConfig({ id: 5 }); expect(result.graphUrl).to.equal("https://api.thegraph.com/subgraphs/name/hypercerts-admin/hypercerts-testnet"); }); it("should return the config specified by overrides", () => { const overrides: Partial = { - chainName: "testnet", + id: 5, graphUrl: "https://api.example.com", contractAddress: "0x1234567890123456789012345678901234567890", unsafeForceOverrideConfig: true, @@ -79,25 +78,37 @@ describe("Config: graphUrl", () => { it("should throw an error when the graph URL specified by overrides is invalid", () => { const overrides: Partial = { - chainName: "testnet", + id: 5, graphUrl: "incorrect-url", contractAddress: "0x1234567890123456789012345678901234567890", unsafeForceOverrideConfig: true, }; - expect(() => getConfig(overrides)).to.throw(ConfigurationError, "Invalid graph URL"); + try { + getConfig(overrides); + } catch (e) { + expect(e instanceof ConfigurationError).to.be.true; + const error = e as ConfigurationError; + expect(error.message).to.eq("Invalid graph URL"); + } }); it("should throw an error when the graph URL specified by overrides is missing", () => { const overrides: Partial = { - chainName: "testnet", + id: 5, contractAddress: "0x1234567890123456789012345678901234567890", unsafeForceOverrideConfig: true, }; - expect(() => getConfig(overrides)).to.throw( - UnsupportedChainError, - "attempted to override with chainId=5, but requires chainName, graphUrl, and contractAddress to be set", - ); + + try { + getConfig(overrides); + } catch (e) { + expect(e instanceof InvalidOrMissingError).to.be.true; + const error = e as InvalidOrMissingError; + expect(error.message).to.eq( + "attempted to override with chainId=5, but requires chainName, graphUrl, and contractAddress to be set", + ); + } }); }); @@ -110,14 +121,16 @@ describe("Config: nftStorageToken", () => { it("should return an empty object when no overrides or environment variables are specified", () => { sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); - const result = getConfig({}); + const result = getConfig({ id: 5 }); expect(result).to.deep.include({ + id: 5, nftStorageToken: "NFTSTOR", }); }); it("should return the nftStorageToken specified by overrides", () => { const overrides: Partial = { + id: 5, nftStorageToken: "NFTSTOR", }; const result = getConfig(overrides); @@ -128,7 +141,7 @@ describe("Config: nftStorageToken", () => { it("should return the nftStorageToken specified by the NFT_STORAGE_TOKEN environment variable", () => { sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); - const result = getConfig({}); + const result = getConfig({ id: 5 }); expect(result).to.deep.include({ nftStorageToken: "NFTSTOR", }); @@ -137,7 +150,7 @@ describe("Config: nftStorageToken", () => { it("should return the nftStorageToken specified by the NEXT_PUBLIC_NFT_STORAGE_TOKEN environment variable", () => { sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: "NFTSTOR" }); - const result = getConfig({}); + const result = getConfig({ id: 5 }); expect(result).to.deep.include({ nftStorageToken: "NFTSTOR", }); @@ -146,48 +159,42 @@ describe("Config: nftStorageToken", () => { it("should not throw an error when the nftStorageToken specified by overrides is invalid", () => { sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: null }); - const overrides: Partial = {}; + const overrides: Partial = { id: 5 }; expect(() => getConfig(overrides)).to.not.throw(); }); }); -describe("Config: getOperator", () => { +describe("Config: getPublicClient", () => { afterEach(() => { sinon.restore(); reloadEnv(); }); - it("should return a default provider when no overrides or environment variables are specified", () => { - const result = getConfig({}); - //TODO: hacky solution to compare providers - expect(JSON.stringify(result.operator)).to.equal(JSON.stringify(ethers.getDefaultProvider(DEFAULT_CHAIN_ID))); - }); it("should return the operator specified by overrides", () => { - const provider = ethers.getDefaultProvider(DEFAULT_CHAIN_ID); - const wallet = new ethers.Wallet("0x0123456789012345678901234567890123456789012345678901234567890123", provider); const overrides: Partial = { - operator: wallet, + id: 5, + publicClient, }; const result = getConfig(overrides); - expect(result.operator).to.equal(overrides.operator); + expect(result.publicClient).to.equal(overrides.publicClient); }); +}); - it("should return the operator specified by the PRIVATE_KEY environment variable", () => { - const PRIVATE_KEY = "0x0123456789012345678901234567890123456789012345678901234567890123"; - sinon.stub(process, "env").value({ PRIVATE_KEY }); +describe("Config: getWalletClient", () => { + afterEach(() => { + sinon.restore(); - const result = getConfig({}); - const provider = ethers.getDefaultProvider(DEFAULT_CHAIN_ID); - const wallet = new ethers.Wallet(PRIVATE_KEY, provider); - expect(JSON.stringify(result.operator)).to.equal(JSON.stringify(wallet)); + reloadEnv(); }); - it("should throw an error when the operator specified by overrides is invalid", () => { + it("should return the operator specified by overrides", () => { const overrides: Partial = { - operator: "invalid" as unknown as ethers.Signer, + id: 5, + walletClient, }; - expect(() => getConfig(overrides)).to.throw(InvalidOrMissingError, "Invalid operator."); + const result = getConfig(overrides); + expect(result.walletClient).to.equal(overrides.walletClient); }); }); @@ -201,7 +208,7 @@ describe("Config: web3StorageToken", () => { it("should return an empty object when no overrides or environment variables are specified", () => { const WEB3_STORAGE_TOKEN = "WEB3"; sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); - const result = getConfig({}); + const result = getConfig({ id: 5 }); expect(result).to.deep.include({ web3StorageToken: WEB3_STORAGE_TOKEN, }); @@ -209,6 +216,7 @@ describe("Config: web3StorageToken", () => { it("should return the web3StorageToken specified by overrides", () => { const overrides: Partial = { + id: 5, web3StorageToken: "WEB3STOR", }; const result = getConfig(overrides); @@ -220,7 +228,7 @@ describe("Config: web3StorageToken", () => { it("should return the web3StorageToken specified by the WEB3_STORAGE_TOKEN environment variable", () => { const WEB3_STORAGE_TOKEN = "WEB3"; sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); - const result = getConfig({}); + const result = getConfig({ id: 5 }); expect(result).to.deep.include({ web3StorageToken: WEB3_STORAGE_TOKEN, }); @@ -230,7 +238,7 @@ describe("Config: web3StorageToken", () => { const NEXT_PUBLIC_WEB3_STORAGE_TOKEN = "WEB3"; sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN }); - const result = getConfig({}); + const result = getConfig({ id: 5 }); expect(result).to.deep.include({ web3StorageToken: NEXT_PUBLIC_WEB3_STORAGE_TOKEN, }); @@ -238,7 +246,7 @@ describe("Config: web3StorageToken", () => { it("should not throw an error when the web3StorageToken specified by overrides is invalid", () => { sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN: null }); - const overrides: Partial = {}; + const overrides: Partial = { id: 5 }; expect(() => getConfig(overrides)).to.not.throw(); }); }); diff --git a/sdk/test/utils/errors.test.ts b/sdk/test/utils/errors.test.ts index affc4362..46f07a1b 100644 --- a/sdk/test/utils/errors.test.ts +++ b/sdk/test/utils/errors.test.ts @@ -1,7 +1,7 @@ import { expect } from "chai"; -import { FetchError, MalformedDataError, UnsupportedChainError } from "../../src/types/errors.js"; -import { handleError } from "../../src/utils/errors.js"; +import { FetchError, MalformedDataError, UnsupportedChainError } from "../../src/types/errors"; +import { handleError } from "../../src/utils/errors"; describe("Error handler test", () => { it("checking error handler", () => { diff --git a/sdk/test/validator.test.ts b/sdk/test/validator.test.ts index 6036f72d..a9e1c347 100644 --- a/sdk/test/validator.test.ts +++ b/sdk/test/validator.test.ts @@ -1,11 +1,11 @@ import { expect } from "chai"; -import { validateClaimData, validateMetaData } from "../src/index.js"; -import type { HypercertClaimdata, HypercertMetadata } from "../src/index.js"; +import { validateClaimData, validateMetaData } from "../src"; +import type { HypercertClaimdata, HypercertMetadata } from "../src"; import testData from "./res/mockMetadata.js"; -import { validateDuplicateEvaluationData, validateSimpleTextEvaluationData } from "../src/validator/index.js"; -import { getDuplicateEvaluationData, getSimpleTextEvaluationData } from "./helpers.js"; -import { DuplicateEvaluation, SimpleTextEvaluation } from "../src/types/evaluation.js"; +import { validateDuplicateEvaluationData, validateSimpleTextEvaluationData } from "../src/validator"; +import { getDuplicateEvaluationData, getSimpleTextEvaluationData } from "./helpers"; +import { DuplicateEvaluation, SimpleTextEvaluation } from "../src/types/evaluation"; describe("Validate claim test", () => { it("checking default metadata", () => { diff --git a/sdk/tsconfig.json b/sdk/tsconfig.json index 202a0aa0..2c208243 100644 --- a/sdk/tsconfig.json +++ b/sdk/tsconfig.json @@ -2,8 +2,8 @@ "compilerOptions": { "lib": ["ES6", "DOM", "ESNext"], "target": "ESNext", - "module": "ESNext", - "moduleResolution": "node", + "module": "NodeNext", + "moduleResolution": "NodeNext", "baseUrl": ".", "outDir": "dist", "allowJs": true, From edd342deffe8504d5fbe9b79db4932f2eaf6b3c8 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Fri, 3 Nov 2023 16:36:20 +0100 Subject: [PATCH 22/49] chore(build): fresh build --- graph/tests/.latest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graph/tests/.latest.json b/graph/tests/.latest.json index 97a0c116..472395b3 100644 --- a/graph/tests/.latest.json +++ b/graph/tests/.latest.json @@ -1,4 +1,4 @@ { "version": "0.6.0", - "timestamp": 1698759751327 + "timestamp": 1699025721005 } From fa5a676767a60ea69b8c8b8c9f35658b3a26808e Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Fri, 3 Nov 2023 16:39:19 +0100 Subject: [PATCH 23/49] chore(clean): remove contracts/contracts dir --- contracts/contracts/AllowlistMinter.sol | 70 --- contracts/contracts/HypercertMinter.sol | 229 --------- contracts/contracts/SemiFungible1155.sol | 433 ------------------ contracts/contracts/interfaces/IAllowlist.sol | 14 - .../contracts/interfaces/IHypercertToken.sol | 62 --- contracts/contracts/libs/Errors.sol | 15 - 6 files changed, 823 deletions(-) delete mode 100644 contracts/contracts/AllowlistMinter.sol delete mode 100644 contracts/contracts/HypercertMinter.sol delete mode 100644 contracts/contracts/SemiFungible1155.sol delete mode 100644 contracts/contracts/interfaces/IAllowlist.sol delete mode 100644 contracts/contracts/interfaces/IHypercertToken.sol delete mode 100644 contracts/contracts/libs/Errors.sol diff --git a/contracts/contracts/AllowlistMinter.sol b/contracts/contracts/AllowlistMinter.sol deleted file mode 100644 index 576b45ee..00000000 --- a/contracts/contracts/AllowlistMinter.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import { MerkleProofUpgradeable } from "oz-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol"; -import { IAllowlist } from "./interfaces/IAllowlist.sol"; - -import { Errors } from "./libs/Errors.sol"; - -/// @title Interface for hypercert token interactions -/// @author bitbeckers -/// @notice This interface declares the required functionality for a hypercert token -/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) -contract AllowlistMinter is IAllowlist { - event AllowlistCreated(uint256 tokenID, bytes32 root); - event LeafClaimed(uint256 tokenID, bytes32 leaf); - - mapping(uint256 => bytes32) internal merkleRoots; - mapping(uint256 => mapping(bytes32 => bool)) public hasBeenClaimed; - mapping(uint256 => uint256) internal maxUnits; - mapping(uint256 => uint256) internal minted; - - function isAllowedToClaim( - bytes32[] calldata proof, - uint256 claimID, - bytes32 leaf - ) external view returns (bool isAllowed) { - if (merkleRoots[claimID].length == 0) revert Errors.DoesNotExist(); - isAllowed = MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf); - } - - function _createAllowlist(uint256 claimID, bytes32 merkleRoot, uint256 units) internal { - if (merkleRoot == "" || units == 0) revert Errors.Invalid(); - if (merkleRoots[claimID] != "") revert Errors.DuplicateEntry(); - - merkleRoots[claimID] = merkleRoot; - maxUnits[claimID] = units; - emit AllowlistCreated(claimID, merkleRoot); - } - - function _processClaim(bytes32[] calldata proof, uint256 claimID, uint256 amount) internal { - if (merkleRoots[claimID].length == 0) revert Errors.DoesNotExist(); - - bytes32 leaf = _calculateLeaf(msg.sender, amount); - - if (hasBeenClaimed[claimID][leaf]) revert Errors.AlreadyClaimed(); - if ( - !MerkleProofUpgradeable.verifyCalldata(proof, merkleRoots[claimID], leaf) || - (minted[claimID] + amount) > maxUnits[claimID] - ) revert Errors.Invalid(); - hasBeenClaimed[claimID][leaf] = true; - - emit LeafClaimed(claimID, leaf); - } - - function _calculateLeaf(address account, uint256 amount) internal pure returns (bytes32 leaf) { - leaf = keccak256(bytes.concat(keccak256(abi.encode(account, amount)))); - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - * Assuming 30 available slots (slots cost space, cost gas) - * 1. merkleRoots - * 2. hasBeenClaimed - * 3. maxUnits - * 4. minted - */ - uint256[26] private __gap; -} diff --git a/contracts/contracts/HypercertMinter.sol b/contracts/contracts/HypercertMinter.sol deleted file mode 100644 index 917c02c5..00000000 --- a/contracts/contracts/HypercertMinter.sol +++ /dev/null @@ -1,229 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import { IHypercertToken } from "./interfaces/IHypercertToken.sol"; -import { SemiFungible1155 } from "./SemiFungible1155.sol"; -import { AllowlistMinter } from "./AllowlistMinter.sol"; -import { PausableUpgradeable } from "oz-upgradeable/security/PausableUpgradeable.sol"; - -import { Errors } from "./libs/Errors.sol"; - -/// @title Contract for managing hypercert claims and whitelists -/// @author bitbeckers -/// @notice Implementation of the HypercertTokenInterface using { SemiFungible1155 } as underlying token. -/// @notice This contract supports whitelisted minting via { AllowlistMinter }. -/// @dev Wrapper contract to expose and chain functions. -contract HypercertMinter is IHypercertToken, SemiFungible1155, AllowlistMinter, PausableUpgradeable { - // solhint-disable-next-line const-name-snakecase - string public constant name = "HypercertMinter"; - /// @dev from typeID to a transfer policy - mapping(uint256 => TransferRestrictions) internal typeRestrictions; - - /// INIT - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - function initialize() public virtual initializer { - __SemiFungible1155_init(); - __Pausable_init(); - } - - /// EXTERNAL - - /// @notice Mint a semi-fungible token for the impact claim referenced via `uri` - /// @dev see {IHypercertToken} - function mintClaim( - address account, - uint256 units, - string memory _uri, - TransferRestrictions restrictions - ) external override whenNotPaused { - // This enables us to release this restriction in the future - if (msg.sender != account) revert Errors.NotAllowed(); - uint256 claimID = _mintNewTypeWithToken(account, units, _uri); - typeRestrictions[claimID] = restrictions; - emit ClaimStored(claimID, _uri, units); - } - - /// @notice Mint semi-fungible tokens for the impact claim referenced via `uri` - /// @dev see {IHypercertToken} - function mintClaimWithFractions( - address account, - uint256 units, - uint256[] calldata fractions, - string memory _uri, - TransferRestrictions restrictions - ) external override whenNotPaused { - // This enables us to release this restriction in the future - if (msg.sender != account) revert Errors.NotAllowed(); - //Using sum to compare units and fractions (sanity check) - if (_getSum(fractions) != units) revert Errors.Invalid(); - - uint256 claimID = _mintNewTypeWithTokens(account, fractions, _uri); - typeRestrictions[claimID] = restrictions; - emit ClaimStored(claimID, _uri, units); - } - - /// @notice Mint a semi-fungible token representing a fraction of the claim - /// @dev Calls AllowlistMinter to verify `proof`. - /// @dev Mints the `amount` of units for the hypercert stored under `claimID` - function mintClaimFromAllowlist( - address account, - bytes32[] calldata proof, - uint256 claimID, - uint256 units - ) external whenNotPaused { - _processClaim(proof, claimID, units); - _mintToken(account, claimID, units); - } - - /// @notice Mint semi-fungible tokens representing a fraction of the claims in `claimIDs` - /// @dev Calls AllowlistMinter to verify `proofs`. - /// @dev Mints the `amount` of units for the hypercert stored under `claimIDs` - function batchMintClaimsFromAllowlists( - address account, - bytes32[][] calldata proofs, - uint256[] calldata claimIDs, - uint256[] calldata units - ) external whenNotPaused { - uint256 len = claimIDs.length; - for (uint256 i; i < len; ) { - _processClaim(proofs[i], claimIDs[i], units[i]); - unchecked { - ++i; - } - } - _batchMintTokens(account, claimIDs, units); - } - - /// @notice Register a claim and the whitelist for minting token(s) belonging to that claim - /// @dev Calls SemiFungible1155 to store the claim referenced in `uri` with amount of `units` - /// @dev Calls AllowlistMinter to store the `merkleRoot` as proof to authorize claims - function createAllowlist( - address account, - uint256 units, - bytes32 merkleRoot, - string memory _uri, - TransferRestrictions restrictions - ) external whenNotPaused { - uint256 claimID = _createTokenType(account, units, _uri); - _createAllowlist(claimID, merkleRoot, units); - typeRestrictions[claimID] = restrictions; - emit ClaimStored(claimID, _uri, units); - } - - /// @notice Split a claimtokens value into parts with summed value equal to the original - /// @dev see {IHypercertToken} - function splitFraction( - address _account, - uint256 _tokenID, - uint256[] calldata _newFractions - ) external whenNotPaused { - _splitTokenUnits(_account, _tokenID, _newFractions); - } - - /// @notice Merge the value of tokens belonging to the same claim - /// @dev see {IHypercertToken} - function mergeFractions(address _account, uint256[] calldata _fractionIDs) external whenNotPaused { - _mergeTokensUnits(_account, _fractionIDs); - } - - /// @notice Burn a claimtoken - /// @dev see {IHypercertToken} - function burnFraction(address _account, uint256 _tokenID) external whenNotPaused { - _burnToken(_account, _tokenID); - } - - /// @dev see {IHypercertToken} - function unitsOf(uint256 tokenID) external view override returns (uint256 units) { - units = _unitsOf(tokenID); - } - - /// @dev see {IHypercertToken} - function unitsOf(address account, uint256 tokenID) external view override returns (uint256 units) { - units = _unitsOf(account, tokenID); - } - - /// PAUSABLE - - function pause() external onlyOwner { - _pause(); - } - - function unpause() external onlyOwner { - _unpause(); - } - - /// METADATA - - /// @dev see { IHypercertMetadata} - function uri(uint256 tokenID) public view override(IHypercertToken, SemiFungible1155) returns (string memory _uri) { - _uri = SemiFungible1155.uri(tokenID); - } - - /// TRANSFER RESTRICTIONS - - function readTransferRestriction(uint256 tokenID) external view returns (string memory) { - TransferRestrictions temp = typeRestrictions[getBaseType(tokenID)]; - if (temp == TransferRestrictions.AllowAll) return "AllowAll"; - if (temp == TransferRestrictions.DisallowAll) return "DisallowAll"; - if (temp == TransferRestrictions.FromCreatorOnly) return "FromCreatorOnly"; - return ""; - } - - /// INTERNAL - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol } - function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { - // solhint-disable-previous-line no-empty-blocks - } - - function _beforeTokenTransfer( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual override { - super._beforeTokenTransfer(operator, from, to, ids, amounts, data); - - // By-pass transfer restrictions for minting and burning - if (from == address(0)) { - // Minting - return; - } else if (to == address(0)) { - // Burning - return; - } - - // Transfer case, where to and from are non-zero - uint256 len = ids.length; - for (uint256 i; i < len; ) { - uint256 typeID = getBaseType(ids[i]); - TransferRestrictions policy = typeRestrictions[typeID]; - if (policy == TransferRestrictions.DisallowAll) { - revert Errors.TransfersNotAllowed(); - } else if (policy == TransferRestrictions.FromCreatorOnly && from != creators[typeID]) { - revert Errors.TransfersNotAllowed(); - } - unchecked { - ++i; - } - } - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - * Assuming 30 available slots (slots cost space, cost gas) - * 1. typeRestrictions - */ - uint256[29] private __gap; -} diff --git a/contracts/contracts/SemiFungible1155.sol b/contracts/contracts/SemiFungible1155.sol deleted file mode 100644 index cd88714a..00000000 --- a/contracts/contracts/SemiFungible1155.sol +++ /dev/null @@ -1,433 +0,0 @@ -// SPDX-License-Identifier: MIT -// Used components of Enjin example implementation for mixed fungibility -// /~https://github.com/enjin/erc-1155/blob/master/contracts/ERC1155MixedFungibleMintable.sol -pragma solidity 0.8.16; - -import { ERC1155Upgradeable } from "oz-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; -import { ERC1155BurnableUpgradeable } from "oz-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol"; -import { ERC1155URIStorageUpgradeable } from "oz-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol"; -import { OwnableUpgradeable } from "oz-upgradeable/access/OwnableUpgradeable.sol"; -import { Initializable } from "oz-upgradeable/proxy/utils/Initializable.sol"; -import { UUPSUpgradeable } from "oz-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { Errors } from "./libs/Errors.sol"; - -/// @title Contract for minting semi-fungible EIP1155 tokens -/// @author bitbeckers -/// @notice Extends { Upgradeable1155 } token with semi-fungible properties and the concept of `units` -/// @dev Adds split bit strategy as described in [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155#non-fungible-tokens) -contract SemiFungible1155 is - Initializable, - ERC1155Upgradeable, - ERC1155BurnableUpgradeable, - ERC1155URIStorageUpgradeable, - OwnableUpgradeable, - UUPSUpgradeable -{ - /// @dev Counter used to generate next typeID. - uint256 internal typeCounter; - - /// @dev Bitmask used to expose only upper 128 bits of uint256 - uint256 internal constant TYPE_MASK = type(uint256).max << 128; - - /// @dev Bitmask used to expose only lower 128 bits of uint256 - uint256 internal constant NF_INDEX_MASK = type(uint256).max >> 128; - - uint256 internal constant FRACTION_LIMIT = 253; - - /// @dev Mapping of `tokenID` to address of `owner` - mapping(uint256 => address) internal owners; - - /// @dev Mapping of `tokenID` to address of `creator` - mapping(uint256 => address) internal creators; - - /// @dev Used to determine amount of `units` stored in token at `tokenID` - mapping(uint256 => uint256) internal tokenValues; - - /// @dev Used to find highest index of token belonging to token at `typeID` - mapping(uint256 => uint256) internal maxIndex; - - /// @dev Emitted on transfer of `value` between `fromTokenID` to `toTokenID` of the same `claimID` - event ValueTransfer(uint256 claimID, uint256 fromTokenID, uint256 toTokenID, uint256 value); - - /// @dev Emitted on transfer of `values` between `fromTokenIDs` to `toTokenIDs` of `claimIDs` - event BatchValueTransfer(uint256[] claimIDs, uint256[] fromTokenIDs, uint256[] toTokenIDs, uint256[] values); - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol } - // solhint-disable-next-line func-name-mixedcase - function __SemiFungible1155_init() public virtual onlyInitializing { - __ERC1155_init(""); - __ERC1155Burnable_init(); - __ERC1155URIStorage_init(); - __Ownable_init(); - __UUPSUpgradeable_init(); - } - - /// @dev Get index of fractional token at `_id` by returning lower 128 bit values - /// @dev Returns 0 if `_id` is a baseType - function getItemIndex(uint256 tokenID) internal pure returns (uint256) { - return tokenID & NF_INDEX_MASK; - } - - /// @dev Get base type ID for token at `_id` by returning upper 128 bit values - function getBaseType(uint256 tokenID) internal pure returns (uint256) { - return tokenID & TYPE_MASK; - } - - /// @dev Identify that token at `_id` is base type. - /// @dev Upper 128 bits identify base type ID, lower bits should be 0 - function isBaseType(uint256 tokenID) internal pure returns (bool) { - return (tokenID & TYPE_MASK == tokenID) && (tokenID & NF_INDEX_MASK == 0); - } - - /// @dev Identify that token at `_id` is fraction of a claim. - /// @dev Upper 128 bits identify base type ID, lower bits should be > 0 - function isTypedItem(uint256 tokenID) internal pure returns (bool) { - return (tokenID & TYPE_MASK != 0) && (tokenID & NF_INDEX_MASK != 0); - } - - /// READ - function ownerOf(uint256 tokenID) public view returns (address _owner) { - _owner = owners[tokenID]; - } - - /// @dev see {IHypercertToken} - function _unitsOf(uint256 tokenID) internal view returns (uint256 units) { - units = tokenValues[tokenID]; - } - - /// @dev see {IHypercertToken} - function _unitsOf(address account, uint256 tokenID) internal view returns (uint256 units) { - // Check if fraction token and accounts owns it - if (ownerOf(tokenID) == account) { - units = tokenValues[tokenID]; - } - } - - /// MUTATE - - /// @dev create token type ID based of token counter - - function _createTokenType(address _account, uint256 units, string memory _uri) internal returns (uint256 typeID) { - _notMaxType(typeCounter); - typeID = ++typeCounter << 128; - - creators[typeID] = _account; - tokenValues[typeID] = units; - - _setURI(typeID, _uri); - - //Event emitted for indexing purposes - emit TransferSingle(_account, address(0), address(0), typeID, 0); - } - - /// @dev Mint a new token type and the initial units - function _mintNewTypeWithToken( - address _account, - uint256 _units, - string memory _uri - ) internal returns (uint256 typeID) { - if (_units == 0) { - revert Errors.NotAllowed(); - } - typeID = _createTokenType(_account, _units, _uri); - - uint256 tokenID = typeID + ++maxIndex[typeID]; //1 based indexing, 0 holds type data - - tokenValues[tokenID] = _units; - - _mint(_account, tokenID, 1, ""); - emit ValueTransfer(typeID, 0, tokenID, _units); - } - - /// @dev Mint a new token type and the initial fractions - function _mintNewTypeWithTokens( - address _account, - uint256[] calldata _fractions, - string memory _uri - ) internal returns (uint256 typeID) { - typeID = _mintNewTypeWithToken(_account, _getSum(_fractions), _uri); - _splitTokenUnits(_account, typeID + maxIndex[typeID], _fractions); - } - - /// @dev Mint a new token for an existing type - function _mintToken(address _account, uint256 _typeID, uint256 _units) internal returns (uint256 tokenID) { - if (!isBaseType(_typeID)) revert Errors.NotAllowed(); - - _notMaxItem(maxIndex[_typeID]); - - unchecked { - tokenID = _typeID + ++maxIndex[_typeID]; //1 based indexing, 0 holds type data - } - - tokenValues[tokenID] = _units; - - _mint(_account, tokenID, 1, ""); - emit ValueTransfer(_typeID, 0, tokenID, _units); - } - - /// @dev Mint new tokens for existing types - /// @notice Enables batch claiming from multiple allowlists - function _batchMintTokens( - address _account, - uint256[] calldata _typeIDs, - uint256[] calldata _units - ) internal returns (uint256[] memory tokenIDs) { - uint256 len = _typeIDs.length; - - tokenIDs = new uint256[](len); - uint256[] memory amounts = new uint256[](len); - uint256[] memory zeroes = new uint256[](len); - - for (uint256 i; i < len; ) { - uint256 _typeID = _typeIDs[i]; - if (!isBaseType(_typeID)) revert Errors.NotAllowed(); - _notMaxItem(maxIndex[_typeID]); - - unchecked { - uint256 tokenID = _typeID + ++maxIndex[_typeID]; //1 based indexing, 0 holds type data - tokenValues[tokenID] = _units[i]; - tokenIDs[i] = tokenID; - amounts[i] = 1; - ++i; - } - } - - _mintBatch(_account, tokenIDs, amounts, ""); - emit BatchValueTransfer(_typeIDs, zeroes, tokenIDs, _units); - } - - /// @dev Split the units of `_tokenID` owned by `account` across `_values` - /// @dev `_values` must sum to total `units` held at `_tokenID` - function _splitTokenUnits(address _account, uint256 _tokenID, uint256[] calldata _values) internal { - if (_values.length > FRACTION_LIMIT || _values.length < 2) revert Errors.ArraySize(); - if (tokenValues[_tokenID] != _getSum(_values)) revert Errors.NotAllowed(); - - // Current token - uint256 _typeID = getBaseType(_tokenID); - uint256 valueLeft = tokenValues[_tokenID]; - - // Prepare batch processing, we want to skip the first entry - uint256 len = _values.length - 1; - - uint256[] memory typeIDs = new uint256[](len); - uint256[] memory fromIDs = new uint256[](len); - uint256[] memory toIDs = new uint256[](len); - uint256[] memory amounts = new uint256[](len); - uint256[] memory values = new uint256[](len); - - { - uint256[] memory _valuesCache = _values; - uint256 swapValue = _valuesCache[len]; - _valuesCache[len] = _valuesCache[0]; - _valuesCache[0] = swapValue; - - for (uint256 i; i < len; ) { - _notMaxItem(maxIndex[_typeID]); - - typeIDs[i] = _typeID; - fromIDs[i] = _tokenID; - toIDs[i] = _typeID + ++maxIndex[_typeID]; - amounts[i] = 1; - values[i] = _valuesCache[i]; - - unchecked { - ++i; - } - } - } - - _beforeUnitTransfer(_msgSender(), _account, fromIDs, toIDs, values, ""); - - for (uint256 i; i < len; ) { - valueLeft -= values[i]; - - tokenValues[toIDs[i]] = values[i]; - - unchecked { - ++i; - } - } - - tokenValues[_tokenID] = valueLeft; - - _mintBatch(_account, toIDs, amounts, ""); - - emit BatchValueTransfer(typeIDs, fromIDs, toIDs, values); - } - - /// @dev Merge the units of `_fractionIDs`. - /// @dev Base type of `_fractionIDs` must be identical for all tokens. - function _mergeTokensUnits(address _account, uint256[] memory _fractionIDs) internal { - if (_fractionIDs.length > FRACTION_LIMIT || _fractionIDs.length < 2) { - revert Errors.ArraySize(); - } - uint256 len = _fractionIDs.length - 1; - - uint256 target = _fractionIDs[len]; - - uint256 _totalValue; - uint256[] memory fromIDs = new uint256[](len); - uint256[] memory toIDs = new uint256[](len); - uint256[] memory values = new uint256[](len); - uint256[] memory amounts = new uint256[](len); - - { - for (uint256 i; i < len; ) { - uint256 _fractionID = _fractionIDs[i]; - fromIDs[i] = _fractionID; - toIDs[i] = target; - amounts[i] = 1; - values[i] = tokenValues[_fractionID]; - - unchecked { - ++i; - } - } - } - - _beforeUnitTransfer(_msgSender(), _account, fromIDs, toIDs, values, ""); - - for (uint256 i; i < len; ) { - _totalValue += values[i]; - - delete tokenValues[fromIDs[i]]; - unchecked { - ++i; - } - } - - tokenValues[target] += _totalValue; - - _burnBatch(_account, fromIDs, amounts); - } - - /// @dev Burn the token at `_tokenID` owned by `_account` - /// @dev Not allowed to burn base type. - /// @dev `_tokenID` must hold all value declared at base type - function _burnToken(address _account, uint256 _tokenID) internal { - if (_account != _msgSender() && !isApprovedForAll(_account, _msgSender())) revert Errors.NotApprovedOrOwner(); - - uint256 value = tokenValues[_tokenID]; - - delete tokenValues[_tokenID]; - - _burn(_account, _tokenID, 1); - emit ValueTransfer(getBaseType(_tokenID), _tokenID, 0, value); - } - - /// TRANSFERS - - // The following functions are overrides required by Solidity. - function _afterTokenTransfer( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual override { - super._afterTokenTransfer(operator, from, to, ids, amounts, data); - - uint256 len = ids.length; - - for (uint256 i; i < len; ) { - owners[ids[i]] = to; - unchecked { - ++i; - } - } - } - - function _beforeUnitTransfer( - address operator, - address from, - uint256[] memory fromIDs, - uint256[] memory toIDs, - uint256[] memory values, - bytes memory data - ) internal virtual { - uint256 len = fromIDs.length; - - for (uint256 i; i < len; ) { - uint256 _from = fromIDs[i]; - uint256 _to = toIDs[i]; - - if (isBaseType(_from)) revert Errors.NotAllowed(); - if (getBaseType(_from) != getBaseType(_to)) revert Errors.TypeMismatch(); - if (from != _msgSender() && !isApprovedForAll(from, _msgSender())) revert Errors.NotApprovedOrOwner(); - unchecked { - ++i; - } - } - } - - /// METADATA - - /// @dev see { openzeppelin-contracts-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol } - /// @dev Always returns the URI for the basetype so that it's managed in one place. - function uri( - uint256 tokenID - ) public view virtual override(ERC1155Upgradeable, ERC1155URIStorageUpgradeable) returns (string memory _uri) { - // All tokens share the same metadata at the moment - _uri = ERC1155URIStorageUpgradeable.uri(getBaseType(tokenID)); - } - - /// UTILS - - /** - * @dev Check if value is below max item index - */ - function _notMaxItem(uint256 tokenID) private pure { - uint128 _count = uint128(tokenID); - ++_count; - } - - /** - * @dev Check if value is below max type index - */ - function _notMaxType(uint256 tokenID) private pure { - uint128 _count = uint128(tokenID >> 128); - ++_count; - } - - /** - * @dev calculate the sum of the elements of an array - */ - function _getSum(uint256[] memory array) internal pure returns (uint256 sum) { - uint256 len = array.length; - for (uint256 i; i < len; ) { - if (array[i] == 0) revert Errors.NotAllowed(); - sum += array[i]; - unchecked { - ++i; - } - } - } - - function _getSingletonArray(uint256 element) private pure returns (uint256[] memory) { - uint256[] memory array = new uint256[](1); - array[0] = element; - - return array; - } - - // UUPS PROXY - - /// @dev see { openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol } - function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { - // solhint-disable-previous-line no-empty-blocks - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - * Assuming 30 available slots (slots cost space, cost gas) - * 1. typeCounter - * 2. owners - * 3. creators - * 4. tokenValues - * 5. maxIndex - */ - uint256[25] private __gap; -} diff --git a/contracts/contracts/interfaces/IAllowlist.sol b/contracts/contracts/interfaces/IAllowlist.sol deleted file mode 100644 index fe4a9ec4..00000000 --- a/contracts/contracts/interfaces/IAllowlist.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -/// @title Interface for allowlist -/// @author bitbeckers -/// @notice This interface declares the required functionality for a hypercert token -/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) -interface IAllowlist { - function isAllowedToClaim( - bytes32[] calldata proof, - uint256 tokenID, - bytes32 leaf - ) external view returns (bool isAllowed); -} diff --git a/contracts/contracts/interfaces/IHypercertToken.sol b/contracts/contracts/interfaces/IHypercertToken.sol deleted file mode 100644 index 1ed1e34e..00000000 --- a/contracts/contracts/interfaces/IHypercertToken.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -/// @title Interface for hypercert token interactions -/// @author bitbeckers -/// @notice This interface declares the required functionality for a hypercert token -/// @notice This interface does not specify the underlying token type (e.g. 721 or 1155) -interface IHypercertToken { - /** - * AllowAll = Unrestricted - * DisallowAll = Transfers disabled after minting - * FromCreatorOnly = Only the original creator can transfer - */ - /// @dev Transfer restriction policies on hypercerts - enum TransferRestrictions { - AllowAll, - DisallowAll, - FromCreatorOnly - } - - /// @dev Emitted when token with tokenID `claimID` is stored, with external data reference via `uri`. - event ClaimStored(uint256 indexed claimID, string uri, uint256 totalUnits); - - /// @dev Function called to store a claim referenced via `uri` with a maximum number of fractions `units`. - function mintClaim(address account, uint256 units, string memory uri, TransferRestrictions restrictions) external; - - /// @dev Function called to store a claim referenced via `uri` with a set of `fractions`. - /// @dev Fractions are internally summed to total units. - function mintClaimWithFractions( - address account, - uint256 units, - uint256[] memory fractions, - string memory uri, - TransferRestrictions restrictions - ) external; - - /// @dev Function called to split `tokenID` owned by `account` into units declared in `values`. - /// @notice The sum of `values` must equal the current value of `_tokenID`. - function splitFraction(address account, uint256 tokenID, uint256[] memory _values) external; - - /// @dev Function called to merge tokens within `tokenIDs`. - /// @notice Tokens that have been merged are burned. - function mergeFractions(address account, uint256[] memory tokenIDs) external; - - /// @dev Function to burn the token at `tokenID` for `account` - /// @notice Operator must be allowed by `creator` and the token must represent the total amount of available units. - function burnFraction(address account, uint256 tokenID) external; - - /// @dev Returns the `units` held by a (fractional) token at `claimID` - /// @dev If `tokenID` is a base type, the total amount of `units` for the claim is returned. - /// @dev If `tokenID` is a fractional token, the `units` held by the token is returned - function unitsOf(uint256 tokenID) external view returns (uint256 units); - - /// @dev Returns the `units` held by `account` of a (fractional) token at `claimID` - /// @dev If `tokenID` is a base type, the total amount of `units` held by `account` for the claim is returned. - /// @dev If `tokenID` is a fractional token, the `units` held by `account` the token is returned - function unitsOf(address account, uint256 tokenID) external view returns (uint256 units); - - /// @dev Returns the `uri` for metadata of the claim represented by `tokenID` - /// @dev Metadata must conform to { Hypercert Metadata } spec (based on ERC1155 Metadata) - function uri(uint256 tokenID) external view returns (string memory metadata); -} diff --git a/contracts/contracts/libs/Errors.sol b/contracts/contracts/libs/Errors.sol deleted file mode 100644 index e19d6b5c..00000000 --- a/contracts/contracts/libs/Errors.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -/// @author bitbeckers -library Errors { - error AlreadyClaimed(); - error ArraySize(); - error DoesNotExist(); - error DuplicateEntry(); - error Invalid(); - error NotAllowed(); - error NotApprovedOrOwner(); - error TransfersNotAllowed(); - error TypeMismatch(); -} From 7e312f1bc135ad0cce385f212af0946adc79de13 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Fri, 3 Nov 2023 16:56:32 +0100 Subject: [PATCH 24/49] fix(gha): non-next env var in gha for sdk --- .github/workflows/ci-default.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci-default.yml b/.github/workflows/ci-default.yml index a7242d72..d4e7b8a6 100644 --- a/.github/workflows/ci-default.yml +++ b/.github/workflows/ci-default.yml @@ -13,6 +13,8 @@ env: NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }} NEXT_PUBLIC_SUPABASE_TABLE: ${{ vars.NEXT_PUBLIC_SUPABASE_TABLE }} NEXT_PUBLIC_WALLETCONNECT_ID: ${{ secrets.NEXT_PUBLIC_WALLETCONNECT_ID }} + WEB3_STORAGE_TOKEN: ${{ secrets.NEXT_PUBLIC_NFT_STORAGE_TOKEN }} + NFT_STORAGE_TOKEN: ${{ secrets.NEXT_PUBLIC_NFT_STORAGE_TOKEN }} DOCKER_PLATFORM: "amd64" # Trigger the workflow when: From 23a8497f135ed4215c1a6cc0625460ffdcc8e230 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Fri, 3 Nov 2023 17:27:03 +0100 Subject: [PATCH 25/49] chore(run): kick From c97ae3c116403a244745d18dfbd34d4b85fb3dfd Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Fri, 3 Nov 2023 17:57:33 +0100 Subject: [PATCH 26/49] fix(jest): forceExit hanging async call --- sdk/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/package.json b/sdk/package.json index 2988fe18..eb835bdb 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -106,7 +106,7 @@ "clean": "rm -rf ./dist", "prebuild": "pnpm clean", "prepack": "pnpm build", - "test": "NODE_OPTIONS=\"--no-warnings --experimental-vm-modules\" jest", + "test": "NODE_OPTIONS=\"--no-warnings --experimental-vm-modules\" jest --detectOpenHandles --forceExit", "types:json": "pnpm json2ts -i './src/resources/schema/' -o 'src/types' --cwd './src/resources/schema'" } } From 96970dc00acce440a3d691c2ed9f11f66b42b951 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Sat, 4 Nov 2023 21:47:33 +0100 Subject: [PATCH 27/49] chore(build): fresh run for sanity --- .lintstagedrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.lintstagedrc b/.lintstagedrc index e6715067..ad678de5 100644 --- a/.lintstagedrc +++ b/.lintstagedrc @@ -1,6 +1,6 @@ { "**/*.{js,jsx,ts,tsx,sol}": [ - "eslint --ignore-path .gitignore --ignore-pattern sdk/ --ignore-pattern graph/generated/ --ignore-pattern graph/", + "eslint --ignore-path .gitignore --ignore-path .lintstagedignore", "prettier --write" ], "**/*.{md,json}": ["prettier --write"] From 01f62de1482f860e504f9de5221d50c9d0bf2d62 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Sat, 4 Nov 2023 22:03:07 +0100 Subject: [PATCH 28/49] fix(lint): ignore **/abi instead of **/src/abi --- contracts/.prettierignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/.prettierignore b/contracts/.prettierignore index 1a71d38f..87bdd5b4 100644 --- a/contracts/.prettierignore +++ b/contracts/.prettierignore @@ -17,7 +17,7 @@ **/deployments **/.openzeppelin **/docs -**/src/abi/ +**/abi # files *.env From 90d61115f3900feb9736077596881d5bef5d3a56 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Sat, 4 Nov 2023 23:56:52 +0100 Subject: [PATCH 29/49] feat(fe): integrate in FE and SDK 0.9.1 --- frontend/hooks/burnFraction.ts | 14 +- frontend/hooks/hypercerts-client.ts | 54 +- frontend/hooks/mergeFractionUnits.ts | 13 +- frontend/hooks/mintClaim.ts | 16 +- frontend/hooks/mintClaimAllowlist.ts | 14 +- frontend/hooks/mintFractionAllowlist.ts | 19 +- frontend/hooks/mintFractionAllowlistBatch.ts | 18 +- frontend/hooks/splitClaimUnits.ts | 15 +- frontend/package.json | 10 +- pnpm-lock.yaml | 668 +++++++++---------- sdk/package.json | 2 +- sdk/src/client.ts | 12 +- sdk/test/client/allowlist.minting.test.ts | 4 +- sdk/test/client/burn.test.ts | 63 +- sdk/test/client/minting.test.ts | 9 +- sdk/test/client/split.merge.test.ts | 41 +- sdk/test/evaluations/evaluator.test.ts | 4 +- sdk/test/helpers.ts | 4 +- 18 files changed, 453 insertions(+), 527 deletions(-) diff --git a/frontend/hooks/burnFraction.ts b/frontend/hooks/burnFraction.ts index 2c28bf11..3bff9e33 100644 --- a/frontend/hooks/burnFraction.ts +++ b/frontend/hooks/burnFraction.ts @@ -13,6 +13,7 @@ export const useBurnFraction = ({ const [txPending, setTxPending] = useState(false); const { client, isLoading } = useHypercertClient(); + const publicClient = client.config.publicClient; const stepDescriptions = { preparing: "Preparing to burn fraction", @@ -31,19 +32,22 @@ export const useBurnFraction = ({ setStep("burning"); - const tx = await client.burnClaimFraction(claimId); + const hash = await client.burnClaimFraction(claimId); - setStep("waiting"); + const receipt = await publicClient?.waitForTransactionReceipt({ + confirmations: 3, + hash: hash, + }); - const receipt = await tx.wait(5); + setStep("waiting"); - if (receipt.status === 0) { + if (receipt?.status === "reverted") { toast("Burning failed", { type: "error", }); console.error(receipt); } - if (receipt.status === 1) { + if (receipt?.status === "success") { toast(burnInteractionLabels.toastSuccess(receipt.transactionHash), { type: "success", }); diff --git a/frontend/hooks/hypercerts-client.ts b/frontend/hooks/hypercerts-client.ts index f616ab5c..5d1fba60 100644 --- a/frontend/hooks/hypercerts-client.ts +++ b/frontend/hooks/hypercerts-client.ts @@ -1,29 +1,23 @@ -import React, { useEffect, useMemo } from "react"; +import React, { useEffect } from "react"; import { DEFAULT_CHAIN_ID, NFT_STORAGE_TOKEN, WEB3_STORAGE_TOKEN, - OVERRIDE_CHAIN_NAME, OVERRIDE_GRAPH_URL, CONTRACT_ADDRESS, UNSAFE_FORCE_OVERRIDE_CONFIG, } from "../lib/config"; import { HypercertClient, HypercertClientConfig } from "@hypercerts-org/sdk"; -import { providers } from "ethers"; -import { type WalletClient, useWalletClient, useNetwork } from "wagmi"; +import { useWalletClient, useNetwork } from "wagmi"; const clientConfig: Partial = { - chainId: DEFAULT_CHAIN_ID, + id: DEFAULT_CHAIN_ID, nftStorageToken: NFT_STORAGE_TOKEN, web3StorageToken: WEB3_STORAGE_TOKEN, }; function loadOverridingConfig(clientConfig: Partial) { - if (OVERRIDE_CHAIN_NAME) { - clientConfig.chainName = OVERRIDE_CHAIN_NAME; - } - if (OVERRIDE_GRAPH_URL) { clientConfig.graphUrl = OVERRIDE_GRAPH_URL; } @@ -35,47 +29,35 @@ function loadOverridingConfig(clientConfig: Partial) { if (UNSAFE_FORCE_OVERRIDE_CONFIG) { clientConfig.unsafeForceOverrideConfig = UNSAFE_FORCE_OVERRIDE_CONFIG; } + + return clientConfig; } + loadOverridingConfig(clientConfig); const defaultClient = new HypercertClient(clientConfig); -const walletClientToSigner = (walletClient: WalletClient) => { - const { account, chain, transport } = walletClient; - const network = { - chainId: chain.id, - name: chain.name, - ensAddress: chain.contracts?.ensRegistry?.address, - }; - const provider = new providers.Web3Provider(transport, network); - const signer = provider.getSigner(account.address); - return signer; -}; - -const useEthersSigner = ({ chainId }: { chainId?: number } = {}) => { - const { data: walletClient } = useWalletClient({ chainId }); - return useMemo( - () => (walletClient ? walletClientToSigner(walletClient) : undefined), - [walletClient], - ); -}; - export const useHypercertClient = () => { const { chain } = useNetwork(); - const signer = useEthersSigner({ chainId: chain?.id }); const [client, setClient] = React.useState(defaultClient); const [isLoading, setIsLoading] = React.useState(false); + const { + data: walletClient, + isError, + isLoading: walletClientLoading, + } = useWalletClient(); + useEffect(() => { - if (chain?.id && signer) { + if (chain?.id && !walletClientLoading && !isError && walletClient) { setIsLoading(true); - const config = { - chainId: chain.id, - operator: signer, + let config: Partial = { + id: chain.id, + walletClient, }; - loadOverridingConfig(config); + config = loadOverridingConfig(config); try { const client = new HypercertClient(config); setClient(client); @@ -85,7 +67,7 @@ export const useHypercertClient = () => { } setIsLoading(false); - }, [chain?.id, signer]); + }, [chain?.id, walletClient, walletClientLoading]); return { client, isLoading }; }; diff --git a/frontend/hooks/mergeFractionUnits.ts b/frontend/hooks/mergeFractionUnits.ts index 2ebf4b8a..e984961f 100644 --- a/frontend/hooks/mergeFractionUnits.ts +++ b/frontend/hooks/mergeFractionUnits.ts @@ -13,6 +13,7 @@ export const useMergeFractionUnits = ({ const [txPending, setTxPending] = useState(false); const { client, isLoading } = useHypercertClient(); + const publicClient = client.config.publicClient; const stepDescriptions = { preparing: "Preparing to merge fraction values", @@ -29,17 +30,21 @@ export const useMergeFractionUnits = ({ try { setTxPending(true); - const tx = await client.mergeClaimUnits(ids); + const hash = await client.mergeFractionUnits(ids); + + const receipt = await publicClient?.waitForTransactionReceipt({ + confirmations: 3, + hash: hash, + }); setStep("waiting"); - const receipt = await tx.wait(5); - if (receipt.status === 0) { + if (receipt?.status === "reverted") { toast("Merging failed", { type: "error", }); console.error(receipt); } - if (receipt.status === 1) { + if (receipt?.status === "success") { toast(mintInteractionLabels.toastSuccess, { type: "success" }); setStep("complete"); diff --git a/frontend/hooks/mintClaim.ts b/frontend/hooks/mintClaim.ts index 4b152f5d..55abc6a1 100644 --- a/frontend/hooks/mintClaim.ts +++ b/frontend/hooks/mintClaim.ts @@ -10,6 +10,7 @@ export const useMintClaim = ({ onComplete }: { onComplete?: () => void }) => { const [txPending, setTxPending] = useState(false); const { client, isLoading } = useHypercertClient(); + const publicClient = client.config.publicClient; const stepDescriptions = { preparing: "Preparing to mint hypercert", @@ -29,21 +30,26 @@ export const useMintClaim = ({ onComplete }: { onComplete?: () => void }) => { try { setTxPending(true); - const tx = await client.mintClaim( + const hash = await client.mintClaim( metaData, - units, + BigInt(units), TransferRestrictions.FromCreatorOnly, ); + + const receipt = await publicClient?.waitForTransactionReceipt({ + confirmations: 3, + hash: hash, + }); + setStep("waiting"); - const receipt = await tx.wait(5); - if (receipt.status === 0) { + if (receipt?.status === "reverted") { toast("Minting failed", { type: "error", }); console.error(receipt); } - if (receipt.status === 1) { + if (receipt?.status === "success") { toast(mintInteractionLabels.toastSuccess, { type: "success" }); setStep("complete"); diff --git a/frontend/hooks/mintClaimAllowlist.ts b/frontend/hooks/mintClaimAllowlist.ts index 45debc0b..18273244 100644 --- a/frontend/hooks/mintClaimAllowlist.ts +++ b/frontend/hooks/mintClaimAllowlist.ts @@ -23,6 +23,7 @@ export const useMintClaimAllowlist = ({ const [txPending, setTxPending] = useState(false); const { client, isLoading } = useHypercertClient(); + const publicClient = client.config.publicClient; const stepDescriptions = { validateAllowlist: "Validating allowlist", @@ -121,22 +122,27 @@ export const useMintClaimAllowlist = ({ setStep("preparing"); setTxPending(true); - const tx = await client.createAllowlist( + const hash = await client.createAllowlist( _allowlist, metaData, _totalSupply, TransferRestrictions.FromCreatorOnly, ); + + const receipt = await publicClient?.waitForTransactionReceipt({ + confirmations: 3, + hash: hash, + }); + setStep("writing"); - const receipt = await tx.wait(5); - if (receipt.status === 0) { + if (receipt?.status === "reverted") { toast("Minting failed", { type: "error", }); console.error(receipt); } - if (receipt.status === 1) { + if (receipt?.status === "success") { toast(mintInteractionLabels.toastSuccess, { type: "success" }); setStep("complete"); diff --git a/frontend/hooks/mintFractionAllowlist.ts b/frontend/hooks/mintFractionAllowlist.ts index 09cd0ff5..822cba42 100644 --- a/frontend/hooks/mintFractionAllowlist.ts +++ b/frontend/hooks/mintFractionAllowlist.ts @@ -15,6 +15,8 @@ export const useMintFractionAllowlist = ({ const [txPending, setTxPending] = useState(false); const { client, isLoading } = useHypercertClient(); + const publicClient = client.config.publicClient; + const { setStep, showModal, hideModal } = useContractModal(); const stepDescriptions = { @@ -29,27 +31,32 @@ export const useMintFractionAllowlist = ({ const initializeWrite = async ( claimID: bigint, units: bigint, - proof: string[], + proof: `0x${string}`[], ) => { setStep("minting"); try { setTxPending(true); - const tx = await client.mintClaimFractionFromAllowlist( + const hash = await client.mintClaimFractionFromAllowlist( claimID, units, proof, ); + + const receipt = await publicClient?.waitForTransactionReceipt({ + confirmations: 3, + hash: hash, + }); + setStep("waiting"); - const receipt = await tx.wait(5); - if (receipt.status === 0) { + if (receipt?.status === "reverted") { toast("Minting failed", { type: "error", }); console.error(receipt); } - if (receipt.status === 1) { + if (receipt?.status === "success") { toast(mintInteractionLabels.toastSuccess, { type: "success" }); setStep("complete"); @@ -67,7 +74,7 @@ export const useMintFractionAllowlist = ({ }; return { - write: async (proof: string[], claimId: bigint, units: bigint) => { + write: async (proof: `0x${string}`[], claimId: bigint, units: bigint) => { showModal({ stepDescriptions }); setStep("initial"); await initializeWrite(claimId, units, proof); diff --git a/frontend/hooks/mintFractionAllowlistBatch.ts b/frontend/hooks/mintFractionAllowlistBatch.ts index e1c65c71..97c5b6f3 100644 --- a/frontend/hooks/mintFractionAllowlistBatch.ts +++ b/frontend/hooks/mintFractionAllowlistBatch.ts @@ -27,6 +27,8 @@ export const useMintFractionAllowlistBatch = ({ const { data: claimIds } = useGetAllEligibility(address ?? "", chain?.id); const parseError = useParseBlockchainError(); + const publicClient = client.config.publicClient; + const stepDescriptions = { initial: "Initializing interaction", proofs: "Getting and verifying proofs", @@ -56,7 +58,9 @@ export const useMintFractionAllowlistBatch = ({ const verified: ClaimProof[] = results.flat().filter((x) => x); const unique = _.uniqWith(verified, _.isEqual); - const claimIDs = unique.map((claimProof) => claimProof.claimIDContract); + const claimIDs = unique.map((claimProof) => + BigInt(claimProof.claimIDContract), + ); const units = unique.map((claimProof) => BigInt(claimProof.units)); const proofs = unique.map((claimProof) => claimProof.proof as HexString[]); @@ -69,21 +73,25 @@ export const useMintFractionAllowlistBatch = ({ try { setTxPending(true); - const tx = await client.batchMintClaimFractionsFromAllowlists( + const hash = await client.batchMintClaimFractionsFromAllowlists( claimIDs, units, proofs, ); + + const receipt = await publicClient?.waitForTransactionReceipt({ + confirmations: 3, + hash: hash, + }); setStep("waiting"); - const receipt = await tx.wait(5); - if (receipt.status === 0) { + if (receipt?.status === "reverted") { toast("Minting failed", { type: "error", }); console.error(receipt); } - if (receipt.status === 1) { + if (receipt?.status === "success") { toast(mintInteractionLabels.toastSuccess, { type: "success" }); setStep("complete"); diff --git a/frontend/hooks/splitClaimUnits.ts b/frontend/hooks/splitClaimUnits.ts index 47cd4859..640ad196 100644 --- a/frontend/hooks/splitClaimUnits.ts +++ b/frontend/hooks/splitClaimUnits.ts @@ -24,22 +24,29 @@ export const useSplitFractionUnits = ({ const { setStep, showModal, hideModal } = useContractModal(); const parseError = useParseBlockchainError(); + const publicClient = client.config.publicClient; + const initializeWrite = async (id: bigint, fractions: bigint[]) => { setStep("splitting"); try { setTxPending(true); - const tx = await client.splitClaimUnits(id, fractions); + const hash = await client.splitFractionUnits(id, fractions); + + const receipt = await publicClient?.waitForTransactionReceipt({ + confirmations: 3, + hash: hash, + }); + setStep("waiting"); - const receipt = await tx.wait(5); - if (receipt.status === 0) { + if (receipt?.status === "reverted") { toast("Splitting failed", { type: "error", }); console.error(receipt); } - if (receipt.status === 1) { + if (receipt?.status === "success") { toast(mintInteractionLabels.toastSuccess, { type: "success" }); setStep("complete"); diff --git a/frontend/package.json b/frontend/package.json index c9d96480..b6113d6e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,9 +23,9 @@ "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", "@graphprotocol/client-cli": "^2.2.16", - "@hypercerts-org/contracts": "0.8.11", + "@hypercerts-org/contracts": "0.9.0", "@hypercerts-org/observabletreemap": "workspace: *", - "@hypercerts-org/sdk": "0.8.16", + "@hypercerts-org/sdk": "0.9.0-viem", "@mui/icons-material": "^5.11.9", "@mui/material": "^5.11.2", "@mui/x-date-pickers": "^5.0.12", @@ -34,7 +34,7 @@ "@openzeppelin/merkle-tree": "^1.0.2", "@plasmicapp/host": "^1.0.171", "@plasmicapp/loader-nextjs": "^1.0.284", - "@rainbow-me/rainbowkit": "1.0.8", + "@rainbow-me/rainbowkit": "1.2.0", "@sentry/nextjs": "^7.73.0", "@sentry/utils": "^7.73.0", "@supabase/supabase-js": "^2.1.2", @@ -66,8 +66,8 @@ "react-toastify": "^9.1.1", "react-use": "^17.4.0", "serve": "^14.0.1", - "viem": "1.5.3", - "wagmi": "1.3.9", + "viem": "1.18.4", + "wagmi": "1.4.5", "yup": "^0.32.11" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d1da78df..30fd5c5f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -295,7 +295,7 @@ importers: version: 3.8.6(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) '@celo/rainbowkit-celo': specifier: ^1.1.0 - version: 1.1.0(@rainbow-me/rainbowkit@1.0.8)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(wagmi@1.3.9)(zod@3.22.4) + version: 1.1.0(@rainbow-me/rainbowkit@1.2.0)(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(wagmi@1.4.5)(zod@3.22.4) '@emotion/react': specifier: ^11.10.5 version: 11.11.1(@types/react@18.2.33)(react@18.2.0) @@ -306,14 +306,14 @@ importers: specifier: ^2.2.16 version: 2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) '@hypercerts-org/contracts': - specifier: 0.8.11 - version: 0.8.11 + specifier: 0.9.0 + version: 0.9.0(typescript@5.1.6) '@hypercerts-org/observabletreemap': specifier: 'workspace: *' version: link:../vendor/observabletreemap '@hypercerts-org/sdk': - specifier: 0.8.16 - version: 0.8.16(@envelop/core@3.0.6)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3) + specifier: 0.9.0-viem + version: 0.9.0-viem(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) '@mui/icons-material': specifier: ^5.11.9 version: 5.14.15(@mui/material@5.14.15)(@types/react@18.2.33)(react@18.2.0) @@ -339,8 +339,8 @@ importers: specifier: ^1.0.284 version: 1.0.333(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) '@rainbow-me/rainbowkit': - specifier: 1.0.8 - version: 1.0.8(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9) + specifier: 1.2.0 + version: 1.2.0(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(viem@1.18.4)(wagmi@1.4.5) '@sentry/nextjs': specifier: ^7.73.0 version: 7.75.1(next@13.5.6)(react@18.2.0)(webpack@5.89.0) @@ -435,11 +435,11 @@ importers: specifier: ^14.0.1 version: 14.2.1 viem: - specifier: 1.5.3 - version: 1.5.3(typescript@5.1.6)(zod@3.22.4) + specifier: 1.18.4 + version: 1.18.4(typescript@5.1.6)(zod@3.22.4) wagmi: - specifier: 1.3.9 - version: 1.3.9(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + specifier: 1.4.5 + version: 1.4.5(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4) yup: specifier: ^0.32.11 version: 0.32.11 @@ -598,8 +598,8 @@ importers: specifier: ^7.1.1 version: 7.1.1(node-fetch@3.3.2) viem: - specifier: 1.5.3 - version: 1.5.3(typescript@5.1.6)(zod@3.22.4) + specifier: ^1.18.4 + version: 1.18.4(typescript@5.1.6)(zod@3.22.4) web3.storage: specifier: ^4.5.5 version: 4.5.5(node-fetch@3.3.2) @@ -797,6 +797,10 @@ packages: /@adraffy/ens-normalize@1.9.0: resolution: {integrity: sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ==} + /@adraffy/ens-normalize@1.9.4: + resolution: {integrity: sha512-UK0bHA7hh9cR39V+4gl2/NnBBjoXIxkuWAPCaY4X7fbH4L/azIi7ilWOCjMUYfpJgraLUAqkRi2BqrjME8Rynw==} + dev: false + /@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.9.0): resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} dependencies: @@ -1543,6 +1547,7 @@ packages: dependencies: '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.23.2): resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} @@ -2583,12 +2588,13 @@ packages: /@bcoe/v8-coverage@0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true /@braintree/sanitize-url@6.0.4: resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==} dev: false - /@celo/rainbowkit-celo@1.1.0(@rainbow-me/rainbowkit@1.0.8)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(wagmi@1.3.9)(zod@3.22.4): + /@celo/rainbowkit-celo@1.1.0(@rainbow-me/rainbowkit@1.2.0)(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(wagmi@1.4.5)(zod@3.22.4): resolution: {integrity: sha512-/G4HFhJNwUk6uU1yqGfQ/LIoNg9UAA4BUcEvFdd0M3DImnKlhodNLUdCmzqv96sjc/I7tMJqBeTnmbhwXdlsjQ==} peerDependencies: '@rainbow-me/rainbowkit': '>=1.0.2 && <=2.0.0' @@ -2596,10 +2602,10 @@ packages: wagmi: '>=1.0.0 && <=2.0.0' dependencies: '@metamask/providers': 11.1.2 - '@rainbow-me/rainbowkit': 1.0.8(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9) - '@wagmi/connectors': 2.7.0(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) - viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) - wagmi: 1.3.9(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + '@rainbow-me/rainbowkit': 1.2.0(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(viem@1.18.4)(wagmi@1.4.5) + '@wagmi/connectors': 2.7.0(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4) + viem: 1.18.4(typescript@5.1.6)(zod@3.22.4) + wagmi: 1.4.5(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4) transitivePeerDependencies: - '@react-native-async-storage/async-storage' - '@wagmi/chains' @@ -5127,24 +5133,6 @@ packages: - utf-8-validate dev: true - /@ethereum-attestation-service/eas-contracts@0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.1.6): - resolution: {integrity: sha512-ly1N/jLbXJjACDL7dnMSkzViBxxuVc+aMZ3EB1kpFxeMWrXkb7nN6w9gxGTH+m3gJztaKvyMsyr/13pA0OYq6Q==} - dependencies: - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.1.6) - '@typechain/hardhat': 6.1.6(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@10.2.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2) - hardhat: 2.13.1(typescript@5.1.6) - typechain: 8.3.2(typescript@5.1.6) - transitivePeerDependencies: - - '@ethersproject/abi' - - '@ethersproject/providers' - - bufferutil - - ethers - - supports-color - - ts-node - - typescript - - utf-8-validate - dev: false - /@ethereum-attestation-service/eas-contracts@1.2.0-beta.1(ts-node@10.9.1)(typescript@5.1.6): resolution: {integrity: sha512-NOicVFjm3UOY6HHmMPIpFTZJ7ieuETl7GRJyceW/CPPXxMMBBu9tf9eDVbVrDn6D7fYX3NMDIR39RoK5BhpWYA==} dependencies: @@ -5157,22 +5145,6 @@ packages: - utf-8-validate dev: false - /@ethereum-attestation-service/eas-sdk@0.28.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(typescript@5.1.6): - resolution: {integrity: sha512-Z197jE5oi8Eh9SmjldTnkPKKhOId2NA9OyEFvbXDMafoHtfC6V117r0GHj9IlsOGtaK8Y0fiZYX1EKMKcJb6UQ==} - dependencies: - '@ethereum-attestation-service/eas-contracts': 0.27.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.1.6) - ethers: 5.7.2 - multiformats: 9.9.0 - transitivePeerDependencies: - - '@ethersproject/abi' - - '@ethersproject/providers' - - bufferutil - - supports-color - - ts-node - - typescript - - utf-8-validate - dev: false - /@ethereum-attestation-service/eas-sdk@1.2.2-beta.0(ts-node@10.9.1)(typescript@5.1.6): resolution: {integrity: sha512-penkXiCKvHY8jN9UVV3B9IX001YnwWCNjbrBNE5e8Wy1rAzcPv7tqTBuvqXzjqmHfcASv7UFOIbfPEc5hd9mpA==} dependencies: @@ -7534,10 +7506,22 @@ packages: resolution: {integrity: sha512-n6fwMsaoR50VITM2upR4OOi4EZJmZvU6vvXrHWCSakP9e1OeDuAOk+kHiK+egqDRYj6uKtg9VTUFKZBYvu3jRg==} dev: false - /@hypercerts-org/sdk@0.8.16(@envelop/core@3.0.6)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3): - resolution: {integrity: sha512-WkxYb5RYhv3QI7+N5y4xg5IL4azLqCq4ia1/bgFB55vWJLjnmoMj3VYbiybMxyfgnPfh5O8n2DU86u8ClLgyhg==} + /@hypercerts-org/contracts@0.9.0(typescript@5.1.6): + resolution: {integrity: sha512-enXkIzZxYMDaOchL9peq6ddIfo0uJeJb1o+nj3LMy5AzK5B+3ijNkJFDUx0N8RZPO2jVgqO3/4czAavndLfNww==} dependencies: - '@ethereum-attestation-service/eas-sdk': 0.28.3(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(typescript@5.1.6) + hardhat: 2.18.3(typescript@5.1.6) + transitivePeerDependencies: + - bufferutil + - supports-color + - ts-node + - typescript + - utf-8-validate + dev: false + + /@hypercerts-org/sdk@0.9.0-viem(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): + resolution: {integrity: sha512-o6zmVQj0w3UnpDk+V8yn6z/mPrW1vfzN8FU22wdulESWf6IrLb09yo75V6srS5PxowC3ggiKfYflBZYpocJWvw==} + dependencies: + '@ethereum-attestation-service/eas-sdk': 1.2.2-beta.0(ts-node@10.9.1)(typescript@5.1.6) '@ethersproject/abstract-signer': 5.7.0 '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) '@graphprotocol/client-polling-live': 2.0.0(@envelop/core@3.0.6)(@graphql-tools/merge@8.4.2)(graphql@16.8.1) @@ -7560,27 +7544,23 @@ packages: ethers: 5.7.2 graphql: 16.8.1 ipfs-core: 0.17.0(uint8arraylist@2.4.3) - jest: 29.7.0(@types/node@18.18.7)(ts-node@10.9.1) loglevel: 1.8.1 mime: 3.0.0 nft.storage: 7.1.1(node-fetch@3.3.2) + viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) web3.storage: 4.5.5(node-fetch@3.3.2) transitivePeerDependencies: - '@envelop/core' - - '@ethersproject/abi' - - '@ethersproject/providers' - '@graphql-tools/delegate' - '@graphql-tools/merge' - '@graphql-tools/utils' - '@graphql-tools/wrap' - '@types/node' - - babel-plugin-macros - bufferutil - debug - encoding - graphql-ws - node-fetch - - node-notifier - react - react-dom - subscriptions-transport-ws @@ -7590,6 +7570,7 @@ packages: - typescript - uint8arraylist - utf-8-validate + - zod dev: false /@iarna/toml@2.2.5: @@ -7690,10 +7671,12 @@ packages: get-package-type: 0.1.0 js-yaml: 3.14.1 resolve-from: 5.0.0 + dev: true /@istanbuljs/schema@0.1.3: resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} + dev: true /@jest/console@29.7.0: resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} @@ -7705,6 +7688,7 @@ packages: jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 + dev: true /@jest/core@29.7.0(ts-node@10.9.1): resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} @@ -7747,6 +7731,7 @@ packages: - babel-plugin-macros - supports-color - ts-node + dev: true /@jest/create-cache-key-function@29.7.0: resolution: {integrity: sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==} @@ -7768,6 +7753,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: jest-get-type: 29.6.3 + dev: true /@jest/expect@29.7.0: resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} @@ -7777,6 +7763,7 @@ packages: jest-snapshot: 29.7.0 transitivePeerDependencies: - supports-color + dev: true /@jest/fake-timers@29.7.0: resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} @@ -7799,6 +7786,7 @@ packages: jest-mock: 29.7.0 transitivePeerDependencies: - supports-color + dev: true /@jest/reporters@29.7.0: resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} @@ -7835,6 +7823,7 @@ packages: v8-to-istanbul: 9.1.3 transitivePeerDependencies: - supports-color + dev: true /@jest/schemas@29.6.3: resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} @@ -7849,6 +7838,7 @@ packages: '@jridgewell/trace-mapping': 0.3.20 callsites: 3.1.0 graceful-fs: 4.2.11 + dev: true /@jest/test-result@29.7.0: resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} @@ -7858,6 +7848,7 @@ packages: '@jest/types': 29.6.3 '@types/istanbul-lib-coverage': 2.0.5 collect-v8-coverage: 1.0.2 + dev: true /@jest/test-sequencer@29.7.0: resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} @@ -7867,6 +7858,7 @@ packages: graceful-fs: 4.2.11 jest-haste-map: 29.7.0 slash: 3.0.0 + dev: true /@jest/transform@29.7.0: resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} @@ -7889,6 +7881,7 @@ packages: write-file-atomic: 4.0.2 transitivePeerDependencies: - supports-color + dev: true /@jest/types@26.6.2: resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==} @@ -9625,22 +9618,6 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - /@nomicfoundation/ethereumjs-block@5.0.0: - resolution: {integrity: sha512-DfhVbqM5DjriguuSv6r3TgOpyXC76oX8D/VEODsSwJQ1bZGqu4xLLfYPPTacpCAYOnewzJsZli+Ao9TBTAo2uw==} - engines: {node: '>=14'} - dependencies: - '@nomicfoundation/ethereumjs-common': 4.0.0 - '@nomicfoundation/ethereumjs-rlp': 5.0.0 - '@nomicfoundation/ethereumjs-trie': 6.0.0 - '@nomicfoundation/ethereumjs-tx': 5.0.0 - '@nomicfoundation/ethereumjs-util': 9.0.0 - ethereum-cryptography: 0.1.3 - ethers: 5.7.2 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: false - /@nomicfoundation/ethereumjs-block@5.0.2: resolution: {integrity: sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q==} engines: {node: '>=14'} @@ -9656,29 +9633,6 @@ packages: - bufferutil - utf-8-validate - /@nomicfoundation/ethereumjs-blockchain@7.0.0: - resolution: {integrity: sha512-cVRCrXZminZr0Mbx2hm0/109GZLn1v5bf0/k+SIbGn50yZm6YCdQt9CgGT0Gk56N2vy8NhXD4apo167m4LWk6Q==} - engines: {node: '>=14'} - dependencies: - '@nomicfoundation/ethereumjs-block': 5.0.0 - '@nomicfoundation/ethereumjs-common': 4.0.0 - '@nomicfoundation/ethereumjs-ethash': 3.0.0 - '@nomicfoundation/ethereumjs-rlp': 5.0.0 - '@nomicfoundation/ethereumjs-trie': 6.0.0 - '@nomicfoundation/ethereumjs-tx': 5.0.0 - '@nomicfoundation/ethereumjs-util': 9.0.0 - abstract-level: 1.0.3 - debug: 4.3.4(supports-color@8.1.1) - ethereum-cryptography: 0.1.3 - level: 8.0.0 - lru-cache: 5.1.1 - memory-level: 1.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: false - /@nomicfoundation/ethereumjs-blockchain@7.0.2: resolution: {integrity: sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w==} engines: {node: '>=14'} @@ -9701,34 +9655,12 @@ packages: - supports-color - utf-8-validate - /@nomicfoundation/ethereumjs-common@4.0.0: - resolution: {integrity: sha512-UPpm5FAGAf2B6hQ8aVgO44Rdo0k73oMMCViqNJcKMlk1s9l3rxwuPTp1l20NiGvNO2Pzqk3chFL+BzmLL2g4wQ==} - dependencies: - '@nomicfoundation/ethereumjs-util': 9.0.0 - crc-32: 1.2.2 - dev: false - /@nomicfoundation/ethereumjs-common@4.0.2: resolution: {integrity: sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg==} dependencies: '@nomicfoundation/ethereumjs-util': 9.0.2 crc-32: 1.2.2 - /@nomicfoundation/ethereumjs-ethash@3.0.0: - resolution: {integrity: sha512-6zNv5Y3vNIsxjrsbKjMInVpo8cmR0c7yjZbBpy7NYuIMtm0JKhQoXsiFN56t/1sfn9V3v0wgrkAixo5v6bahpA==} - engines: {node: '>=14'} - dependencies: - '@nomicfoundation/ethereumjs-block': 5.0.0 - '@nomicfoundation/ethereumjs-rlp': 5.0.0 - '@nomicfoundation/ethereumjs-util': 9.0.0 - abstract-level: 1.0.3 - bigint-crypto-utils: 3.3.0 - ethereum-cryptography: 0.1.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: false - /@nomicfoundation/ethereumjs-ethash@3.0.2: resolution: {integrity: sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg==} engines: {node: '>=14'} @@ -9743,24 +9675,6 @@ packages: - bufferutil - utf-8-validate - /@nomicfoundation/ethereumjs-evm@2.0.0: - resolution: {integrity: sha512-D+tr3M9sictopr3E20OVgme7YF/d0fU566WKh+ofXwmxapz/Dd8RSLSaVeKgfCI2BkzVA+XqXY08NNCV8w8fWA==} - engines: {node: '>=14'} - dependencies: - '@ethersproject/providers': 5.7.2 - '@nomicfoundation/ethereumjs-common': 4.0.0 - '@nomicfoundation/ethereumjs-tx': 5.0.0 - '@nomicfoundation/ethereumjs-util': 9.0.0 - debug: 4.3.4(supports-color@8.1.1) - ethereum-cryptography: 0.1.3 - mcl-wasm: 0.7.9 - rustbn.js: 0.2.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: false - /@nomicfoundation/ethereumjs-evm@2.0.2: resolution: {integrity: sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ==} engines: {node: '>=14'} @@ -9778,32 +9692,11 @@ packages: - supports-color - utf-8-validate - /@nomicfoundation/ethereumjs-rlp@5.0.0: - resolution: {integrity: sha512-U1A0y330PtGb8Wft4yPVv0myWYJTesi89ItGoB0ICdqz7793KmUhpfQb2vJUXBi98wSdnxkIABO/GmsQvGKVDw==} - engines: {node: '>=14'} - hasBin: true - dev: false - /@nomicfoundation/ethereumjs-rlp@5.0.2: resolution: {integrity: sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA==} engines: {node: '>=14'} hasBin: true - /@nomicfoundation/ethereumjs-statemanager@2.0.0: - resolution: {integrity: sha512-tgXtsx8yIDlxWMN+ThqPtGK0ITAuITrDy+GYIgGrnT6ZtelvXWM7SUYR0Mcv578lmGCoIwyHFtSBqOkOBYHLjw==} - dependencies: - '@nomicfoundation/ethereumjs-common': 4.0.0 - '@nomicfoundation/ethereumjs-rlp': 5.0.0 - debug: 4.3.4(supports-color@8.1.1) - ethereum-cryptography: 0.1.3 - ethers: 5.7.2 - js-sdsl: 4.4.2 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: false - /@nomicfoundation/ethereumjs-statemanager@2.0.2: resolution: {integrity: sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA==} dependencies: @@ -9818,17 +9711,6 @@ packages: - supports-color - utf-8-validate - /@nomicfoundation/ethereumjs-trie@6.0.0: - resolution: {integrity: sha512-YqPWiNxrZvL+Ef7KHqgru1IlaIGXhu78wd2fxNFOvi/NAQBF845dVfTKKXs1L9x0QBRRQRephgxHCKMuISGppw==} - engines: {node: '>=14'} - dependencies: - '@nomicfoundation/ethereumjs-rlp': 5.0.0 - '@nomicfoundation/ethereumjs-util': 9.0.0 - '@types/readable-stream': 2.3.15 - ethereum-cryptography: 0.1.3 - readable-stream: 3.6.2 - dev: false - /@nomicfoundation/ethereumjs-trie@6.0.2: resolution: {integrity: sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ==} engines: {node: '>=14'} @@ -9839,21 +9721,6 @@ packages: ethereum-cryptography: 0.1.3 readable-stream: 3.6.2 - /@nomicfoundation/ethereumjs-tx@5.0.0: - resolution: {integrity: sha512-LTyxI+zBJ+HuEBblUGbxvfKl1hg1uJlz2XhnszNagiBWQSgLb1vQCa1QaXV5Q8cUDYkr/Xe4NXWiUGEvH4e6lA==} - engines: {node: '>=14'} - dependencies: - '@chainsafe/ssz': 0.9.4 - '@ethersproject/providers': 5.7.2 - '@nomicfoundation/ethereumjs-common': 4.0.0 - '@nomicfoundation/ethereumjs-rlp': 5.0.0 - '@nomicfoundation/ethereumjs-util': 9.0.0 - ethereum-cryptography: 0.1.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: false - /@nomicfoundation/ethereumjs-tx@5.0.2: resolution: {integrity: sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g==} engines: {node: '>=14'} @@ -9868,15 +9735,6 @@ packages: - bufferutil - utf-8-validate - /@nomicfoundation/ethereumjs-util@9.0.0: - resolution: {integrity: sha512-9EG98CsEC9BnI7AY27F4QXZ8Vf0re8R9XoxQ0//KWF+B7quu6GQvgTq1RlNUjGh/XNCCJNf8E3LOY9ULR85wFQ==} - engines: {node: '>=14'} - dependencies: - '@chainsafe/ssz': 0.10.2 - '@nomicfoundation/ethereumjs-rlp': 5.0.0 - ethereum-cryptography: 0.1.3 - dev: false - /@nomicfoundation/ethereumjs-util@9.0.2: resolution: {integrity: sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ==} engines: {node: '>=14'} @@ -9885,29 +9743,6 @@ packages: '@nomicfoundation/ethereumjs-rlp': 5.0.2 ethereum-cryptography: 0.1.3 - /@nomicfoundation/ethereumjs-vm@7.0.0: - resolution: {integrity: sha512-eHkEoe/4r4+g+fZyIIlQjBHEjCPFs8CHiIEEMvMfvFrV4hyHnuTg4LH7l92ok7TGZqpWxgMG2JOEUFkNsXrKuQ==} - engines: {node: '>=14'} - dependencies: - '@nomicfoundation/ethereumjs-block': 5.0.0 - '@nomicfoundation/ethereumjs-blockchain': 7.0.0 - '@nomicfoundation/ethereumjs-common': 4.0.0 - '@nomicfoundation/ethereumjs-evm': 2.0.0 - '@nomicfoundation/ethereumjs-rlp': 5.0.0 - '@nomicfoundation/ethereumjs-statemanager': 2.0.0 - '@nomicfoundation/ethereumjs-trie': 6.0.0 - '@nomicfoundation/ethereumjs-tx': 5.0.0 - '@nomicfoundation/ethereumjs-util': 9.0.0 - debug: 4.3.4(supports-color@8.1.1) - ethereum-cryptography: 0.1.3 - mcl-wasm: 0.7.9 - rustbn.js: 0.2.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: false - /@nomicfoundation/ethereumjs-vm@7.0.2: resolution: {integrity: sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA==} engines: {node: '>=14'} @@ -10648,25 +10483,27 @@ packages: /@protobufjs/utf8@1.1.0: resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - /@rainbow-me/rainbowkit@1.0.8(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(viem@1.5.3)(wagmi@1.3.9): - resolution: {integrity: sha512-m1B9/X3p8MLmj4fDfs2NpJlFRmKz7vOR0jmcdBw2SMFzXqP1FQFQc4pjvtLEeyfEUGSNNceGrecFZRVS0Qk//A==} + /@rainbow-me/rainbowkit@1.2.0(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(viem@1.18.4)(wagmi@1.4.5): + resolution: {integrity: sha512-XjdeX31GwFdRR/1rCRqPXiO94nbq2qOlnaox5P4K/KMRIUwyelKzak27uWw8Krmor/Hcrd5FisfepGDS0tUfEA==} engines: {node: '>=12.4'} peerDependencies: react: '>=17' react-dom: '>=17' viem: ~0.3.19 || ^1.0.0 - wagmi: ~1.0.1 || ~1.1.0 || ~1.2.0 || ~1.3.0 + wagmi: ~1.0.1 || ~1.1.0 || ~1.2.0 || ~1.3.0 || ~1.4.0 dependencies: '@vanilla-extract/css': 1.9.1 '@vanilla-extract/dynamic': 2.0.2 '@vanilla-extract/sprinkles': 1.5.0(@vanilla-extract/css@1.9.1) clsx: 1.1.1 + i18n-js: 4.3.2 qrcode: 1.5.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-remove-scroll: 2.5.4(@types/react@18.2.33)(react@18.2.0) - viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) - wagmi: 1.3.9(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + ua-parser-js: 1.0.36 + viem: 1.18.4(typescript@5.1.6)(zod@3.22.4) + wagmi: 1.4.5(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4) transitivePeerDependencies: - '@types/react' dev: false @@ -11205,7 +11042,7 @@ packages: resolution: {integrity: sha512-gYw0ki/EAuV1oSyMxpqandHjnthZjYYy+YWpTAzf8BqfXM3ItcZLpjxfg+3+mXW8HIO+3jw6T9iiqEXsqHaMMw==} dependencies: '@safe-global/safe-gateway-typescript-sdk': 3.12.0 - viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) + viem: 1.18.4(typescript@5.1.6)(zod@3.22.4) transitivePeerDependencies: - bufferutil - typescript @@ -11217,7 +11054,7 @@ packages: resolution: {integrity: sha512-XJbEPuaVc7b9n23MqlF6c+ToYIS3f7P2Sel8f3cSBQ9WORE4xrSuvhMpK9fDSFqJ7by/brc+rmJR/5HViRr0/w==} dependencies: '@safe-global/safe-gateway-typescript-sdk': 3.12.0 - viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) + viem: 1.18.4(typescript@5.1.6)(zod@3.22.4) transitivePeerDependencies: - bufferutil - typescript @@ -11255,6 +11092,14 @@ packages: '@scure/base': 1.1.3 dev: true + /@scure/bip32@1.3.2: + resolution: {integrity: sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==} + dependencies: + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@scure/base': 1.1.3 + dev: false + /@scure/bip39@1.1.1: resolution: {integrity: sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==} dependencies: @@ -11272,7 +11117,6 @@ packages: dependencies: '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 - dev: true /@sentry-internal/tracing@7.75.1: resolution: {integrity: sha512-nynV+7iVcF8k3CqhvI2K7iA8h4ovJhgYHKnXR8RDDevQOqNG2AEX9+hjCj9fZM4MhKHYFqf1od2oO9lTr38kwg==} @@ -12246,6 +12090,7 @@ packages: ts-essentials: 7.0.3(typescript@5.1.6) typechain: 8.3.2(typescript@5.1.6) typescript: 5.1.6 + dev: true /@typechain/ethers-v6@0.4.3(ethers@6.8.0)(typechain@8.3.2)(typescript@4.9.5): resolution: {integrity: sha512-TrxBsyb4ryhaY9keP6RzhFCviWYApcLCIRMPyWaKp2cZZrfaM3QBoxXTnw/eO4+DAY3l+8O0brNW0WgeQeOiDA==} @@ -12261,25 +12106,6 @@ packages: typescript: 4.9.5 dev: true - /@typechain/hardhat@6.1.6(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@10.2.1)(ethers@5.7.2)(hardhat@2.13.1)(typechain@8.3.2): - resolution: {integrity: sha512-BiVnegSs+ZHVymyidtK472syodx1sXYlYJJixZfRstHVGYTi8V1O7QG4nsjyb0PC/LORcq7sfBUcHto1y6UgJA==} - peerDependencies: - '@ethersproject/abi': ^5.4.7 - '@ethersproject/providers': ^5.4.7 - '@typechain/ethers-v5': ^10.2.1 - ethers: ^5.4.7 - hardhat: ^2.9.9 - typechain: ^8.1.1 - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/providers': 5.7.2 - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.1.6) - ethers: 5.7.2 - fs-extra: 9.1.0 - hardhat: 2.13.1(typescript@5.1.6) - typechain: 8.3.2(typescript@5.1.6) - dev: false - /@typechain/hardhat@8.0.3(@typechain/ethers-v6@0.4.3)(ethers@6.8.0)(hardhat@2.18.3)(typechain@8.3.2): resolution: {integrity: sha512-MytSmJJn+gs7Mqrpt/gWkTCOpOQ6ZDfRrRT2gtZL0rfGe4QrU4x9ZdW15fFbVM/XTa+5EsKiOMYXhRABibNeng==} peerDependencies: @@ -12315,22 +12141,26 @@ packages: '@types/babel__generator': 7.6.6 '@types/babel__template': 7.4.3 '@types/babel__traverse': 7.20.3 + dev: true /@types/babel__generator@7.6.6: resolution: {integrity: sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==} dependencies: '@babel/types': 7.23.0 + dev: true /@types/babel__template@7.4.3: resolution: {integrity: sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==} dependencies: '@babel/parser': 7.23.0 '@babel/types': 7.23.0 + dev: true /@types/babel__traverse@7.20.3: resolution: {integrity: sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==} dependencies: '@babel/types': 7.23.0 + dev: true /@types/better-sqlite3@7.6.6: resolution: {integrity: sha512-nuFAptzt0hZYBvyLzKQCbuCCK+RN9PHH4ezar5EJLIg2qpVhwQ/uLvLO/K8A9O7N8DafawgFupiyXQSs0U48Ng==} @@ -12458,6 +12288,7 @@ packages: resolution: {integrity: sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==} dependencies: '@types/node': 18.18.7 + dev: true /@types/hast@2.3.7: resolution: {integrity: sha512-EVLigw5zInURhzfXUM65eixfadfsHKomGKUakToXo84t8gGIJuTcD2xooM2See7GyQ7DRtYjhCHnSUQez8JaLw==} @@ -12668,6 +12499,7 @@ packages: /@types/prettier@2.7.3: resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + dev: true /@types/prop-types@15.7.9: resolution: {integrity: sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==} @@ -13317,10 +13149,10 @@ packages: typescript: 5.1.6 dev: false - /@wagmi/connectors@2.6.6(@wagmi/chains@1.6.0)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): - resolution: {integrity: sha512-/o1c/TCivQs8DOAUOcQvY2UIt3p2mWOAHi39D0LC74+ncpXzLC5/gyaWU38qnTxPM8s/PmTmaWDgz+VhICXrag==} + /@wagmi/connectors@2.7.0(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4): + resolution: {integrity: sha512-1KOL0HTJl5kzSC/YdKwFwiokr6poUQn1V/tcT0TpG3iH2x0lSM7FTkvCjVVY/6lKzTXrLlo9y2aE7AsOPnkvqg==} peerDependencies: - '@wagmi/chains': '>=1.3.0' + '@wagmi/chains': '>=1.7.0' typescript: '>=5.0.4' viem: '>=0.3.35' peerDependenciesMeta: @@ -13333,15 +13165,14 @@ packages: '@ledgerhq/connect-kit-loader': 1.1.2 '@safe-global/safe-apps-provider': 0.17.1(typescript@5.1.6)(zod@3.22.4) '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.1.6)(zod@3.22.4) - '@wagmi/chains': 1.6.0(typescript@5.1.6) - '@walletconnect/ethereum-provider': 2.9.0(@walletconnect/modal@2.5.9) + '@walletconnect/ethereum-provider': 2.9.2(@walletconnect/modal@2.6.1) '@walletconnect/legacy-provider': 2.0.0 - '@walletconnect/modal': 2.5.9(react@18.2.0) - '@walletconnect/utils': 2.9.0 + '@walletconnect/modal': 2.6.1(react@18.2.0) + '@walletconnect/utils': 2.9.2 abitype: 0.8.7(typescript@5.1.6)(zod@3.22.4) eventemitter3: 4.0.7 typescript: 5.1.6 - viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) + viem: 1.18.4(typescript@5.1.6)(zod@3.22.4) transitivePeerDependencies: - '@react-native-async-storage/async-storage' - bufferutil @@ -13353,15 +13184,12 @@ packages: - zod dev: false - /@wagmi/connectors@2.7.0(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): - resolution: {integrity: sha512-1KOL0HTJl5kzSC/YdKwFwiokr6poUQn1V/tcT0TpG3iH2x0lSM7FTkvCjVVY/6lKzTXrLlo9y2aE7AsOPnkvqg==} + /@wagmi/connectors@3.1.3(@types/react@18.2.33)(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4): + resolution: {integrity: sha512-UgwsQKQDFObJVJMf9pDfFoXTv710o4zrTHyhIWKBTMMkLpCMsMxN5+ZaDhBYt/BgoRinfRYQo8uwuwLhxE6Log==} peerDependencies: - '@wagmi/chains': '>=1.7.0' typescript: '>=5.0.4' viem: '>=0.3.35' peerDependenciesMeta: - '@wagmi/chains': - optional: true typescript: optional: true dependencies: @@ -13369,16 +13197,17 @@ packages: '@ledgerhq/connect-kit-loader': 1.1.2 '@safe-global/safe-apps-provider': 0.17.1(typescript@5.1.6)(zod@3.22.4) '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.1.6)(zod@3.22.4) - '@walletconnect/ethereum-provider': 2.9.2(@walletconnect/modal@2.6.1) + '@walletconnect/ethereum-provider': 2.10.2(@walletconnect/modal@2.6.2) '@walletconnect/legacy-provider': 2.0.0 - '@walletconnect/modal': 2.6.1(react@18.2.0) - '@walletconnect/utils': 2.9.2 + '@walletconnect/modal': 2.6.2(@types/react@18.2.33)(react@18.2.0) + '@walletconnect/utils': 2.10.2 abitype: 0.8.7(typescript@5.1.6)(zod@3.22.4) eventemitter3: 4.0.7 typescript: 5.1.6 - viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) + viem: 1.18.4(typescript@5.1.6)(zod@3.22.4) transitivePeerDependencies: - '@react-native-async-storage/async-storage' + - '@types/react' - bufferutil - encoding - lokijs @@ -13388,8 +13217,8 @@ packages: - zod dev: false - /@wagmi/core@1.3.8(@types/react@18.2.33)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): - resolution: {integrity: sha512-OYSxikoMizqVnpSkFTwGE7PwFaz2k0PXteSiI0W2Mtk4j4sZzRFdP+9AWeDB6AYm0yU3WvgN1IATx0EEBKUe3w==} + /@wagmi/core@1.4.5(@types/react@18.2.33)(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4): + resolution: {integrity: sha512-N9luRb1Uk4tBN9kaYcQSWKE9AsRt/rvZaFt5IZech4JPzNN2sQlfhKd9GEjOXYRDqEPHdDvos7qyBKiDNTz4GA==} peerDependencies: typescript: '>=5.0.4' viem: '>=0.3.35' @@ -13397,12 +13226,11 @@ packages: typescript: optional: true dependencies: - '@wagmi/chains': 1.6.0(typescript@5.1.6) - '@wagmi/connectors': 2.6.6(@wagmi/chains@1.6.0)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + '@wagmi/connectors': 3.1.3(@types/react@18.2.33)(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4) abitype: 0.8.7(typescript@5.1.6)(zod@3.22.4) eventemitter3: 4.0.7 typescript: 5.1.6 - viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) + viem: 1.18.4(typescript@5.1.6)(zod@3.22.4) zustand: 4.4.4(@types/react@18.2.33)(react@18.2.0) transitivePeerDependencies: - '@react-native-async-storage/async-storage' @@ -13417,22 +13245,22 @@ packages: - zod dev: false - /@walletconnect/core@2.9.0: - resolution: {integrity: sha512-MZYJghS9YCvGe32UOgDj0mCasaOoGHQaYXWeQblXE/xb8HuaM6kAWhjIQN9P+MNp5QP134BHP5olQostcCotXQ==} + /@walletconnect/core@2.10.2: + resolution: {integrity: sha512-JQz/xp3SLEpTeRQctdck2ugSBVEpMxoSE+lFi2voJkZop1hv6P+uqr6E4PzjFluAjeAnKlT1xvra0aFWjPWVcw==} dependencies: '@walletconnect/heartbeat': 1.2.1 '@walletconnect/jsonrpc-provider': 1.0.13 '@walletconnect/jsonrpc-types': 1.0.3 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/jsonrpc-ws-connection': 1.0.12 + '@walletconnect/jsonrpc-ws-connection': 1.0.13 '@walletconnect/keyvaluestorage': 1.0.2 '@walletconnect/logger': 2.0.1 '@walletconnect/relay-api': 1.0.9 '@walletconnect/relay-auth': 1.0.4 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.9.0 - '@walletconnect/utils': 2.9.0 + '@walletconnect/types': 2.10.2 + '@walletconnect/utils': 2.10.2 events: 3.3.0 lodash.isequal: 4.5.0 uint8arrays: 3.1.1 @@ -13494,8 +13322,8 @@ packages: tslib: 1.14.1 dev: false - /@walletconnect/ethereum-provider@2.9.0(@walletconnect/modal@2.5.9): - resolution: {integrity: sha512-rSXkC0SXMigJRdIi/M2RMuEuATY1AwtlTWQBnqyxoht7xbO2bQNPCXn0XL4s/GRNrSUtoKSY4aPMHXV4W4yLBA==} + /@walletconnect/ethereum-provider@2.10.2(@walletconnect/modal@2.6.2): + resolution: {integrity: sha512-QMYFZ6+rVq2CJLdIPdKK0j1Qm66UA27oQU5V2SrL8EVwl7wFfm0Bq7fnL+qAWeDpn612dNeNErpk/ROa1zWlWg==} peerDependencies: '@walletconnect/modal': '>=2' peerDependenciesMeta: @@ -13506,11 +13334,11 @@ packages: '@walletconnect/jsonrpc-provider': 1.0.13 '@walletconnect/jsonrpc-types': 1.0.3 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/modal': 2.5.9(react@18.2.0) - '@walletconnect/sign-client': 2.9.0 - '@walletconnect/types': 2.9.0 - '@walletconnect/universal-provider': 2.9.0 - '@walletconnect/utils': 2.9.0 + '@walletconnect/modal': 2.6.2(@types/react@18.2.33)(react@18.2.0) + '@walletconnect/sign-client': 2.10.2 + '@walletconnect/types': 2.10.2 + '@walletconnect/universal-provider': 2.10.2 + '@walletconnect/utils': 2.10.2 events: 3.3.0 transitivePeerDependencies: - '@react-native-async-storage/async-storage' @@ -13595,19 +13423,6 @@ packages: tslib: 1.14.1 dev: false - /@walletconnect/jsonrpc-ws-connection@1.0.12: - resolution: {integrity: sha512-HAcadga3Qjt1Cqy+qXEW6zjaCs8uJGdGQrqltzl3OjiK4epGZRdvSzTe63P+t/3z+D2wG+ffEPn0GVcDozmN1w==} - dependencies: - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/safe-json': 1.0.2 - events: 3.3.0 - tslib: 1.14.1 - ws: 7.5.9 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: false - /@walletconnect/jsonrpc-ws-connection@1.0.13: resolution: {integrity: sha512-mfOM7uFH4lGtQxG+XklYuFBj6dwVvseTt5/ahOkkmpcAEgz2umuzu7fTR+h5EmjQBdrmYyEBOWADbeaFNxdySg==} dependencies: @@ -13700,15 +13515,6 @@ packages: tslib: 1.14.1 dev: false - /@walletconnect/modal-core@2.5.9(react@18.2.0): - resolution: {integrity: sha512-isIebwF9hOknGouhS/Ob4YJ9Sa/tqNYG2v6Ua9EkCqIoLimepkG5eC53tslUWW29SLSfQ9qqBNG2+iE7yQXqgw==} - dependencies: - buffer: 6.0.3 - valtio: 1.10.6(react@18.2.0) - transitivePeerDependencies: - - react - dev: false - /@walletconnect/modal-core@2.6.1(react@18.2.0): resolution: {integrity: sha512-f2hYlJ5pwzGvjyaZ6BoGR5uiMgXzWXt6w6ktt1N8lmY6PiYp8whZgqx2hTxVWwVlsGnaIfh6UHp1hGnANx0eTQ==} dependencies: @@ -13717,14 +13523,12 @@ packages: - react dev: false - /@walletconnect/modal-ui@2.5.9(react@18.2.0): - resolution: {integrity: sha512-nfBaAT9Ls7RZTBBgAq+Nt/3AoUcinIJ9bcq5UHXTV3lOPu/qCKmUC/0HY3GvUK8ykabUAsjr0OAGmcqkB91qug==} + /@walletconnect/modal-core@2.6.2(@types/react@18.2.33)(react@18.2.0): + resolution: {integrity: sha512-cv8ibvdOJQv2B+nyxP9IIFdxvQznMz8OOr/oR/AaUZym4hjXNL/l1a2UlSQBXrVjo3xxbouMxLb3kBsHoYP2CA==} dependencies: - '@walletconnect/modal-core': 2.5.9(react@18.2.0) - lit: 2.7.5 - motion: 10.16.2 - qrcode: 1.5.3 + valtio: 1.11.2(@types/react@18.2.33)(react@18.2.0) transitivePeerDependencies: + - '@types/react' - react dev: false @@ -13739,12 +13543,15 @@ packages: - react dev: false - /@walletconnect/modal@2.5.9(react@18.2.0): - resolution: {integrity: sha512-Zs2RvPwbBNRdBhb50FuJCxi3FJltt1KSpI7odjU/x9GTpTOcSOkmR66PBCy2JvNA0+ztnS1Xs0LVEr3lu7/Jzw==} + /@walletconnect/modal-ui@2.6.2(@types/react@18.2.33)(react@18.2.0): + resolution: {integrity: sha512-rbdstM1HPGvr7jprQkyPggX7rP4XiCG85ZA+zWBEX0dVQg8PpAgRUqpeub4xQKDgY7pY/xLRXSiCVdWGqvG2HA==} dependencies: - '@walletconnect/modal-core': 2.5.9(react@18.2.0) - '@walletconnect/modal-ui': 2.5.9(react@18.2.0) + '@walletconnect/modal-core': 2.6.2(@types/react@18.2.33)(react@18.2.0) + lit: 2.8.0 + motion: 10.16.2 + qrcode: 1.5.3 transitivePeerDependencies: + - '@types/react' - react dev: false @@ -13757,6 +13564,16 @@ packages: - react dev: false + /@walletconnect/modal@2.6.2(@types/react@18.2.33)(react@18.2.0): + resolution: {integrity: sha512-eFopgKi8AjKf/0U4SemvcYw9zlLpx9njVN8sf6DAkowC2Md0gPU/UNEbH1Wwj407pEKnEds98pKWib1NN1ACoA==} + dependencies: + '@walletconnect/modal-core': 2.6.2(@types/react@18.2.33)(react@18.2.0) + '@walletconnect/modal-ui': 2.6.2(@types/react@18.2.33)(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - react + dev: false + /@walletconnect/randombytes@1.0.3: resolution: {integrity: sha512-35lpzxcHFbTN3ABefC9W+uBpNZl1GC4Wpx0ed30gibfO/y9oLdy1NznbV96HARQKSBV9J9M/rrtIvf6a23jfYw==} dependencies: @@ -13790,17 +13607,17 @@ packages: tslib: 1.14.1 dev: false - /@walletconnect/sign-client@2.9.0: - resolution: {integrity: sha512-mEKc4LlLMebCe45qzqh+MX4ilQK4kOEBzLY6YJpG8EhyT45eX4JMNA7qQoYa9MRMaaVb/7USJcc4e3ZrjZvQmA==} + /@walletconnect/sign-client@2.10.2: + resolution: {integrity: sha512-vviSLV3f92I0bReX+OLr1HmbH0uIzYEQQFd1MzIfDk9PkfFT/LLAHhUnDaIAMkIdippqDcJia+5QEtT4JihL3Q==} dependencies: - '@walletconnect/core': 2.9.0 + '@walletconnect/core': 2.10.2 '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.1 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.0.1 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.9.0 - '@walletconnect/utils': 2.9.0 + '@walletconnect/types': 2.10.2 + '@walletconnect/utils': 2.10.2 events: 3.3.0 transitivePeerDependencies: - '@react-native-async-storage/async-storage' @@ -13834,8 +13651,8 @@ packages: tslib: 1.14.1 dev: false - /@walletconnect/types@2.9.0: - resolution: {integrity: sha512-ORopsMfSRvUYqtjKKd6scfg8o4/aGebipLxx92AuuUgMTERSU6cGmIrK6rdLu7W6FBJkmngPLEGc9mRqAb9Lug==} + /@walletconnect/types@2.10.2: + resolution: {integrity: sha512-luNV+07Wdla4STi9AejseCQY31tzWKQ5a7C3zZZaRK/di+rFaAAb7YW04OP4klE7tw/mJRGPTlekZElmHxO8kQ==} dependencies: '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.1 @@ -13862,17 +13679,17 @@ packages: - lokijs dev: false - /@walletconnect/universal-provider@2.9.0: - resolution: {integrity: sha512-k3nkSBkF69sJJVoe17IVoPtnhp/sgaa2t+x7BvA/BKeMxE0DGdtRJdEXotTc8DBmI7o2tkq6l8+HyFBGjQ/CjQ==} + /@walletconnect/universal-provider@2.10.2: + resolution: {integrity: sha512-wFgI0LbQ3D56sgaUMsgOHCM5m8WLxiC71BGuCKQfApgsbNMVKugYVy2zWHyUyi8sqTQHI+uSaVpDev4UHq9LEw==} dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.7 '@walletconnect/jsonrpc-provider': 1.0.13 '@walletconnect/jsonrpc-types': 1.0.3 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.0.1 - '@walletconnect/sign-client': 2.9.0 - '@walletconnect/types': 2.9.0 - '@walletconnect/utils': 2.9.0 + '@walletconnect/sign-client': 2.10.2 + '@walletconnect/types': 2.10.2 + '@walletconnect/utils': 2.10.2 events: 3.3.0 transitivePeerDependencies: - '@react-native-async-storage/async-storage' @@ -13902,8 +13719,8 @@ packages: - utf-8-validate dev: false - /@walletconnect/utils@2.9.0: - resolution: {integrity: sha512-7Tu3m6dZL84KofrNBcblsgpSqU2vdo9ImLD7zWimLXERVGNQ8smXG+gmhQYblebIBhsPzjy9N38YMC3nPlfQNw==} + /@walletconnect/utils@2.10.2: + resolution: {integrity: sha512-syxXRpc2yhSknMu3IfiBGobxOY7fLfLTJuw+ppKaeO6WUdZpIit3wfuGOcc0Ms3ZPFCrGfyGOoZsCvgdXtptRg==} dependencies: '@stablelib/chacha20poly1305': 1.0.1 '@stablelib/hkdf': 1.0.1 @@ -13913,7 +13730,7 @@ packages: '@walletconnect/relay-api': 1.0.9 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.9.0 + '@walletconnect/types': 2.10.2 '@walletconnect/window-getters': 1.0.1 '@walletconnect/window-metadata': 1.0.1 detect-browser: 5.3.0 @@ -14311,6 +14128,21 @@ packages: zod: 3.22.4 dev: false + /abitype@0.9.8(typescript@5.1.6)(zod@3.22.4): + resolution: {integrity: sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3 >=3.19.1 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + dependencies: + typescript: 5.1.6 + zod: 3.22.4 + dev: false + /abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -14760,10 +14592,12 @@ packages: /array-back@3.1.0: resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} engines: {node: '>=6'} + dev: true /array-back@4.0.2: resolution: {integrity: sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==} engines: {node: '>=8'} + dev: true /array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} @@ -15134,6 +14968,7 @@ packages: slash: 3.0.0 transitivePeerDependencies: - supports-color + dev: true /babel-loader@8.3.0(@babel/core@7.23.2)(webpack@5.89.0): resolution: {integrity: sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==} @@ -15196,6 +15031,7 @@ packages: test-exclude: 6.0.0 transitivePeerDependencies: - supports-color + dev: true /babel-plugin-jest-hoist@29.6.3: resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} @@ -15205,6 +15041,7 @@ packages: '@babel/types': 7.23.0 '@types/babel__core': 7.20.3 '@types/babel__traverse': 7.20.3 + dev: true /babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} @@ -15305,6 +15142,7 @@ packages: '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.2) '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.2) '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.23.2) + dev: true /babel-preset-fbjs@3.4.0(@babel/core@7.23.2): resolution: {integrity: sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==} @@ -15349,6 +15187,7 @@ packages: '@babel/core': 7.23.2 babel-plugin-jest-hoist: 29.6.3 babel-preset-current-node-syntax: 1.0.1(@babel/core@7.23.2) + dev: true /babel-runtime@6.26.0: resolution: {integrity: sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==} @@ -15433,7 +15272,6 @@ packages: /bignumber.js@9.1.2: resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} - dev: true /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} @@ -16181,6 +16019,7 @@ packages: /char-regex@1.0.2: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} + dev: true /character-entities-legacy@1.1.4: resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} @@ -16283,6 +16122,7 @@ packages: /cjs-module-lexer@1.2.3: resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} + dev: true /class-is@1.1.0: resolution: {integrity: sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==} @@ -16502,6 +16342,7 @@ packages: /co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true /code-point-at@1.1.0: resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} @@ -16514,6 +16355,7 @@ packages: /collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + dev: true /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -16577,6 +16419,7 @@ packages: find-replace: 3.0.0 lodash.camelcase: 4.3.0 typical: 4.0.0 + dev: true /command-line-usage@6.1.3: resolution: {integrity: sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==} @@ -16586,6 +16429,7 @@ packages: chalk: 2.4.2 table-layout: 1.0.2 typical: 5.2.0 + dev: true /commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} @@ -17024,6 +16868,7 @@ packages: - babel-plugin-macros - supports-color - ts-node + dev: true /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} @@ -17899,6 +17744,7 @@ packages: peerDependenciesMeta: babel-plugin-macros: optional: true + dev: true /deep-eql@4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} @@ -18104,6 +17950,7 @@ packages: /detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} + dev: true /detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} @@ -18135,6 +17982,7 @@ packages: /diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true /diff@3.5.0: resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} @@ -18473,6 +18321,7 @@ packages: /emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} engines: {node: '>=12'} + dev: true /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -19675,6 +19524,7 @@ packages: /exit@0.1.2: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} engines: {node: '>= 0.8.0'} + dev: true /expand-tilde@2.0.2: resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} @@ -19692,6 +19542,7 @@ packages: jest-matcher-utils: 29.7.0 jest-message-util: 29.7.0 jest-util: 29.7.0 + dev: true /express@4.18.2: resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} @@ -20160,6 +20011,7 @@ packages: engines: {node: '>=4.0.0'} dependencies: array-back: 3.1.0 + dev: true /find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} @@ -20639,6 +20491,7 @@ packages: /get-package-type@0.1.0: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} engines: {node: '>=8.0.0'} + dev: true /get-port@3.2.0: resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==} @@ -21258,9 +21111,8 @@ packages: murmur-128: 0.2.1 dev: true - /hardhat@2.13.1(typescript@5.1.6): - resolution: {integrity: sha512-ZZL7LQxHmbw4JQJsiEv2qE35nbR+isr2sIdtgZVPp0+zWqRkpr1OT7gmvhCNYfjpEPyfjZIxWriQWlphJhVPLQ==} - engines: {node: '>=14.0.0'} + /hardhat@2.18.2(ts-node@10.9.1)(typescript@5.1.6): + resolution: {integrity: sha512-lUVmJg7DsKcUCDpqv57CJl6vHqo/1PeHSfM3+WIa8UtRKmXyVTj1qQK01TDiuetkZBVg9Dn52qU+ZwaJQynaKA==} hasBin: true peerDependencies: ts-node: '*' @@ -21273,21 +21125,20 @@ packages: dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.1 - '@nomicfoundation/ethereumjs-block': 5.0.0 - '@nomicfoundation/ethereumjs-blockchain': 7.0.0 - '@nomicfoundation/ethereumjs-common': 4.0.0 - '@nomicfoundation/ethereumjs-evm': 2.0.0 - '@nomicfoundation/ethereumjs-rlp': 5.0.0 - '@nomicfoundation/ethereumjs-statemanager': 2.0.0 - '@nomicfoundation/ethereumjs-trie': 6.0.0 - '@nomicfoundation/ethereumjs-tx': 5.0.0 - '@nomicfoundation/ethereumjs-util': 9.0.0 - '@nomicfoundation/ethereumjs-vm': 7.0.0 + '@nomicfoundation/ethereumjs-block': 5.0.2 + '@nomicfoundation/ethereumjs-blockchain': 7.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-evm': 2.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-statemanager': 2.0.2 + '@nomicfoundation/ethereumjs-trie': 6.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + '@nomicfoundation/ethereumjs-vm': 7.0.2 '@nomicfoundation/solidity-analyzer': 0.1.1 '@sentry/node': 5.30.0 '@types/bn.js': 5.1.3 '@types/lru-cache': 5.1.1 - abort-controller: 3.0.0 adm-zip: 0.4.16 aggregate-error: 3.1.0 ansi-escapes: 4.3.2 @@ -21310,13 +21161,13 @@ packages: mnemonist: 0.38.5 mocha: 10.2.0 p-map: 4.0.0 - qs: 6.11.2 raw-body: 2.5.2 resolve: 1.17.0 semver: 6.3.1 solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 + ts-node: 10.9.1(@types/node@18.18.7)(typescript@5.1.6) tsort: 0.0.1 typescript: 5.1.6 undici: 5.26.5 @@ -21328,8 +21179,8 @@ packages: - utf-8-validate dev: false - /hardhat@2.18.2(ts-node@10.9.1)(typescript@5.1.6): - resolution: {integrity: sha512-lUVmJg7DsKcUCDpqv57CJl6vHqo/1PeHSfM3+WIa8UtRKmXyVTj1qQK01TDiuetkZBVg9Dn52qU+ZwaJQynaKA==} + /hardhat@2.18.3(ts-node@10.9.1)(typescript@4.9.5): + resolution: {integrity: sha512-JuYaTG+4ZHVjEHCW5Hn6jCHH3LpO75dtgznZpM/dLv12RcSlw/xHbeQh3FAsGahQr1epKryZcZEMHvztVZHe0g==} hasBin: true peerDependencies: ts-node: '*' @@ -21384,9 +21235,9 @@ packages: solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 - ts-node: 10.9.1(@types/node@18.18.7)(typescript@5.1.6) + ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) tsort: 0.0.1 - typescript: 5.1.6 + typescript: 4.9.5 undici: 5.26.5 uuid: 8.3.2 ws: 7.5.9 @@ -21394,9 +21245,8 @@ packages: - bufferutil - supports-color - utf-8-validate - dev: false - /hardhat@2.18.3(ts-node@10.9.1)(typescript@4.9.5): + /hardhat@2.18.3(typescript@5.1.6): resolution: {integrity: sha512-JuYaTG+4ZHVjEHCW5Hn6jCHH3LpO75dtgznZpM/dLv12RcSlw/xHbeQh3FAsGahQr1epKryZcZEMHvztVZHe0g==} hasBin: true peerDependencies: @@ -21452,9 +21302,8 @@ packages: solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 - ts-node: 10.9.1(@types/node@18.18.7)(typescript@4.9.5) tsort: 0.0.1 - typescript: 4.9.5 + typescript: 5.1.6 undici: 5.26.5 uuid: 8.3.2 ws: 7.5.9 @@ -21462,6 +21311,7 @@ packages: - bufferutil - supports-color - utf-8-validate + dev: false /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -21715,6 +21565,7 @@ packages: /html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true /html-minifier-terser@5.1.1: resolution: {integrity: sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==} @@ -21965,6 +21816,14 @@ packages: resolution: {integrity: sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==} dev: false + /i18n-js@4.3.2: + resolution: {integrity: sha512-n8gbEbQEueym2/q2yrZk5/xKWjFcKtg3/Escw4JHSVWa8qtKqP8j7se3UjkRbHlO/REqFA0V/MG1q8tEfyHeOA==} + dependencies: + bignumber.js: 9.1.2 + lodash: 4.17.21 + make-plural: 7.3.0 + dev: false + /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -23040,6 +22899,7 @@ packages: /is-generator-fn@2.1.0: resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} engines: {node: '>=6'} + dev: true /is-generator-function@1.0.10: resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} @@ -23444,6 +23304,14 @@ packages: dependencies: ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + /isows@1.0.3(ws@8.13.0): + resolution: {integrity: sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==} + peerDependencies: + ws: '*' + dependencies: + ws: 8.13.0 + dev: false + /isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} dev: true @@ -23456,6 +23324,7 @@ packages: /istanbul-lib-coverage@3.2.0: resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} engines: {node: '>=8'} + dev: true /istanbul-lib-hook@3.0.0: resolution: {integrity: sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==} @@ -23487,6 +23356,7 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color + dev: true /istanbul-lib-instrument@6.0.1: resolution: {integrity: sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==} @@ -23499,6 +23369,7 @@ packages: semver: 7.5.4 transitivePeerDependencies: - supports-color + dev: true /istanbul-lib-processinfo@2.0.3: resolution: {integrity: sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==} @@ -23519,6 +23390,7 @@ packages: istanbul-lib-coverage: 3.2.0 make-dir: 4.0.0 supports-color: 7.2.0 + dev: true /istanbul-lib-source-maps@4.0.1: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} @@ -23529,6 +23401,7 @@ packages: source-map: 0.6.1 transitivePeerDependencies: - supports-color + dev: true /istanbul-reports@3.1.6: resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} @@ -23536,6 +23409,7 @@ packages: dependencies: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 + dev: true /isurl@1.0.0: resolution: {integrity: sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==} @@ -23922,6 +23796,7 @@ packages: execa: 5.1.1 jest-util: 29.7.0 p-limit: 3.1.0 + dev: true /jest-circus@29.7.0: resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} @@ -23950,6 +23825,7 @@ packages: transitivePeerDependencies: - babel-plugin-macros - supports-color + dev: true /jest-cli@29.7.0(@types/node@18.18.7)(ts-node@10.9.1): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} @@ -23977,6 +23853,7 @@ packages: - babel-plugin-macros - supports-color - ts-node + dev: true /jest-config@29.7.0(@types/node@18.18.7)(ts-node@10.9.1): resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} @@ -24017,6 +23894,7 @@ packages: transitivePeerDependencies: - babel-plugin-macros - supports-color + dev: true /jest-diff@29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} @@ -24026,12 +23904,14 @@ packages: diff-sequences: 29.6.3 jest-get-type: 29.6.3 pretty-format: 29.7.0 + dev: true /jest-docblock@29.7.0: resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: detect-newline: 3.1.0 + dev: true /jest-each@29.7.0: resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} @@ -24042,6 +23922,7 @@ packages: jest-get-type: 29.6.3 jest-util: 29.7.0 pretty-format: 29.7.0 + dev: true /jest-environment-jsdom@29.7.0: resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} @@ -24121,6 +24002,7 @@ packages: walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 + dev: true /jest-leak-detector@29.7.0: resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} @@ -24128,6 +24010,7 @@ packages: dependencies: jest-get-type: 29.6.3 pretty-format: 29.7.0 + dev: true /jest-matcher-utils@29.7.0: resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} @@ -24137,6 +24020,7 @@ packages: jest-diff: 29.7.0 jest-get-type: 29.6.3 pretty-format: 29.7.0 + dev: true /jest-message-util@29.7.0: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} @@ -24170,6 +24054,7 @@ packages: optional: true dependencies: jest-resolve: 29.7.0 + dev: true /jest-regex-util@27.5.1: resolution: {integrity: sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==} @@ -24178,6 +24063,7 @@ packages: /jest-regex-util@29.6.3: resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true /jest-resolve-dependencies@29.7.0: resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} @@ -24187,6 +24073,7 @@ packages: jest-snapshot: 29.7.0 transitivePeerDependencies: - supports-color + dev: true /jest-resolve@29.7.0: resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} @@ -24201,6 +24088,7 @@ packages: resolve: 1.22.8 resolve.exports: 2.0.2 slash: 3.0.0 + dev: true /jest-runner@29.7.0: resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} @@ -24229,6 +24117,7 @@ packages: source-map-support: 0.5.13 transitivePeerDependencies: - supports-color + dev: true /jest-runtime@29.7.0: resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} @@ -24258,6 +24147,7 @@ packages: strip-bom: 4.0.0 transitivePeerDependencies: - supports-color + dev: true /jest-snapshot@29.7.0: resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} @@ -24285,6 +24175,7 @@ packages: semver: 7.5.4 transitivePeerDependencies: - supports-color + dev: true /jest-util@27.5.1: resolution: {integrity: sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==} @@ -24331,6 +24222,7 @@ packages: emittery: 0.13.1 jest-util: 29.7.0 string-length: 4.0.2 + dev: true /jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} @@ -24368,6 +24260,7 @@ packages: - babel-plugin-macros - supports-color - ts-node + dev: true /jiti@1.20.0: resolution: {integrity: sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==} @@ -25144,16 +25037,16 @@ packages: '@types/trusted-types': 2.0.5 dev: false - /lit@2.7.5: - resolution: {integrity: sha512-i/cH7Ye6nBDUASMnfwcictBnsTN91+aBjXoTHF2xARghXScKxpD4F4WYI+VLXg9lqbMinDfvoI7VnZXjyHgdfQ==} + /lit@2.7.6: + resolution: {integrity: sha512-1amFHA7t4VaaDe+vdQejSVBklwtH9svGoG6/dZi9JhxtJBBlqY5D1RV7iLUYY0trCqQc4NfhYYZilZiVHt7Hxg==} dependencies: '@lit/reactive-element': 1.6.3 lit-element: 3.3.3 lit-html: 2.8.0 dev: false - /lit@2.7.6: - resolution: {integrity: sha512-1amFHA7t4VaaDe+vdQejSVBklwtH9svGoG6/dZi9JhxtJBBlqY5D1RV7iLUYY0trCqQc4NfhYYZilZiVHt7Hxg==} + /lit@2.8.0: + resolution: {integrity: sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==} dependencies: '@lit/reactive-element': 1.6.3 lit-element: 3.3.3 @@ -25266,6 +25159,7 @@ packages: /lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: true /lodash.clone@4.5.0: resolution: {integrity: sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==} @@ -25604,10 +25498,15 @@ packages: engines: {node: '>=10'} dependencies: semver: 7.5.4 + dev: true /make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + /make-plural@7.3.0: + resolution: {integrity: sha512-/K3BC0KIsO+WK2i94LkMPv3wslMrazrQhfi5We9fMbLlLjzoOSJWr7TAdupLlDWaJcWxwoNosBkhFDejiu5VDw==} + dev: false + /makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} dependencies: @@ -28514,6 +28413,7 @@ packages: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} hasBin: true + dev: true /pretty-bytes@5.6.0: resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} @@ -28810,6 +28710,7 @@ packages: /pure-rand@6.0.4: resolution: {integrity: sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==} + dev: true /pvtsutils@1.3.5: resolution: {integrity: sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==} @@ -29581,6 +29482,7 @@ packages: /reduce-flatten@2.0.0: resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} engines: {node: '>=6'} + dev: true /reflect.getprototypeof@1.0.4: resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} @@ -29923,6 +29825,7 @@ packages: /resolve.exports@2.0.2: resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} engines: {node: '>=10'} + dev: true /resolve@1.1.7: resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} @@ -31011,6 +30914,7 @@ packages: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 + dev: true /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -31290,6 +31194,7 @@ packages: /string-format@2.0.0: resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} + dev: true /string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} @@ -31297,6 +31202,7 @@ packages: dependencies: char-regex: 1.0.2 strip-ansi: 6.0.1 + dev: true /string-similarity@4.0.4: resolution: {integrity: sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==} @@ -31449,6 +31355,7 @@ packages: /strip-bom@4.0.0: resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} engines: {node: '>=8'} + dev: true /strip-dirs@2.1.0: resolution: {integrity: sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==} @@ -31670,6 +31577,7 @@ packages: deep-extend: 0.6.0 typical: 5.2.0 wordwrapjs: 4.0.1 + dev: true /table@6.8.1: resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} @@ -31781,6 +31689,7 @@ packages: '@istanbuljs/schema': 0.1.3 glob: 7.2.3 minimatch: 3.1.2 + dev: true /testrpc@0.0.1: resolution: {integrity: sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA==} @@ -32088,6 +31997,7 @@ packages: command-line-args: 5.2.1 command-line-usage: 6.1.3 string-format: 2.0.0 + dev: true /ts-dedent@2.2.0: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} @@ -32112,6 +32022,7 @@ packages: typescript: '>=3.7.0' dependencies: typescript: 5.1.6 + dev: true /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} @@ -32552,6 +32463,7 @@ packages: typescript: 5.1.6 transitivePeerDependencies: - supports-color + dev: true /typed-array-buffer@1.0.0: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} @@ -32644,10 +32556,12 @@ packages: /typical@4.0.0: resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} engines: {node: '>=8'} + dev: true /typical@5.2.0: resolution: {integrity: sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==} engines: {node: '>=8'} + dev: true /ua-parser-js@1.0.36: resolution: {integrity: sha512-znuyCIXzl8ciS3+y3fHJI/2OhQIXbXw9MWC/o3qwyR+RGppjZHrM27CGFSKCJXi2Kctiz537iOu2KnXs1lMQhw==} @@ -33213,6 +33127,7 @@ packages: '@jridgewell/trace-mapping': 0.3.20 '@types/istanbul-lib-coverage': 2.0.5 convert-source-map: 2.0.0 + dev: true /validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -33227,8 +33142,8 @@ packages: builtins: 5.0.1 dev: true - /valtio@1.10.6(react@18.2.0): - resolution: {integrity: sha512-SxN1bHUmdhW6V8qsQTpCgJEwp7uHbntuH0S9cdLQtiohuevwBksbpXjwj5uDMA7bLwg1WKyq9sEpZrx3TIMrkA==} + /valtio@1.11.0(react@18.2.0): + resolution: {integrity: sha512-65Yd0yU5qs86b5lN1eu/nzcTgQ9/6YnD6iO+DDaDbQLn1Zv2w12Gwk43WkPlUBxk5wL/6cD5YMFf7kj6HZ1Kpg==} engines: {node: '>=12.20.0'} peerDependencies: react: '>=16.8' @@ -33241,15 +33156,19 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - /valtio@1.11.0(react@18.2.0): - resolution: {integrity: sha512-65Yd0yU5qs86b5lN1eu/nzcTgQ9/6YnD6iO+DDaDbQLn1Zv2w12Gwk43WkPlUBxk5wL/6cD5YMFf7kj6HZ1Kpg==} + /valtio@1.11.2(@types/react@18.2.33)(react@18.2.0): + resolution: {integrity: sha512-1XfIxnUXzyswPAPXo1P3Pdx2mq/pIqZICkWN60Hby0d9Iqb+MEIpqgYVlbflvHdrp2YR/q3jyKWRPJJ100yxaw==} engines: {node: '>=12.20.0'} peerDependencies: + '@types/react': '>=16.8' react: '>=16.8' peerDependenciesMeta: + '@types/react': + optional: true react: optional: true dependencies: + '@types/react': 18.2.33 proxy-compare: 2.5.1 react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) @@ -33345,6 +33264,29 @@ packages: - zod dev: true + /viem@1.18.4(typescript@5.1.6)(zod@3.22.4): + resolution: {integrity: sha512-im+y30k+IGT6VtfD/q1V0RX5PaiHPsFTHkKqvTjTqV+ZT8RgJXzOGPXr5E0uPIm2cbJAJp6A9nR9BCHY7BKR2Q==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@adraffy/ens-normalize': 1.9.4 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@scure/bip32': 1.3.2 + '@scure/bip39': 1.2.1 + abitype: 0.9.8(typescript@5.1.6)(zod@3.22.4) + isows: 1.0.3(ws@8.13.0) + typescript: 5.1.6 + ws: 8.13.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + dev: false + /viem@1.5.3(typescript@5.1.6)(zod@3.22.4): resolution: {integrity: sha512-oImpSDDvm8Y72qxXV0pCAGAqQLYgo8YENdz9EKS8ExnnOJLascpex4LNazNyp9cksjm3ORpVpbqGMr9Cy1z2mg==} peerDependencies: @@ -33523,8 +33465,8 @@ packages: hasBin: true dev: true - /wagmi@1.3.9(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4): - resolution: {integrity: sha512-BQbl+vWLNpLraXd/MWsl1P3I41l7DHrujx6qshIa1HDV7Mdh0GNrDuluRYBtuK2bBx9WM/Fjw45Ef2aKADan9A==} + /wagmi@1.4.5(@types/react@18.2.33)(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4): + resolution: {integrity: sha512-Ph62E6cO5n2Z8Z5LTyZrkaNprxTsbC4w0qZJT4OJdXrEELziI8z/b4FO6amVFXdu2rDp/wpvF56e4mhKC8/Kdw==} peerDependencies: react: '>=17.0.0' typescript: '>=5.0.4' @@ -33536,12 +33478,12 @@ packages: '@tanstack/query-sync-storage-persister': 4.36.1 '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react-native@0.72.6)(react@18.2.0) '@tanstack/react-query-persist-client': 4.36.1(@tanstack/react-query@4.36.1) - '@wagmi/core': 1.3.8(@types/react@18.2.33)(react@18.2.0)(typescript@5.1.6)(viem@1.5.3)(zod@3.22.4) + '@wagmi/core': 1.4.5(@types/react@18.2.33)(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4) abitype: 0.8.7(typescript@5.1.6)(zod@3.22.4) react: 18.2.0 typescript: 5.1.6 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) + viem: 1.18.4(typescript@5.1.6)(zod@3.22.4) transitivePeerDependencies: - '@react-native-async-storage/async-storage' - '@types/react' @@ -34073,6 +34015,7 @@ packages: dependencies: reduce-flatten: 2.0.0 typical: 5.2.0 + dev: true /workerpool@6.2.1: resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} @@ -34163,6 +34106,7 @@ packages: dependencies: imurmurhash: 0.1.4 signal-exit: 3.0.7 + dev: true /ws@6.2.2: resolution: {integrity: sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==} diff --git a/sdk/package.json b/sdk/package.json index c86d6153..24f20f0b 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -49,7 +49,7 @@ "loglevel": "^1.8.1", "mime": "^3.0.0", "nft.storage": "^7.1.1", - "viem": "1.5.3", + "viem": "^1.18.4", "web3.storage": "^4.5.5" }, "devDependencies": { diff --git a/sdk/src/client.ts b/sdk/src/client.ts index d86f6135..f4491a68 100644 --- a/sdk/src/client.ts +++ b/sdk/src/client.ts @@ -5,6 +5,7 @@ import { GetContractReturnType, Hex, PublicClient, + WalletClient, WriteContractReturnType, getContract, parseAbi, @@ -42,7 +43,7 @@ export default class HypercertClient implements HypercertClientInterface { private _indexer: HypercertIndexer; //TODO added the TypedDataSigner since that's needed for EAS signing. Will this work on front-end? private _publicClient: PublicClient; - private _walletClient; + private _walletClient: WalletClient | undefined; readonly: boolean; /** @@ -315,13 +316,16 @@ export default class HypercertClient implements HypercertClientInterface { const claimOwner = await readContract.read.ownerOf([claimId]); - if ((claimOwner as `0x${string}`).toLowerCase() !== operator.account?.address.toLowerCase()) + if ((claimOwner as `0x${string}`).toLowerCase() !== operator.account?.address.toLowerCase()) { + console.log("claimOwner", claimOwner); + console.log("operator.account?.address", operator.account?.address); throw new ClientError("Claim is not owned by the signer", { signer: operator.account?.address, claimOwner }); + } const { request } = await this._publicClient.simulateContract({ functionName: "burnFraction", - account: operator.account.address, - args: [operator.account.address, claimId], + account: operator.account?.address, + args: [operator.account?.address, claimId], ...this.getContractConfig(), ...this.getCleanedOverrides(overrides), }); diff --git a/sdk/test/client/allowlist.minting.test.ts b/sdk/test/client/allowlist.minting.test.ts index 8c297712..54126e62 100644 --- a/sdk/test/client/allowlist.minting.test.ts +++ b/sdk/test/client/allowlist.minting.test.ts @@ -13,14 +13,14 @@ describe("Allows for minting claims from an allowlist", () => { const metaDataStub = sinon.stub(HypercertsStorage.prototype, "storeMetadata").resolves(hypercertMetadata.cid); const dataStub = sinon.stub(HypercertsStorage.prototype, "storeData").resolves(hypercertData.cid); const wallet = walletClient; - const userAddress = wallet.account.address; + const userAddress = wallet.account?.address; const client = new HypercertClient({ id: 5, walletClient, publicClient, }); - const readSpy = sinon.stub(publicClient, "request"); + const readSpy = sinon.stub(publicClient, "readContract"); let writeSpy = sinon.stub(walletClient, "writeContract"); const mintClaimFromAllowlistResult = encodeFunctionResult({ diff --git a/sdk/test/client/burn.test.ts b/sdk/test/client/burn.test.ts index f5c1de5a..e127cbf5 100644 --- a/sdk/test/client/burn.test.ts +++ b/sdk/test/client/burn.test.ts @@ -1,14 +1,13 @@ import HypercertClient from "../../src/client"; -import { HypercertMinterAbi } from "@hypercerts-org/contracts"; import { walletClient, publicClient } from "../helpers"; -import { encodeFunctionResult, isHex, parseAbi } from "viem"; +import { ContractFunctionExecutionError, isHex, toHex } from "viem"; import sinon from "sinon"; import { faker } from "@faker-js/faker"; import { ClientError } from "../../src"; describe("burn fraction tokens in HypercertClient", () => { const wallet = walletClient; - const userAddress = wallet.account.address; + const userAddress = wallet.account?.address; const client = new HypercertClient({ id: 5, walletClient, @@ -17,15 +16,9 @@ describe("burn fraction tokens in HypercertClient", () => { const fractionId = 9868188640707215440437863615521278132232n; - let readSpy = sinon.stub(publicClient, "request"); + let readSpy = sinon.stub(publicClient, "readContract"); let writeSpy = sinon.stub(walletClient, "writeContract"); - const burnFractionResult = encodeFunctionResult({ - abi: parseAbi(HypercertMinterAbi), - functionName: "burnFraction", - result: [], - }); - beforeEach(async () => { readSpy.resetBehavior(); readSpy.resetHistory(); @@ -39,19 +32,14 @@ describe("burn fraction tokens in HypercertClient", () => { }); it("allows for a hypercert fraction to be burned", async () => { - const ownerOfResult = encodeFunctionResult({ - abi: parseAbi(HypercertMinterAbi), - functionName: "ownerOf", - result: [userAddress], - }); + readSpy = readSpy.resolves(userAddress); - readSpy = readSpy.withArgs(sinon.match({ method: "eth_call" })).resolves(ownerOfResult); - - writeSpy = writeSpy.resolves(burnFractionResult); + writeSpy = writeSpy.resolves(toHex(420)); expect(client.readonly).toBe(false); const hash = await client.burnClaimFraction(fractionId); + console.log(hash); //TODO determine underlying calls and mock those out. Some are provider simulation calls expect(isHex(hash)).toBeTruthy(); @@ -60,15 +48,7 @@ describe("burn fraction tokens in HypercertClient", () => { }); it("throws on burning fraction not owned by signer", async () => { - const ownerOfResult = encodeFunctionResult({ - abi: parseAbi(HypercertMinterAbi), - functionName: "ownerOf", - result: [faker.finance.ethereumAddress()], - }); - - readSpy = readSpy.withArgs(sinon.match({ method: "eth_call" })).resolves(ownerOfResult); - - writeSpy = writeSpy.resolves(burnFractionResult); + readSpy = readSpy.resolves(faker.finance.ethereumAddress()); expect(client.readonly).toBe(false); @@ -76,7 +56,6 @@ describe("burn fraction tokens in HypercertClient", () => { try { hash = await client.burnClaimFraction(fractionId); } catch (e) { - console.log(e); expect(e instanceof ClientError).toBeTruthy(); const error = e as ClientError; @@ -85,39 +64,35 @@ describe("burn fraction tokens in HypercertClient", () => { //TODO determine underlying calls and mock those out. Some are provider simulation calls expect(hash).toBeUndefined(); - expect(readSpy.callCount).toBe(2); + expect(readSpy.callCount).toBe(1); expect(writeSpy.callCount).toBe(0); expect.assertions(6); }); it("allows for a hypercert fraction to be burned with override params", async () => { - const ownerOfResult = encodeFunctionResult({ - abi: parseAbi(HypercertMinterAbi), - functionName: "ownerOf", - result: [userAddress], - }); + readSpy = readSpy.resolves(userAddress); - readSpy = readSpy.withArgs(sinon.match({ method: "eth_call" })).resolves(ownerOfResult); - - writeSpy = writeSpy.resolves(burnFractionResult); + writeSpy = writeSpy.resolves(toHex(420)); expect(client.readonly).toBe(false); - let hash; + let noHash; try { - hash = await client.burnClaimFraction(fractionId, { gasLimit: "FALSE_VALUE" as unknown as bigint }); + noHash = await client.burnClaimFraction(fractionId, { gasLimit: "FALSE_VALUE" as unknown as bigint }); expect.fail("should have thrown on incorrect gasLimit value"); } catch (e) { - expect((e as Error).message).toMatch(/Cannot convert FALSE_VALUE to a BigInt/); + expect(e instanceof ContractFunctionExecutionError).toBeTruthy(); } - await client.burnClaimFraction(fractionId, { gasLimit: 12300000n }); + const hash = await client.burnClaimFraction(fractionId, { gasLimit: 12300000n }); //TODO determine underlying calls and mock those out. Some are provider simulation calls - expect(hash).toBeUndefined(); - expect(readSpy.callCount).toBe(4); + expect(noHash).toBeUndefined(); + + expect(isHex(hash)).toBeTrue(); + expect(readSpy.callCount).toBe(2); expect(writeSpy.callCount).toBe(1); - expect.assertions(5); + expect.assertions(6); }); }); diff --git a/sdk/test/client/minting.test.ts b/sdk/test/client/minting.test.ts index cb71bfb4..518b973c 100644 --- a/sdk/test/client/minting.test.ts +++ b/sdk/test/client/minting.test.ts @@ -1,6 +1,6 @@ import { expect } from "chai"; import sinon from "sinon"; -import { encodeFunctionResult, isHex, parseAbi } from "viem"; +import { ContractFunctionExecutionError, encodeFunctionResult, isHex, parseAbi } from "viem"; import HypercertClient from "../../src/client"; import { HypercertMetadata, formatHypercertData } from "../../src"; @@ -24,7 +24,7 @@ describe("mintClaim in HypercertClient", () => { publicClient, }); - const readSpy = sinon.stub(publicClient, "request"); + const readSpy = sinon.stub(publicClient, "readContract"); let writeSpy = sinon.stub(walletClient, "writeContract"); const mintClaimResult = encodeFunctionResult({ @@ -34,9 +34,6 @@ describe("mintClaim in HypercertClient", () => { }); beforeEach(async () => { - readSpy.resetBehavior(); - readSpy.resetHistory(); - writeSpy.resetBehavior(); writeSpy.resetHistory(); @@ -92,7 +89,7 @@ describe("mintClaim in HypercertClient", () => { }); expect.fail("Should throw Error"); } catch (e) { - expect((e as Error).message).to.match(/.Cannot convert FALSE_VALUE to a BigInt/); + expect(e).to.be.instanceOf(ContractFunctionExecutionError); } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion diff --git a/sdk/test/client/split.merge.test.ts b/sdk/test/client/split.merge.test.ts index 8c4f2a16..f963b8c2 100644 --- a/sdk/test/client/split.merge.test.ts +++ b/sdk/test/client/split.merge.test.ts @@ -2,15 +2,14 @@ import sinon from "sinon"; import HypercertClient from "../../src/client"; -import { HypercertMinterAbi } from "@hypercerts-org/contracts"; import { publicClient, walletClient } from "../helpers"; -import { encodeFunctionResult, isHex, parseAbi } from "viem"; +import { ContractFunctionExecutionError, isHex, toHex } from "viem"; describe("splitClaimUnits in HypercertClient", () => { const wallet = walletClient; - const userAddress = wallet.account.address; + const userAddress = wallet.account?.address; - let readSpy = sinon.stub(publicClient, "request"); + let readSpy = sinon.stub(publicClient, "readContract"); let writeSpy = sinon.stub(walletClient, "writeContract"); const client = new HypercertClient({ @@ -21,24 +20,6 @@ describe("splitClaimUnits in HypercertClient", () => { const fractionId = 9868188640707215440437863615521278132232n; - const ownerOfResult = encodeFunctionResult({ - abi: parseAbi(HypercertMinterAbi), - functionName: "ownerOf", - result: [userAddress], - }); - - const unitsOfResult = encodeFunctionResult({ - abi: parseAbi(HypercertMinterAbi), - functionName: "unitsOf", - result: [300n], - }); - - const splitFractionResult = encodeFunctionResult({ - abi: parseAbi(HypercertMinterAbi), - functionName: "splitFraction", - result: [], - }); - beforeEach(async () => { readSpy.resetBehavior(); readSpy.resetHistory(); @@ -52,8 +33,8 @@ describe("splitClaimUnits in HypercertClient", () => { }); it("allows for a hypercert fractions to be splitted over value", async () => { - readSpy = readSpy.onFirstCall().resolves(ownerOfResult).onSecondCall().resolves(unitsOfResult); - writeSpy = writeSpy.resolves(splitFractionResult); + readSpy = readSpy.onFirstCall().resolves(userAddress).onSecondCall().resolves(300n); + writeSpy = writeSpy.resolves(toHex(420)); expect(client.readonly).toBe(false); @@ -69,22 +50,22 @@ describe("splitClaimUnits in HypercertClient", () => { it("allows for a hypercert fractions to be splitted over value with override params", async () => { readSpy = readSpy .onFirstCall() - .resolves(ownerOfResult) + .resolves(userAddress) .onSecondCall() - .resolves(unitsOfResult) + .resolves(300n) .onThirdCall() - .resolves(ownerOfResult) + .resolves(userAddress) .onCall(3) - .resolves(unitsOfResult); + .resolves(300n); - writeSpy = writeSpy.resolves(splitFractionResult); + writeSpy = writeSpy.resolves(toHex(420)); expect(client.readonly).toBe(false); try { await client.splitFractionUnits(fractionId, [100n, 200n], { gasLimit: "FALSE_VALUE" as unknown as bigint }); } catch (e) { - expect((e as Error).message).toMatch(/Cannot convert FALSE_VALUE to a BigInt/); + expect(e instanceof ContractFunctionExecutionError).toBeTruthy(); } const hash = await client.splitFractionUnits(fractionId, [100n, 200n], { gasLimit: 12300000n }); diff --git a/sdk/test/evaluations/evaluator.test.ts b/sdk/test/evaluations/evaluator.test.ts index 2533be55..780c20d2 100644 --- a/sdk/test/evaluations/evaluator.test.ts +++ b/sdk/test/evaluations/evaluator.test.ts @@ -25,7 +25,7 @@ describe("HypercertEvaluator", () => { describe("submitEvaluation", () => { it("should throw an error for unexpected evaluation source", async () => { const evaluation = { - creator: signer.address, + creator: signer?.address, evaluationSource: { type: "invalid", }, @@ -68,7 +68,7 @@ describe("HypercertEvaluator", () => { sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: null }); sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN: null }); - const evaluation: HypercertEvaluationSchema = getEvaluationData({ creator: signer.address }); + const evaluation: HypercertEvaluationSchema = getEvaluationData({ creator: signer?.address }); const readonlyEvaluator = new HypercertEvaluator({ id: 5, diff --git a/sdk/test/helpers.ts b/sdk/test/helpers.ts index c249702a..a35aedb1 100644 --- a/sdk/test/helpers.ts +++ b/sdk/test/helpers.ts @@ -5,7 +5,7 @@ import { HypercertMetadata } from "../src"; import { AllowlistEntry, DuplicateEvaluation, HypercertEvaluationSchema, SimpleTextEvaluation } from "../src/types"; import { formatHypercertData } from "../src/utils/formatter"; import { Chain, foundry } from "viem/chains"; -import { PublicClient, createPublicClient, createTestClient, createWalletClient, http } from "viem"; +import { PublicClient, WalletClient, createPublicClient, createTestClient, createWalletClient, http } from "viem"; import * as HypercertMinter from "./resources/HypercertMinter.json"; import mockMetadata from "./res/mockMetadata"; import mockData from "./res/mockData"; @@ -62,7 +62,7 @@ export const publicClient: PublicClient = createPublicClient({ transport: http(), }); -export const walletClient = createWalletClient({ +export const walletClient: WalletClient = createWalletClient({ chain: anvil, transport: http(), account: faker.finance.ethereumAddress() as `0x${string}`, From b40fbe85ffa53ba9617d6924de2cf5bb092151e9 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Sat, 4 Nov 2023 23:57:23 +0100 Subject: [PATCH 30/49] chore(bump): sdk 0.9.1-viem --- sdk/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/package.json b/sdk/package.json index 24f20f0b..2558fadb 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@hypercerts-org/sdk", - "version": "0.9.0-viem", + "version": "0.9.1-viem", "description": "SDK for hypercerts protocol", "repository": "git@github.com:hypercerts-org/hypercerts.git", "author": "Hypercerts team", From 67a40529be27c56926846087565110917e3251dd Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Sun, 5 Nov 2023 00:35:39 +0100 Subject: [PATCH 31/49] feat(fe): update FE to use SDK 0.9.1 --- frontend/components/blueprint-create.tsx | 487 ------------------ frontend/components/config.tsx | 7 +- .../contribution-blueprint-create.tsx | 28 - frontend/hooks/hypercerts-client.ts | 24 +- frontend/lib/config.ts | 11 +- frontend/lib/parsing.ts | 14 +- frontend/next.config.mjs | 1 + frontend/package.json | 2 +- frontend/plasmic-init.ts | 25 - pnpm-lock.yaml | 68 +-- 10 files changed, 37 insertions(+), 630 deletions(-) delete mode 100644 frontend/components/blueprint-create.tsx delete mode 100644 frontend/components/contribution-blueprint-create.tsx diff --git a/frontend/components/blueprint-create.tsx b/frontend/components/blueprint-create.tsx deleted file mode 100644 index 876b6a6c..00000000 --- a/frontend/components/blueprint-create.tsx +++ /dev/null @@ -1,487 +0,0 @@ -import { useAccountLowerCase } from "../hooks/account"; -import { useMintBlueprintToRegistry } from "../hooks/createBlueprintInRegistry"; -import { useListRegistries } from "../hooks/list-registries"; -import { parseListFromString } from "../lib/parsing"; -import { useConfetti } from "./confetti"; -import { useContractModal } from "./contract-interaction-dialog-context"; -import { DATE_INDEFINITE, DateIndefinite, FormContext } from "./forms"; -import { formatHypercertData } from "@hypercerts-org/sdk"; -import { DataProvider } from "@plasmicapp/loader-nextjs"; -import dayjs from "dayjs"; -import { Formik, FormikProps } from "formik"; -import html2canvas from "html2canvas"; -import _ from "lodash"; -import { useRouter } from "next/router"; -import qs from "qs"; -import React, { ReactNode } from "react"; -import { toast } from "react-toastify"; -import * as Yup from "yup"; - -/** - * Constants - */ -const FORM_SELECTOR = "currentForm"; -const IMAGE_SELECTOR = "hypercertimage"; -export const NAME_MIN_LENGTH = 2; -export const NAME_MAX_LENGTH = 50; - -export const DESCRIPTION_MIN_LENGTH = 20; -export const DESCRIPTION_MAX_LENGTH = 1500; - -export const DEFAULT_NUM_FRACTIONS = 10000; -export const DEFAULT_HYPERCERT_VERSION = "0.0.1"; - -//const DEFAULT_TIME = dayjs().format("YYYY-MM-DD"); -const DEFAULT_TIME = dayjs(); -const DEFAULT_FORM_DATA: BlueprintCreateFormData = { - registryId: "", - minterAddress: "", - name: "", - description: "", - externalLink: "", - logoUrl: "", - //logoImage: null, - bannerUrl: "", - //bannerImage: null, - impactScopes: ["all"] as string[], - //impactTimeStart: DEFAULT_TIME.format("YYYY-MM-DD"), - impactTimeEnd: DEFAULT_TIME.format("YYYY-MM-DD"), - workScopes: "", - workTimeStart: DEFAULT_TIME.format("YYYY-MM-DD"), - workTimeEnd: DEFAULT_TIME.format("YYYY-MM-DD"), - rights: ["Public Display"] as string[], - contributors: "", - agreeContributorsConsent: false, - agreeTermsConditions: false, - // Hidden - backgroundColor: "", - backgroundVectorArt: "", - metadataProperties: "", -}; - -interface BlueprintCreateFormData { - registryId: string; - minterAddress: string; - name: string; - description: string; - externalLink: string; - logoUrl: string; - //logoImage: File | null; - bannerUrl: string; - //bannerImage: File | null; - impactScopes: string[]; - //impactTimeStart?: string; - impactTimeEnd?: string | DateIndefinite; - workScopes: string; - workTimeStart?: string; - workTimeEnd?: string; - rights: string[]; - contributors: string; - agreeContributorsConsent: boolean; - agreeTermsConditions: boolean; - // Hidden - backgroundColor: string; - backgroundVectorArt: string; - metadataProperties: string; -} - -/** - * Generic utility function to check for valid URLs - * - We should probably move this to common.ts or util.ts - * @param value - * @param opts - * @returns - */ -const isValidUrl = ( - value: any, - opts: { - emptyAllowed?: boolean; - ipfsAllowed?: boolean; - }, -) => { - // Check empty, null, or undefined - if (opts.emptyAllowed && !value) { - return true; - } else if (!value) { - return false; - } - - // Check IPFS - const isIpfsUrl = value.match(/^(ipfs):\/\//); - if (opts.ipfsAllowed && isIpfsUrl) { - return true; - } - - try { - const urlSchema = Yup.string().url(); - urlSchema.validateSync(value); - return true; - } catch (e) { - return false; - } -}; - -/** - * Converts raw form data to a query string - * @param values - * @returns - */ -const formDataToQueryString = (values: Record) => { - // We will serialize our Dayjs objects - const formatDate = (key: string) => { - if (values[key] === DATE_INDEFINITE) { - values[key] = DATE_INDEFINITE; - } else if (values[key] && values[key].format) { - values[key] = values[key].format("YYYY-MM-DD"); - } - }; - ["impactTimeStart", "impactTimeEnd", "workTimeStart", "workTimeEnd"].forEach( - formatDate, - ); - const filteredValues = _.chain(values).pickBy().value(); - return qs.stringify(filteredValues); -}; - -/** - * Converts a query string into raw form data - * @param query - * @returns - */ -const queryStringToFormData = (query?: string) => { - const rawValues = qs.parse(query ?? ""); - const parseValue = (v: any) => { - return v === DATE_INDEFINITE ? DATE_INDEFINITE : dayjs(v as string); - }; - const values = { - ...rawValues, - // we need to parse dates to match the expected types - //impactTimeStart: parseValue(rawValues["impactTimeStart"]), - impactTimeEnd: parseValue(rawValues["impactTimeEnd"]), - workTimeStart: parseValue(rawValues["workTimeStart"]), - workTimeEnd: parseValue(rawValues["workTimeEnd"]), - }; - return values as any; -}; - -/** - * Form validation rules - */ -const ValidationSchema = Yup.object().shape({ - registryId: Yup.string().required("Required"), - minterAddress: Yup.string().required("Required"), - name: Yup.string() - .min(NAME_MIN_LENGTH, `Name must be at least ${NAME_MIN_LENGTH} characters`) - .max(NAME_MAX_LENGTH, `Name must be at most ${NAME_MAX_LENGTH} characters`) - .required("Required"), - description: Yup.string() - .min( - DESCRIPTION_MIN_LENGTH, - `Description must be at least ${DESCRIPTION_MIN_LENGTH} characters`, - ) - .max( - DESCRIPTION_MAX_LENGTH, - `Description must be at most ${DESCRIPTION_MAX_LENGTH} characters`, - ) - .required("Required"), - externalLink: Yup.string().test( - "valid uri", - "Please enter a valid URL", - (value) => - isValidUrl(value, { - emptyAllowed: true, - ipfsAllowed: true, - }), - ), - logoUrl: Yup.string().test("valid uri", "Please enter a valid URL", (value) => - isValidUrl(value, { - emptyAllowed: true, - ipfsAllowed: false, - }), - ), - bannerUrl: Yup.string().test( - "valid uri", - "Please enter a valid URL", - (value) => - isValidUrl(value, { - emptyAllowed: true, - ipfsAllowed: false, - }), - ), - impactScopes: Yup.array().min(1, "Please choose at least 1 item"), - impactTimeEnd: Yup.lazy((val: any) => { - switch (typeof val) { - case "string": - return Yup.string(); - default: - return Yup.date().when("workTimeStart", (workTimeStart) => { - return Yup.date().min( - workTimeStart, - "End date must be after start date", - ); - }); - } - }), - workScopes: Yup.string() - .required("Required") - .min( - NAME_MIN_LENGTH, - `Work scopes must be at least ${NAME_MIN_LENGTH} characters`, - ) - .test("no duplicates", "Please remove duplicate items", (value) => { - if (!value) { - return true; - } - const items = parseListFromString(value, { lowercase: "all" }); - const dedup = parseListFromString(value, { - lowercase: "all", - deduplicate: true, - }); - return _.isEqual(items, dedup); - }), - workTimeEnd: Yup.date().when("workTimeStart", (workTimeStart) => { - return Yup.date().min(workTimeStart, "End date must be after start date"); - }), - rights: Yup.array().min(1), - contributors: Yup.string() - .required("Required") - .test("no duplicates", "Please remove duplicate items", (value) => { - if (!value) { - return true; - } - const items = parseListFromString(value, { lowercase: "all" }); - const dedup = parseListFromString(value, { - lowercase: "all", - deduplicate: true, - }); - return _.isEqual(items, dedup); - }), - agreeContributorsConsent: Yup.boolean().oneOf( - [true], - "You must get the consent of contributors before creating", - ), - agreeTermsConditions: Yup.boolean().oneOf( - [true], - "You must agree to the terms and conditions", - ), -}); - -/** - * Hypercert creation form logic using Formik - * - For the actual layout of form elements, - * we assume it's passed in via the `children` prop. - * - Use the form elements defined in `./forms.tsx` - * - Make sure that there is a form element with a `fieldName` - * for each field in HypercertCreateFormData - */ -export interface HypercertCreateFormProps { - className?: string; // Plasmic CSS class - children?: ReactNode; // Form elements -} - -export function BlueprintCreateForm(props: HypercertCreateFormProps) { - const { data: registries = [] } = useListRegistries(); - const registryOptions = registries.map((r: any) => `${r.name} - ${r.id}`); - const { className, children } = props; - const { address } = useAccountLowerCase(); - const { push } = useRouter(); - const { hideModal } = useContractModal(); - const confetti = useConfetti(); - - // Query string - const [initialQuery, setInitialQuery] = React.useState( - undefined, - ); - // Load the querystring into React state only once on initial page load - React.useEffect(() => { - if (!initialQuery) { - window.location.hash.startsWith("#") - ? setInitialQuery(window.location.hash.slice(1)) - : setInitialQuery(window.location.hash); - } - }, [initialQuery]); - - const onComplete = async () => { - hideModal(); - confetti && - (await confetti.addConfetti({ - emojis: ["🌈", "⚡️", "💥", "✨", "💫", "🌸"], - })); - push("/app/dashboard"); - }; - - const { mutate: createBlueprint, isLoading: createBlueprintPending } = - useMintBlueprintToRegistry({ - onComplete, - }); - - return ( -
- { - // console.log(values); - if (typeof initialQuery !== "undefined") { - // The useEffect has run already, so it's safe to just update the query string directly - //const querystring = formDataToQueryString(values); - //const path = `${window.location.pathname}#${querystring}`; - //window.history.pushState(null, "", path); - } - }} - initialValues={{ - ...DEFAULT_FORM_DATA, - ...queryStringToFormData(initialQuery), - }} - enableReinitialize - onSubmit={async (values, { setSubmitting }) => { - const image = await exportAsImage(IMAGE_SELECTOR); - const metaData = formatValuesToMetaData( - values, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - address!, - image, - ); - console.log(`Metadata(valid=${metaData.valid}): `, metaData.data); - if (metaData.data) { - const registryId = values.registryId.split(" - ")[1]; - //return; // Used for testing - - if (!registryId) { - toast("Error creating blueprint. Please contact the team.", { - type: "error", - }); - console.error("Registry ID not found"); - return; - } - createBlueprint({ - registryId, - value: formDataToQueryString(values), - minterAddress: values.minterAddress, - }); - } else { - toast("Error creating hypercert. Please contact the team.", { - type: "error", - }); - console.error("SDK formatting errors: ", metaData.errors); - } - - if (!createBlueprintPending) { - setSubmitting(false); - } - }} - > - {(formikProps: FormikProps) => ( - - -
{ - e.preventDefault(); - console.log("Submitting form..."); - console.log("Form values: ", formikProps.values); - console.log("Form errors: ", formikProps.errors); - formikProps.handleSubmit(); - }} - > - {children} -
-
-
- )} -
-
- ); -} - -const formatValuesToMetaData = ( - val: BlueprintCreateFormData, - address: string, - image?: string, -) => { - // Split contributor names and addresses. - // - make sure addresses are always lower case - const contributorNamesAndAddresses = parseListFromString(val.contributors, { - lowercase: "addresses", - }); - // Split the work scopes - const workScopes = parseListFromString(val.workScopes); - - // Mint certificate using contract - // NOTE: we set the times to be UNIX time (seconds since the epoch) - // but Date.getTime() returns milliseconds since the epoch - // NOTE: we are fixing the impactTimeStart to be the same as workTimeStart - const impactTimeframeStart = val.workTimeStart - ? new Date(val.workTimeStart).getTime() / 1000 - : 0; - /** - const impactTimeframeStart = val.impactTimeStart - ? new Date(val.impactTimeStart).getTime() / 1000 - : 0; - */ - const impactTimeframeEnd = - val.impactTimeEnd !== "indefinite" && val.impactTimeEnd !== undefined - ? new Date(val.impactTimeEnd).getTime() / 1000 - : 0; - const workTimeframeStart = val.workTimeStart - ? new Date(val.workTimeStart).getTime() / 1000 - : 0; - const workTimeframeEnd = val.workTimeEnd - ? new Date(val.workTimeEnd).getTime() / 1000 - : 0; - - let properties = []; - if (val.metadataProperties) { - try { - properties = JSON.parse(val.metadataProperties); - } catch (e) { - console.warn( - `Unable to parse metadataProperties: ${val.metadataProperties}`, - ); - } - } - - return formatHypercertData({ - name: val.name, - description: val.description, - external_url: val.externalLink, - image: image ?? "", - contributors: contributorNamesAndAddresses, - workTimeframeStart, - workTimeframeEnd, - impactTimeframeStart, - impactTimeframeEnd, - workScope: workScopes, - impactScope: val.impactScopes, - rights: val.rights, - version: DEFAULT_HYPERCERT_VERSION, - properties: properties, - excludedImpactScope: [], - excludedRights: [], - excludedWorkScope: [], - }); -}; - -const exportAsImage = async (id: string) => { - const el = document.getElementById(id); - if (!el) { - return; - } - const canvas = await html2canvas(el, { - logging: true, - backgroundColor: null, - //useCORS: true, - proxy: "https://cors-proxy.hypercerts.workers.dev/", - imageTimeout: 0, - }); - const image = canvas.toDataURL("image/png", 1.0); - return image; -}; diff --git a/frontend/components/config.tsx b/frontend/components/config.tsx index 5cad0317..bdd293e0 100644 --- a/frontend/components/config.tsx +++ b/frontend/components/config.tsx @@ -7,8 +7,8 @@ const PLASMIC_DATA_KEY = "Config"; interface ConfigData { domain: string; - chainId: number; - graphUrl: string; + chainId?: number; + graphUrl?: string; supabaseTable: string; } @@ -20,9 +20,10 @@ export interface ConfigProps { export function Config(props: ConfigProps) { const { className, children } = props; const { client: hypercertClient } = useHypercertClient(); + const data: ConfigData = { domain: DOMAIN, - chainId: hypercertClient._config.chainId, + chainId: Number(hypercertClient._config.chainId), graphUrl: hypercertClient._config.graphUrl, supabaseTable: SUPABASE_TABLE, }; diff --git a/frontend/components/contribution-blueprint-create.tsx b/frontend/components/contribution-blueprint-create.tsx deleted file mode 100644 index 8ca28c1a..00000000 --- a/frontend/components/contribution-blueprint-create.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { useListRegistries } from "../hooks/list-registries"; -import { Button, Divider } from "@mui/material"; -import { useState } from "react"; -import { AddRegistryDialog } from "./add-registry-dialog"; - -export const ContributionBlueprintCreate = () => { - const { data } = useListRegistries(); - const [showAddRegistryDialog, setShowAddRegistryDialog] = useState(false); - return ( -
- - {data?.map((registry: any) => ( -
-

{registry.name}

-

{registry.description}

-

{registry.owner_address}

- -
- ))} - setShowAddRegistryDialog(false)} - /> -
- ); -}; diff --git a/frontend/hooks/hypercerts-client.ts b/frontend/hooks/hypercerts-client.ts index 5d1fba60..9f892c82 100644 --- a/frontend/hooks/hypercerts-client.ts +++ b/frontend/hooks/hypercerts-client.ts @@ -4,7 +4,6 @@ import { DEFAULT_CHAIN_ID, NFT_STORAGE_TOKEN, WEB3_STORAGE_TOKEN, - OVERRIDE_GRAPH_URL, CONTRACT_ADDRESS, UNSAFE_FORCE_OVERRIDE_CONFIG, } from "../lib/config"; @@ -12,16 +11,13 @@ import { HypercertClient, HypercertClientConfig } from "@hypercerts-org/sdk"; import { useWalletClient, useNetwork } from "wagmi"; const clientConfig: Partial = { - id: DEFAULT_CHAIN_ID, + id: DEFAULT_CHAIN_ID ? Number(DEFAULT_CHAIN_ID) : 5, nftStorageToken: NFT_STORAGE_TOKEN, web3StorageToken: WEB3_STORAGE_TOKEN, }; +// TODO - make overrides explicit in loading config function loadOverridingConfig(clientConfig: Partial) { - if (OVERRIDE_GRAPH_URL) { - clientConfig.graphUrl = OVERRIDE_GRAPH_URL; - } - if (CONTRACT_ADDRESS) { clientConfig.contractAddress = CONTRACT_ADDRESS; } @@ -33,9 +29,7 @@ function loadOverridingConfig(clientConfig: Partial) { return clientConfig; } -loadOverridingConfig(clientConfig); - -const defaultClient = new HypercertClient(clientConfig); +const defaultClient = new HypercertClient(loadOverridingConfig(clientConfig)); export const useHypercertClient = () => { const { chain } = useNetwork(); @@ -53,13 +47,13 @@ export const useHypercertClient = () => { if (chain?.id && !walletClientLoading && !isError && walletClient) { setIsLoading(true); - let config: Partial = { - id: chain.id, - walletClient, - }; - config = loadOverridingConfig(config); try { - const client = new HypercertClient(config); + const config: Partial = { + id: chain.id, + walletClient, + }; + + const client = new HypercertClient(loadOverridingConfig(config)); setClient(client); } catch (e) { console.error(e); diff --git a/frontend/lib/config.ts b/frontend/lib/config.ts index a30134c6..5ceac794 100644 --- a/frontend/lib/config.ts +++ b/frontend/lib/config.ts @@ -12,12 +12,7 @@ export const DOMAIN = requireEnv( export const isProduction = DOMAIN === "hypercerts.org"; -export const DEFAULT_CHAIN_ID = parseInt( - requireEnv( - process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID, - "NEXT_PUBLIC_DEFAULT_CHAIN_ID", - ), -); +export const DEFAULT_CHAIN_ID = process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID; export const CONTRACT_ADDRESS = process.env.NEXT_PUBLIC_CONTRACT_ADDRESS; @@ -53,7 +48,3 @@ export const SUPABASE_TABLE = requireEnv( export const UNSAFE_FORCE_OVERRIDE_CONFIG = process.env.NEXT_PUBLIC_UNSAFE_FORCE_OVERRIDE_CONFIG == "1"; - -export const OVERRIDE_CHAIN_NAME = process.env.NEXT_PUBLIC_CHAIN_NAME; - -export const OVERRIDE_GRAPH_URL = process.env.NEXT_PUBLIC_GRAPH_URL; diff --git a/frontend/lib/parsing.ts b/frontend/lib/parsing.ts index e7444a9c..cefc9b17 100644 --- a/frontend/lib/parsing.ts +++ b/frontend/lib/parsing.ts @@ -30,9 +30,12 @@ export function parseAllowlistCsv( // Get the addresses and units from the CSV const csvData = rawData.map((row: any) => ({ address: row["address"].trim().toLowerCase(), - units: parseInt(row["fractions"].trim(), 10), + units: BigInt((row["fractions"].trim(), 10)), })); - const csvTotalSupply = csvData.reduce((accum, curr) => accum + curr.units, 0); + const csvTotalSupply = csvData.reduce( + (accum, curr) => accum + curr.units, + 0n, + ); if (csvTotalSupply <= 0) { throw new InvalidDataError("Did not find any valid rows"); } @@ -53,11 +56,12 @@ export function parseAllowlistCsv( } // Combine CSV data with manually added addresses const csvTotalPercentage = 1.0 - addTotalPercentage; - const totalSupply = csvTotalSupply / csvTotalPercentage; + const totalSupply = csvTotalSupply / BigInt(csvTotalPercentage); + // TODO risk over overflow on units - casting bigint to number const data = csvData.concat( add.map((x) => ({ address: x.address.trim().toLowerCase(), - units: Math.floor(totalSupply * x.percentage), + units: BigInt(Math.floor(Number(totalSupply) * x.percentage)), })), ); @@ -69,7 +73,7 @@ export function parseAllowlistCsv( // Deduplicate const groups = _.groupBy(data, (x) => x.address); const addressToUnits = _.mapValues(groups, (x) => - x.reduce((accum, curr) => accum + curr.units, 0), + x.reduce((accum, curr) => accum + curr.units, 0n), ); const result = _.toPairs(addressToUnits).map(([address, units]) => ({ diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index beb093bd..c8d52715 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -15,6 +15,7 @@ const nextConfig = { config.resolve.fallback = { fs: false, net: false, tls: false }; return config; }, + transpilePackages: ["@hypercerts-org/sdk"], }; export default withSentryConfig( diff --git a/frontend/package.json b/frontend/package.json index b6113d6e..70923e1e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,7 +25,7 @@ "@graphprotocol/client-cli": "^2.2.16", "@hypercerts-org/contracts": "0.9.0", "@hypercerts-org/observabletreemap": "workspace: *", - "@hypercerts-org/sdk": "0.9.0-viem", + "@hypercerts-org/sdk": "0.9.1-viem", "@mui/icons-material": "^5.11.9", "@mui/material": "^5.11.2", "@mui/x-date-pickers": "^5.0.12", diff --git a/frontend/plasmic-init.ts b/frontend/plasmic-init.ts index c722eca3..42c167c4 100644 --- a/frontend/plasmic-init.ts +++ b/frontend/plasmic-init.ts @@ -1,9 +1,7 @@ -import { BlueprintCreateForm } from "./components/blueprint-create"; import { BurnFractionButton } from "./components/burn-fraction-button"; import ClaimAllFractionsButton from "./components/claim-all-fractions-button"; import { ClientGrid } from "./components/client-grid"; import { Config } from "./components/config"; -import { ContributionBlueprintCreate } from "./components/contribution-blueprint-create"; import { DEFAULT_TEST_DATA } from "./components/dapp-state"; import { FormField, @@ -240,29 +238,6 @@ PLASMIC.registerComponent(HypercertCreateForm, { importPath: "./components/hypercert-create", }); -PLASMIC.registerComponent(BlueprintCreateForm, { - name: "BlueprintCreateForm", - description: "Create a blueprint", - props: { - children: { - type: "slot", - defaultValue: { - type: "text", - value: "Placeholder", - }, - }, - }, - providesData: true, - importPath: "./components/blueprint-create", -}); - -PLASMIC.registerComponent(ContributionBlueprintCreate, { - name: "ContributionBlueprintCreate", - description: "Create a contribution blueprint", - importPath: "./components/contribution-blueprint-create", - props: {}, -}); - PLASMIC.registerComponent(FormError, { name: "FormError", description: "Displays the error associated with fieldName", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30fd5c5f..ff4015c7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -312,8 +312,8 @@ importers: specifier: 'workspace: *' version: link:../vendor/observabletreemap '@hypercerts-org/sdk': - specifier: 0.9.0-viem - version: 0.9.0-viem(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) + specifier: 0.9.1-viem + version: 0.9.1-viem(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) '@mui/icons-material': specifier: ^5.11.9 version: 5.14.15(@mui/material@5.14.15)(@types/react@18.2.33)(react@18.2.0) @@ -796,6 +796,7 @@ packages: /@adraffy/ens-normalize@1.9.0: resolution: {integrity: sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ==} + dev: true /@adraffy/ens-normalize@1.9.4: resolution: {integrity: sha512-UK0bHA7hh9cR39V+4gl2/NnBBjoXIxkuWAPCaY4X7fbH4L/azIi7ilWOCjMUYfpJgraLUAqkRi2BqrjME8Rynw==} @@ -7518,8 +7519,8 @@ packages: - utf-8-validate dev: false - /@hypercerts-org/sdk@0.9.0-viem(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): - resolution: {integrity: sha512-o6zmVQj0w3UnpDk+V8yn6z/mPrW1vfzN8FU22wdulESWf6IrLb09yo75V6srS5PxowC3ggiKfYflBZYpocJWvw==} + /@hypercerts-org/sdk@0.9.1-viem(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): + resolution: {integrity: sha512-OWGHBiONrSOJ0si3fBpaLpF8qdNJFQXgPekhKyE2rVWs76YfqrJzMjCxODsi0lq59JCGb1TyuAq28GLASvG3aw==} dependencies: '@ethereum-attestation-service/eas-sdk': 1.2.2-beta.0(ts-node@10.9.1)(typescript@5.1.6) '@ethersproject/abstract-signer': 5.7.0 @@ -7547,7 +7548,7 @@ packages: loglevel: 1.8.1 mime: 3.0.0 nft.storage: 7.1.1(node-fetch@3.3.2) - viem: 1.5.3(typescript@5.1.6)(zod@3.22.4) + viem: 1.18.4(typescript@5.1.6)(zod@3.22.4) web3.storage: 4.5.5(node-fetch@3.3.2) transitivePeerDependencies: - '@envelop/core' @@ -9566,6 +9567,7 @@ packages: resolution: {integrity: sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==} dependencies: '@noble/hashes': 1.3.0 + dev: true /@noble/curves@1.1.0: resolution: {integrity: sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==} @@ -9587,6 +9589,7 @@ packages: /@noble/hashes@1.3.0: resolution: {integrity: sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==} + dev: true /@noble/hashes@1.3.1: resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} @@ -11083,6 +11086,7 @@ packages: '@noble/curves': 1.0.0 '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 + dev: true /@scure/bip32@1.3.1: resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==} @@ -11111,6 +11115,7 @@ packages: dependencies: '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 + dev: true /@scure/bip39@1.2.1: resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} @@ -13138,17 +13143,6 @@ packages: typescript: 5.1.6 dev: true - /@wagmi/chains@1.6.0(typescript@5.1.6): - resolution: {integrity: sha512-5FRlVxse5P4ZaHG3GTvxwVANSmYJas1eQrTBHhjxVtqXoorm0aLmCHbhmN8Xo1yu09PaWKlleEvfE98yH4AgIw==} - peerDependencies: - typescript: '>=5.0.4' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - typescript: 5.1.6 - dev: false - /@wagmi/connectors@2.7.0(react@18.2.0)(typescript@5.1.6)(viem@1.18.4)(zod@3.22.4): resolution: {integrity: sha512-1KOL0HTJl5kzSC/YdKwFwiokr6poUQn1V/tcT0TpG3iH2x0lSM7FTkvCjVVY/6lKzTXrLlo9y2aE7AsOPnkvqg==} peerDependencies: @@ -14113,21 +14107,6 @@ packages: typescript: 5.1.6 zod: 3.22.4 - /abitype@0.9.3(typescript@5.1.6)(zod@3.22.4): - resolution: {integrity: sha512-dz4qCQLurx97FQhnb/EIYTk/ldQ+oafEDUqC0VVIeQS1Q48/YWt/9YNfMmp9SLFqN41ktxny3c8aYxHjmFIB/w==} - peerDependencies: - typescript: '>=5.0.4' - zod: ^3 >=3.19.1 - peerDependenciesMeta: - typescript: - optional: true - zod: - optional: true - dependencies: - typescript: 5.1.6 - zod: 3.22.4 - dev: false - /abitype@0.9.8(typescript@5.1.6)(zod@3.22.4): resolution: {integrity: sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==} peerDependencies: @@ -23289,6 +23268,7 @@ packages: ws: '*' dependencies: ws: 8.12.0 + dev: true /isomorphic-ws@5.0.0(ws@8.13.0): resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} @@ -33287,31 +33267,6 @@ packages: - zod dev: false - /viem@1.5.3(typescript@5.1.6)(zod@3.22.4): - resolution: {integrity: sha512-oImpSDDvm8Y72qxXV0pCAGAqQLYgo8YENdz9EKS8ExnnOJLascpex4LNazNyp9cksjm3ORpVpbqGMr9Cy1z2mg==} - peerDependencies: - typescript: '>=5.0.4' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@adraffy/ens-normalize': 1.9.0 - '@noble/curves': 1.0.0 - '@noble/hashes': 1.3.0 - '@scure/bip32': 1.3.0 - '@scure/bip39': 1.2.0 - '@types/ws': 8.5.8 - '@wagmi/chains': 1.6.0(typescript@5.1.6) - abitype: 0.9.3(typescript@5.1.6)(zod@3.22.4) - isomorphic-ws: 5.0.0(ws@8.12.0) - typescript: 5.1.6 - ws: 8.12.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - zod - dev: false - /vite-node@0.28.5(@types/node@18.18.7): resolution: {integrity: sha512-LmXb9saMGlrMZbXTvOveJKwMTBTNUH66c8rJnQ0ZPNX+myPEol64+szRzXtV5ORb0Hb/91yq+/D3oERoyAt6LA==} engines: {node: '>=v14.16.0'} @@ -34169,6 +34124,7 @@ packages: optional: true utf-8-validate: optional: true + dev: true /ws@8.13.0: resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} From 53e45aeacd664b5fa24f1de7b431039b272edca1 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 12:22:33 +0100 Subject: [PATCH 32/49] chore(cleanup): code cleanup SDK --- sdk/src/client.ts | 187 ++++++++++++++--------------------- sdk/src/evaluations/index.ts | 4 +- sdk/src/indexer/utils.ts | 2 +- sdk/src/storage.ts | 29 ++++-- sdk/src/types/client.ts | 26 ++--- sdk/src/utils/adapters.ts | 2 +- sdk/src/utils/config.ts | 7 +- sdk/src/utils/resolvers.ts | 4 +- sdk/src/validator/index.ts | 2 +- sdk/test/client.test.ts | 14 +-- 10 files changed, 117 insertions(+), 160 deletions(-) diff --git a/sdk/src/client.ts b/sdk/src/client.ts index f4491a68..b6db6762 100644 --- a/sdk/src/client.ts +++ b/sdk/src/client.ts @@ -1,18 +1,9 @@ import { HypercertMinterAbi } from "@hypercerts-org/contracts"; import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; -import { - ByteArray, - GetContractReturnType, - Hex, - PublicClient, - WalletClient, - WriteContractReturnType, - getContract, - parseAbi, -} from "viem"; -import HypercertEvaluator from "./evaluations/index"; +import { ByteArray, GetContractReturnType, Hex, PublicClient, WalletClient, getContract, parseAbi } from "viem"; +import HypercertEvaluator from "./evaluations"; import HypercertIndexer from "./indexer"; -import HypercertsStorage from "./storage.js"; +import HypercertsStorage from "./storage"; import { AllowlistEntry, ClientError, @@ -31,19 +22,18 @@ import { validateAllowlist, validateMetaData, verifyMerkleProof, verifyMerklePro /** * Hypercerts client factory * @dev Creates a Hypercerts client instance - * @notice The client is readonly if no signer is set or if the contract address is not set + * @notice The client is readonly if the storage is readonly (no nft.storage/web3.storage keys) + * or if nog walletClient was found. * @param config - Hypercerts client configuration - * @param storage - Hypercerts storage object */ export default class HypercertClient implements HypercertClientInterface { readonly _config; private _storage: HypercertsStorage; // TODO better handling readonly. For now not needed since we don't use this class; - private _evaluator: HypercertEvaluator | undefined; + private _evaluator?: HypercertEvaluator; private _indexer: HypercertIndexer; - //TODO added the TypedDataSigner since that's needed for EAS signing. Will this work on front-end? private _publicClient: PublicClient; - private _walletClient: WalletClient | undefined; + private _walletClient?: WalletClient; readonly: boolean; /** @@ -63,9 +53,7 @@ export default class HypercertClient implements HypercertClientInterface { this._indexer = new HypercertIndexer(this._config); - this.readonly = this._config.readOnly || this._storage.readonly; - - this.readonly = !this._walletClient || this._storage.readonly; + this.readonly = this._config.readOnly || this._storage.readonly || !this._walletClient; if (this.readonly) { logger.warn("HypercertsClient is in readonly mode", "client"); @@ -122,14 +110,8 @@ export default class HypercertClient implements HypercertClientInterface { totalUnits: bigint, transferRestriction: TransferRestrictions, overrides?: SupportedOverrides, - ): Promise => { - this.checkWritable(); - - if (!this._walletClient) { - throw new ClientError("Could not detect account; sending transactions not allowed."); - } - - const operator = this._walletClient; + ) => { + const { account } = this.getWallet(); // validate metadata const { valid, errors } = validateMetaData(metaData); @@ -142,13 +124,13 @@ export default class HypercertClient implements HypercertClientInterface { const { request } = await this._publicClient.simulateContract({ functionName: "mintClaim", - account: operator.account, - args: [operator.account?.address, totalUnits, cid, transferRestriction], + account, + args: [account?.address, totalUnits, cid, transferRestriction], ...this.getContractConfig(), ...this.getCleanedOverrides(overrides), }); - return operator.writeContract(request); + return this.submitRequest(request); }; /** @@ -168,13 +150,7 @@ export default class HypercertClient implements HypercertClientInterface { transferRestriction: TransferRestrictions, overrides?: SupportedOverrides, ) => { - this.checkWritable(); - - if (!this._walletClient) { - throw new ClientError("Could not connect to wallet; sending transactions not allowed."); - } - - const operator = this._walletClient; + const { account } = this.getWallet(); // validate allowlist const { valid: validAllowlist, errors: allowlistErrors } = validateAllowlist(allowList, totalUnits); @@ -193,20 +169,18 @@ export default class HypercertClient implements HypercertClientInterface { const tree = StandardMerkleTree.of(tuples, ["address", "uint256"]); const cidMerkle = await this.storage.storeData(JSON.stringify(tree.dump())); - metaData.allowList = cidMerkle; - // store metadata on IPFS - const cid = await this.storage.storeMetadata(metaData); + const cid = await this.storage.storeMetadata({ ...metaData, allowList: cidMerkle }); const { request } = await this._publicClient.simulateContract({ functionName: "createAllowlist", - account: operator.account, - args: [operator.account?.address, totalUnits, tree.root, cid, transferRestriction], + account, + args: [account?.address, totalUnits, tree.root, cid, transferRestriction], ...this.getContractConfig(), ...this.getCleanedOverrides(overrides), }); - return operator.writeContract(request); + return this.submitRequest(request); }; /** @@ -218,24 +192,18 @@ export default class HypercertClient implements HypercertClientInterface { * @returns Contract transaction */ splitFractionUnits = async (fractionId: bigint, fractions: bigint[], overrides?: SupportedOverrides) => { - this.checkWritable(); - - if (!this._walletClient) { - throw new ClientError("Could not connect to wallet; sending transactions not allowed."); - } - - const operator = this._walletClient; + const { account } = this.getWallet(); const readContract = getContract({ ...this.getContractConfig(), publicClient: this._publicClient, }); - const fractionOwner = await readContract.read.ownerOf([fractionId]); + const fractionOwner = (await readContract.read.ownerOf([fractionId])) as `0x${string}`; const totalUnits = (await readContract.read.unitsOf([fractionId])) as bigint; - if ((fractionOwner as `0x${string}`).toLowerCase() !== operator.account?.address.toLowerCase()) - throw new ClientError("Claim is not owned by the signer", { signer: operator.account?.address, fractionOwner }); + if (fractionOwner.toLowerCase() !== account?.address.toLowerCase()) + throw new ClientError("Claim is not owned by the signer", { signer: account?.address, fractionOwner }); // check if the sum of the fractions is equal to the total units const sumFractions = fractions.reduce((a, b) => a + b, 0n); @@ -244,13 +212,13 @@ export default class HypercertClient implements HypercertClientInterface { const { request } = await this._publicClient.simulateContract({ functionName: "splitFraction", - account: operator.account, - args: [operator.account.address, fractionId, fractions], + account, + args: [account.address, fractionId, fractions], ...this.getContractConfig(), ...this.getCleanedOverrides(overrides), }); - return operator.writeContract(request); + return this.submitRequest(request); }; /** @@ -260,12 +228,7 @@ export default class HypercertClient implements HypercertClientInterface { * @returns Contract transaction */ mergeFractionUnits = async (fractionIds: bigint[], overrides?: SupportedOverrides) => { - this.checkWritable(); - - if (!this._walletClient) { - throw new ClientError("Could not connect to wallet; sending transactions not allowed."); - } - const operator = this._walletClient; + const { account } = this.getWallet(); const readContract = getContract({ ...this.getContractConfig(), @@ -273,25 +236,27 @@ export default class HypercertClient implements HypercertClientInterface { }); const fractions = await Promise.all( - fractionIds.map(async (id) => ({ id, owner: await readContract.read.ownerOf([id]) })), + fractionIds.map(async (id) => ({ id, owner: (await readContract.read.ownerOf([id])) as `0x${string}` })), ); - if (fractions.some((c) => (c.owner as `0x${string}`).toLowerCase() !== operator.account?.address.toLowerCase())) { - const invalidIds = fractions.filter((c) => c.owner !== operator.account?.address).map((c) => c.id); - throw new ClientError("One or more claims are not owned by the signer", { - signer: operator.account?.address, - invalidIds, + + const notOwned = fractions.filter((fraction) => fraction.owner.toLowerCase() !== account?.address.toLowerCase()); + + if (notOwned.length > 0) { + throw new ClientError("One or more fractions are not owned by the signer", { + signer: account?.address, + notOwned, }); } const { request } = await this._publicClient.simulateContract({ functionName: "mergeFractions", - account: operator.account, - args: [operator.account?.address, fractionIds], + account, + args: [account?.address, fractionIds], ...this.getContractConfig(), ...this.getCleanedOverrides(overrides), }); - return operator.writeContract(request); + return this.submitRequest(request); }; /** @@ -301,36 +266,28 @@ export default class HypercertClient implements HypercertClientInterface { * @returns Contract transaction */ burnClaimFraction = async (claimId: bigint, overrides?: SupportedOverrides) => { - this.checkWritable(); - - if (!this._walletClient) { - throw new ClientError("Could not connect to wallet; sending transactions not allowed."); - } - - const operator = this._walletClient; + const { account } = this.getWallet(); const readContract = getContract({ ...this.getContractConfig(), publicClient: this._publicClient, }); - const claimOwner = await readContract.read.ownerOf([claimId]); + const claimOwner = (await readContract.read.ownerOf([claimId])) as `0x${string}`; - if ((claimOwner as `0x${string}`).toLowerCase() !== operator.account?.address.toLowerCase()) { - console.log("claimOwner", claimOwner); - console.log("operator.account?.address", operator.account?.address); - throw new ClientError("Claim is not owned by the signer", { signer: operator.account?.address, claimOwner }); + if (claimOwner.toLowerCase() !== account?.address.toLowerCase()) { + throw new ClientError("Claim is not owned by the signer", { signer: account?.address, claimOwner }); } const { request } = await this._publicClient.simulateContract({ functionName: "burnFraction", - account: operator.account?.address, - args: [operator.account?.address, claimId], + account, + args: [account?.address, claimId], ...this.getContractConfig(), ...this.getCleanedOverrides(overrides), }); - return operator.writeContract(request); + return this.submitRequest(request); }; /** @@ -349,20 +306,14 @@ export default class HypercertClient implements HypercertClientInterface { root?: Hex | ByteArray, overrides?: SupportedOverrides, ) => { - this.checkWritable(); - - if (!this._walletClient) { - throw new ClientError("Could not connect to wallet; sending transactions not allowed."); - } - - const operator = this._walletClient; + const { account } = this.getWallet(); //verify the proof using the OZ merkle tree library if (root && root.length > 0) { - if (!operator.account?.address) throw new InvalidOrMissingError("No wallet address found, are you connected?"); + if (!account?.address) throw new InvalidOrMissingError("No wallet address found, are you connected?"); verifyMerkleProof( root.toString(), - operator.account?.address, + account?.address, units, proof.map((p) => p.toString()), ); @@ -370,13 +321,13 @@ export default class HypercertClient implements HypercertClientInterface { const { request } = await this._publicClient.simulateContract({ functionName: "mintClaimFromAllowlist", - account: operator.account, - args: [operator.account?.address, proof, claimId, units], + account, + args: [account?.address, proof, claimId, units], ...this.getContractConfig(), ...this.getCleanedOverrides(overrides), }); - return operator.writeContract(request); + return this.submitRequest(request); }; /** @@ -396,21 +347,15 @@ export default class HypercertClient implements HypercertClientInterface { roots?: (Hex | ByteArray)[], overrides?: SupportedOverrides, ) => { - this.checkWritable(); - - if (!this._walletClient) { - throw new ClientError("Could not connect to wallet; sending transactions not allowed."); - } - - const operator = this._walletClient; + const { account } = this.getWallet(); //verify the proof using the OZ merkle tree library if (roots && roots.length > 0) { - if (!operator.account?.address) throw new InvalidOrMissingError("No wallet address found, are you connected?"); + if (!account?.address) throw new InvalidOrMissingError("No wallet address found, are you connected?"); verifyMerkleProofs( roots.map((r) => r.toString()), - operator.account?.address, + account?.address, units, proofs.map((p) => p.map((p) => p.toString())), ); @@ -418,16 +363,18 @@ export default class HypercertClient implements HypercertClientInterface { const { request } = await this._publicClient.simulateContract({ functionName: "batchMintClaimsFromAllowlists", - account: operator.account, - args: [operator.account?.address, proofs, claimIds, units], + account, + args: [account?.address, proofs, claimIds, units], ...this.getContractConfig(), ...this.getCleanedOverrides(overrides), }); - return operator.writeContract(request); + return this.submitRequest(request); }; private getContractConfig = () => { + if (!this.config?.contractAddress) throw new ClientError("No contract address found", { config: this.config }); + return getContract({ address: this.config.contractAddress as `0x${string}`, abi: parseAbi(HypercertMinterAbi), @@ -444,9 +391,23 @@ export default class HypercertClient implements HypercertClientInterface { return Object.fromEntries(Object.entries(_overrides).filter(([_, value]) => value !== undefined)); }; - private checkWritable = () => { + private getWallet = () => { + if (!this._walletClient) { + throw new ClientError("Could not connect to wallet; sending transactions not allowed.", { client: this }); + } if (this.readonly) throw new ClientError("Client is readonly", { client: this }); - return true; + return { walletClient: this._walletClient, account: this._walletClient.account }; + }; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private submitRequest = async (request: any) => { + const hash = this._walletClient?.writeContract(request); + + if (!hash) { + throw new ClientError("Something went wrong when executing request", { request, hash }); + } + + return hash; }; } diff --git a/sdk/src/evaluations/index.ts b/sdk/src/evaluations/index.ts index 33d501d8..44f13c23 100644 --- a/sdk/src/evaluations/index.ts +++ b/sdk/src/evaluations/index.ts @@ -1,9 +1,9 @@ -import { isAddress } from "ethers/lib/utils.js"; +import { isAddress } from "viem"; //eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore import { CIDString } from "nft.storage"; -import HypercertsStorage from "../storage.js"; +import HypercertsStorage from "../storage"; import { HypercertClientConfig, HypercertEvaluationSchema, MalformedDataError } from "../types"; export interface EvaluatorInterface { diff --git a/sdk/src/indexer/utils.ts b/sdk/src/indexer/utils.ts index d016677e..28329336 100644 --- a/sdk/src/indexer/utils.ts +++ b/sdk/src/indexer/utils.ts @@ -1,4 +1,4 @@ -import { QueryParams } from "../types/index.js"; +import { QueryParams } from "../types"; export const defaultQueryParams: QueryParams = { orderDirections: "desc", diff --git a/sdk/src/storage.ts b/sdk/src/storage.ts index 3ae94db1..c501e640 100644 --- a/sdk/src/storage.ts +++ b/sdk/src/storage.ts @@ -38,17 +38,17 @@ export default class HypercertsStorage implements HypercertStorageInterface { const { nftStorageToken } = getNftStorageToken(overrides); const { web3StorageToken } = getWeb3StorageToken(overrides); - if (!nftStorageToken) { - logger.warn(`NFT Storage API key is missing or invalid: ${nftStorageToken}}`); - } - - if (!web3StorageToken) { - logger.warn(`Web3 Storage API key is missing or invalid: ${web3StorageToken}`); - } - if (!nftStorageToken || !web3StorageToken) { logger.warn("HypercertsStorage is read only", "storage"); this.readonly = true; + + if (!nftStorageToken) { + logger.warn(`NFT Storage API key is missing or invalid: ${nftStorageToken}}`); + } + + if (!web3StorageToken) { + logger.warn(`Web3 Storage API key is missing or invalid: ${web3StorageToken}`); + } } else { this.nftStorageClient = new NFTStorage({ token: nftStorageToken || "" }); this.web3StorageClient = new Web3Storage({ web3StorageToken }); @@ -58,10 +58,14 @@ export default class HypercertsStorage implements HypercertStorageInterface { getFromIPFS = async (cidOrIpfsUri: string) => { const nftStorageGatewayLink = this.getNftStorageGatewayUri(cidOrIpfsUri); + const web3StorageGatewayLink = this.getWeb3StorageGatewayUri(cidOrIpfsUri); logger.debug(`Getting metadata ${cidOrIpfsUri} at ${nftStorageGatewayLink}`); - //TODO add fallback methods - const res = await axios.get(nftStorageGatewayLink); + const res = await axios.get(nftStorageGatewayLink, { timeout: 5000 }).catch(() => { + logger.debug(`${nftStorageGatewayLink} timed out.`); + logger.debug(`Getting metadata ${cidOrIpfsUri} at ${web3StorageGatewayLink}`); + return axios.get(web3StorageGatewayLink, { timeout: 5000 }); + }); if (!res || !res.data) { throw new StorageError(`Failed to get ${cidOrIpfsUri}`); @@ -188,4 +192,9 @@ export default class HypercertsStorage implements HypercertStorageInterface { const NFT_STORAGE_IPFS_GATEWAY = "https://nftstorage.link/ipfs/{cid}"; return NFT_STORAGE_IPFS_GATEWAY.replace("{cid}", getCid(cidOrIpfsUri)); }; + + getWeb3StorageGatewayUri = (cidOrIpfsUri: string) => { + const WEB3_STORAGE_IPFS_GATEWAY = "https://w3s.link/ipfs/{cid}"; + return WEB3_STORAGE_IPFS_GATEWAY.replace("{cid}", getCid(cidOrIpfsUri)); + }; } diff --git a/sdk/src/types/client.ts b/sdk/src/types/client.ts index 13c31e59..22beb6e2 100644 --- a/sdk/src/types/client.ts +++ b/sdk/src/types/client.ts @@ -7,15 +7,7 @@ import HypercertIndexer from "../indexer"; import { AllowlistEntry, TransferRestrictions } from "./hypercerts"; import { HypercertMetadata } from "./metadata"; -import { - ByteArray, - Chain, - Hex, - PublicClient, - WalletClient, - WriteContractReturnType, - GetContractReturnType, -} from "viem"; +import { ByteArray, Chain, Hex, PublicClient, WalletClient, Abi } from "viem"; export type SupportedChainIds = 5 | 10 | 42220 | 11155111; export type SupportedOverrides = { @@ -126,7 +118,7 @@ export interface HypercertClientState { storage: HypercertStorageInterface; /** The indexer used by the client. */ indexer: HypercertIndexer; - contract: GetContractReturnType; + contract: { abi: Abi; address?: `0x${string}` }; } /** @@ -144,7 +136,7 @@ export interface HypercertClientMethods { metaData: HypercertMetadata, totalUnits: bigint, transferRestriction: TransferRestrictions, - ) => Promise; + ) => Promise<`0x${string}`>; /** * Creates a new allowlist and mints a new claim with the allowlist. @@ -159,7 +151,7 @@ export interface HypercertClientMethods { metaData: HypercertMetadata, totalUnits: bigint, transferRestriction: TransferRestrictions, - ) => Promise; + ) => Promise<`0x${string}`>; /** * Splits a claim into multiple fractions. @@ -167,21 +159,21 @@ export interface HypercertClientMethods { * @param newFractions The number of units for each fraction. * @returns A Promise that resolves to the transaction receipt */ - splitFractionUnits: (fractionId: bigint, fractions: bigint[]) => Promise; + splitFractionUnits: (fractionId: bigint, fractions: bigint[]) => Promise<`0x${string}`>; /** * Merges multiple claim fractions into a single claim. * @param fractionIds The IDs of the claim fractions to merge. * @returns A Promise that resolves to the transaction receipt */ - mergeFractionUnits: (fractionIds: bigint[]) => Promise; + mergeFractionUnits: (fractionIds: bigint[]) => Promise<`0x${string}`>; /** * Burns a claim fraction. * @param fractionId The ID of the claim fraction to burn. * @returns A Promise that resolves to the transaction receipt */ - burnClaimFraction: (fractionId: bigint) => Promise; + burnClaimFraction: (fractionId: bigint) => Promise<`0x${string}`>; /** * Mints a claim fraction from an allowlist. @@ -194,7 +186,7 @@ export interface HypercertClientMethods { claimId: bigint, units: bigint, proof: (Hex | ByteArray)[], - ) => Promise; + ) => Promise<`0x${string}`>; /** * Batch mints a claim fraction from an allowlist @@ -210,5 +202,5 @@ export interface HypercertClientMethods { claimIds: bigint[], units: bigint[], proofs: (Hex | ByteArray)[][], - ) => Promise; + ) => Promise<`0x${string}`>; } diff --git a/sdk/src/utils/adapters.ts b/sdk/src/utils/adapters.ts index ed1e3fcf..9c33a336 100644 --- a/sdk/src/utils/adapters.ts +++ b/sdk/src/utils/adapters.ts @@ -1,6 +1,6 @@ import { providers } from "ethers"; import { PublicClient, HttpTransport, WalletClient } from "viem"; -import logger from "./logger.js"; +import logger from "./logger"; import { Signer, TypedDataSigner } from "@ethersproject/abstract-signer"; export function publicClientToProvider(publicClient: PublicClient) { diff --git a/sdk/src/utils/config.ts b/sdk/src/utils/config.ts index 67ea94df..85a04fc2 100644 --- a/sdk/src/utils/config.ts +++ b/sdk/src/utils/config.ts @@ -9,7 +9,7 @@ import { SupportedChainIds, UnsupportedChainError, } from "../types"; -import logger from "./logger.js"; +import logger from "./logger"; import { createPublicClient, http, isAddress } from "viem"; import { deployments } from "../../src"; @@ -125,11 +125,6 @@ const getContractAddress = (overrides: Partial) => { } return { contractAddress: overrides.contractAddress }; } - const contractAddress = process.env.CONTRACT_ADDRESS; - if (contractAddress && !isAddress(contractAddress)) { - throw new InvalidOrMissingError("Invalid contract address.", { contractAddress }); - } - return contractAddress ? { contractAddress } : undefined; }; const getGraphUrl = (overrides: Partial) => { diff --git a/sdk/src/utils/resolvers.ts b/sdk/src/utils/resolvers.ts index d22d832a..0641e565 100644 --- a/sdk/src/utils/resolvers.ts +++ b/sdk/src/utils/resolvers.ts @@ -2,9 +2,9 @@ import { Resolvers } from "../../.graphclient"; export const resolvers: Resolvers = { Claim: { - chainName: (root, args, context) => context.chainName || "hypercerts-testnet", // The value we provide in the config + chainName: (root, args, context) => context.chainName, // The value we provide in the config }, ClaimToken: { - chainName: (root, args, context) => context.chainName || "hypercerts-testnet", // The value we provide in the config + chainName: (root, args, context) => context.chainName, // The value we provide in the config }, }; diff --git a/sdk/src/validator/index.ts b/sdk/src/validator/index.ts index 2a9a8e25..e843fd84 100644 --- a/sdk/src/validator/index.ts +++ b/sdk/src/validator/index.ts @@ -11,7 +11,7 @@ import { HypercertMetadata, MintingError, SimpleTextEvaluation, -} from "../types/index.js"; +} from "../types"; import { isAddress } from "viem"; const ajv = new Ajv({ allErrors: true }); // options can be passed, e.g. {allErrors: true} diff --git a/sdk/test/client.test.ts b/sdk/test/client.test.ts index 42112026..85e8c566 100644 --- a/sdk/test/client.test.ts +++ b/sdk/test/client.test.ts @@ -63,7 +63,7 @@ describe("HypercertClient setup tests", () => { expect(e).to.be.instanceOf(ClientError); const error = e as ClientError; - expect(error.message).to.eq("Client is readonly"); + expect(error.message).to.eq("Could not connect to wallet; sending transactions not allowed."); expect(error.payload?.client instanceof HypercertClient).to.be.true; } @@ -80,7 +80,7 @@ describe("HypercertClient setup tests", () => { expect(e).to.be.instanceOf(ClientError); const error = e as ClientError; - expect(error.message).to.eq("Client is readonly"); + expect(error.message).to.eq("Could not connect to wallet; sending transactions not allowed."); expect(error.payload?.client).to.be.instanceOf(HypercertClient); } @@ -95,7 +95,7 @@ describe("HypercertClient setup tests", () => { expect(e).to.be.instanceOf(ClientError); const error = e as ClientError; - expect(error.message).to.eq("Client is readonly"); + expect(error.message).to.eq("Could not connect to wallet; sending transactions not allowed."); expect(error.payload?.client).to.be.instanceOf(HypercertClient); } @@ -109,7 +109,7 @@ describe("HypercertClient setup tests", () => { expect(e).to.be.instanceOf(ClientError); const error = e as ClientError; - expect(error.message).to.eq("Client is readonly"); + expect(error.message).to.eq("Could not connect to wallet; sending transactions not allowed."); expect(error.payload?.client).to.be.instanceOf(HypercertClient); } @@ -123,7 +123,7 @@ describe("HypercertClient setup tests", () => { expect(e).to.be.instanceOf(ClientError); const error = e as ClientError; - expect(error.message).to.eq("Client is readonly"); + expect(error.message).to.eq("Could not connect to wallet; sending transactions not allowed."); expect(error.payload?.client).to.be.instanceOf(HypercertClient); } @@ -140,7 +140,7 @@ describe("HypercertClient setup tests", () => { expect(e).to.be.instanceOf(ClientError); const error = e as ClientError; - expect(error.message).to.eq("Client is readonly"); + expect(error.message).to.eq("Could not connect to wallet; sending transactions not allowed."); expect(error.payload?.client).to.be.instanceOf(HypercertClient); } @@ -157,7 +157,7 @@ describe("HypercertClient setup tests", () => { expect(e).to.be.instanceOf(ClientError); const error = e as ClientError; - expect(error.message).to.eq("Client is readonly"); + expect(error.message).to.eq("Could not connect to wallet; sending transactions not allowed."); expect(error.payload?.client).to.be.instanceOf(HypercertClient); } }); From 5302e323a8091fbfae00547f782a0b29906dff56 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 12:24:35 +0100 Subject: [PATCH 33/49] chore(bump): sdk version bump --- sdk/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/package.json b/sdk/package.json index 2558fadb..e78056b7 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@hypercerts-org/sdk", - "version": "0.9.1-viem", + "version": "1.0.0-alpha.0", "description": "SDK for hypercerts protocol", "repository": "git@github.com:hypercerts-org/hypercerts.git", "author": "Hypercerts team", From f54e1f42e85dcae0839fa93877ced973a1ad25ab Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 12:32:24 +0100 Subject: [PATCH 34/49] chore(fe): update SDK dep version --- frontend/package.json | 2 +- pnpm-lock.yaml | 131 ++++++++++++++++++++++-------------------- 2 files changed, 71 insertions(+), 62 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 70923e1e..c9e0ee14 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,7 +25,7 @@ "@graphprotocol/client-cli": "^2.2.16", "@hypercerts-org/contracts": "0.9.0", "@hypercerts-org/observabletreemap": "workspace: *", - "@hypercerts-org/sdk": "0.9.1-viem", + "@hypercerts-org/sdk": "1.0.0-alpha.0", "@mui/icons-material": "^5.11.9", "@mui/material": "^5.11.2", "@mui/x-date-pickers": "^5.0.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ff4015c7..2cc8bf90 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -304,7 +304,7 @@ importers: version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) '@graphprotocol/client-cli': specifier: ^2.2.16 - version: 2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) + version: 2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) '@hypercerts-org/contracts': specifier: 0.9.0 version: 0.9.0(typescript@5.1.6) @@ -312,8 +312,8 @@ importers: specifier: 'workspace: *' version: link:../vendor/observabletreemap '@hypercerts-org/sdk': - specifier: 0.9.1-viem - version: 0.9.1-viem(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) + specifier: 1.0.0-alpha.0 + version: 1.0.0-alpha.0(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) '@mui/icons-material': specifier: ^5.11.9 version: 5.14.15(@mui/material@5.14.15)(@types/react@18.2.33)(react@18.2.0) @@ -5757,24 +5757,6 @@ packages: '@trufflesuite/bigint-buffer': 1.1.9 dev: true - /@graphprotocol/client-add-source-name@1.0.20(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): - resolution: {integrity: sha512-JJ++BVg4fhNCbLej105uHpabZesLsCSo9p43ZKSTT1VUdbuZtarzyIHC3uUmbvCfWQMVTCJEBZGx4l41oooOiw==} - peerDependencies: - '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 - '@graphql-tools/delegate': ^9.0.32 - '@graphql-tools/utils': ^9.2.1 - '@graphql-tools/wrap': ^9.4.2 - graphql: ^15.2.0 || ^16.0.0 - dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) - graphql: 16.8.1 - lodash: 4.17.21 - tslib: 2.6.2 - dev: false - /@graphprotocol/client-add-source-name@1.0.20(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): resolution: {integrity: sha512-JJ++BVg4fhNCbLej105uHpabZesLsCSo9p43ZKSTT1VUdbuZtarzyIHC3uUmbvCfWQMVTCJEBZGx4l41oooOiw==} peerDependencies: @@ -5812,7 +5794,7 @@ packages: tslib: 2.6.2 dev: true - /@graphprotocol/client-auto-pagination@1.1.18(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): + /@graphprotocol/client-auto-pagination@1.1.18(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): resolution: {integrity: sha512-p8eEyeBcqxCXLxC7CNgIhLSCd7bjiKToKnrwYPShVb26gIG2JdAmD3/mpjuR+QaMA4chN/EO5t+TGvq6KnFx9g==} peerDependencies: '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 @@ -5821,7 +5803,7 @@ packages: '@graphql-tools/wrap': ^9.4.2 graphql: ^15.2.0 || ^16.0.0 dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) @@ -5849,15 +5831,15 @@ packages: tslib: 2.6.2 dev: true - /@graphprotocol/client-auto-type-merging@1.0.25(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1): + /@graphprotocol/client-auto-type-merging@1.0.25(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1): resolution: {integrity: sha512-kpiX2s804mpP3EVL0EdJfxeHWBTdg6SglIyEvSZ5T1OWyGDeMhr19D+gVIAlo22/PiBUkBDd0JfqppLsliPZ1A==} peerDependencies: '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 '@graphql-tools/delegate': ^9.0.32 graphql: ^15.2.0 || ^16.0.0 dependencies: - '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) graphql: 16.8.1 tslib: 2.6.2 @@ -5907,19 +5889,19 @@ packages: tslib: 2.6.2 dev: true - /@graphprotocol/client-cli@2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): + /@graphprotocol/client-cli@2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): resolution: {integrity: sha512-PIi8rFibYZVup+0jb08399RmbGF1ZrqUe6RXzLtKZBT57OWIMWwsFvdJyUAdr8Y8f0rrMn6A+Oy4nP1lf3hc1g==} hasBin: true peerDependencies: graphql: ^15.2.0 || ^16.0.0 dependencies: - '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) - '@graphprotocol/client-auto-pagination': 1.1.18(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) - '@graphprotocol/client-auto-type-merging': 1.0.25(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) + '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) + '@graphprotocol/client-auto-pagination': 1.1.18(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) + '@graphprotocol/client-auto-type-merging': 1.0.25(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-block-tracking': 1.0.14(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-polling-live': 1.1.1(@envelop/core@3.0.6)(@graphql-tools/merge@8.4.2)(graphql@16.8.1) '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) - '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2) graphql: 16.8.1 tslib: 2.6.2 transitivePeerDependencies: @@ -6420,7 +6402,7 @@ packages: graphql: 16.8.1 path-browserify: 1.0.1 - /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2): + /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-1G2/1jkl1VPWhsZsUBwFQI5d9OxxEc+CMxy5ef0qI2WEXqIocOxMhEY53cc+tCSbuXR99rxos+KD/8Z6ZasaOQ==} peerDependencies: '@graphql-mesh/cross-helpers': ^0.3.4 @@ -6432,10 +6414,10 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) - '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/url-loader': 7.17.18(@types/node@18.18.7)(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -6663,7 +6645,7 @@ packages: graphql: 16.8.1 tslib: 2.6.2 - /@graphql-mesh/runtime@0.96.13(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + /@graphql-mesh/runtime@0.96.13(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-eZIW/gdEVLvCLEEae8e3lny7d89CFfDyu0Z0xu4yVEdYeVpG9Ki2mDYFHztusIIkZikecvdsoM9MZX6LYcPOkg==} engines: {node: '>=16.0.0'} peerDependencies: @@ -6679,8 +6661,8 @@ packages: '@envelop/graphql-jit': 8.0.1(@envelop/core@5.0.0)(graphql@16.8.1) '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) '@graphql-mesh/string-interpolation': 0.5.3(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/batch-delegate': 9.0.0(graphql@16.8.1) '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/executor': 1.2.0(graphql@16.8.1) @@ -6739,6 +6721,26 @@ packages: graphql: 16.8.1 tslib: 2.6.2 + /@graphql-mesh/store@0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-29lpMcvqS1DM9alUOCyj6he2V7ZzG/DZxkerRefT8Mo5FexwJZI3LeI0YHNSY9Cq0x8KzRoH1TWcTTN/1PDRRw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.4.1 + '@graphql-mesh/types': ^0.95.8 + '@graphql-mesh/utils': ^0.95.8 + '@graphql-tools/utils': ^9.2.1 || ^10.0.0 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-inspector/core': 5.0.1(graphql@16.8.1) + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + dev: false + /@graphql-mesh/store@0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-29lpMcvqS1DM9alUOCyj6he2V7ZzG/DZxkerRefT8Mo5FexwJZI3LeI0YHNSY9Cq0x8KzRoH1TWcTTN/1PDRRw==} engines: {node: '>=16.0.0'} @@ -6783,22 +6785,6 @@ packages: lodash.get: 4.4.2 tslib: 2.6.2 - /@graphql-mesh/transform-type-merging@0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-CUrqCMaEqO1LDusv59UPqmQju3f+LpEGxFu7CydMiIvbfKDDDrf8+dF3OVU7d/ZOMRxB6hR80JsQF0SVeXPCOQ==} - peerDependencies: - '@graphql-mesh/types': ^0.93.1 - '@graphql-mesh/utils': ^0.93.1 - graphql: '*' - tslib: ^2.4.0 - dependencies: - '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) - '@graphql-tools/stitching-directives': 2.3.34(graphql@16.8.1) - graphql: 16.8.1 - tslib: 2.6.2 - dev: false - /@graphql-mesh/transform-type-merging@0.93.1(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-CUrqCMaEqO1LDusv59UPqmQju3f+LpEGxFu7CydMiIvbfKDDDrf8+dF3OVU7d/ZOMRxB6hR80JsQF0SVeXPCOQ==} peerDependencies: @@ -6808,12 +6794,11 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/stitching-directives': 2.3.34(graphql@16.8.1) graphql: 16.8.1 tslib: 2.6.2 - dev: true /@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-113DuJzmR7aj2EMnLPu33ktCe5k7+Mk0BxFfmQViUH+mkr6i4JMsWvPKs9dTODSYuSuwvAZ90Vw2l3QyMrbFVA==} @@ -6870,6 +6855,30 @@ packages: tiny-lru: 8.0.2 tslib: 2.6.2 + /@graphql-mesh/utils@0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-gH2/kXvxMHVWMX8DppIIZpFfSUaoKDJ6eQHFoAAsdabGE+vLtVk0OEYqMGVGtD/8ZDFa/P6CmwXc6hBzoLY6Kg==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.4.1 + '@graphql-mesh/types': ^0.95.8 + '@graphql-tools/utils': ^9.2.1 || ^10.0.0 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) + '@graphql-mesh/string-interpolation': 0.5.3(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@whatwg-node/fetch': 0.9.14 + dset: 3.1.3 + graphql: 16.8.1 + js-yaml: 4.1.0 + lodash.get: 4.4.2 + lodash.topath: 4.5.2 + tiny-lru: 11.2.3 + tslib: 2.6.2 + /@graphql-mesh/utils@0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-gH2/kXvxMHVWMX8DppIIZpFfSUaoKDJ6eQHFoAAsdabGE+vLtVk0OEYqMGVGtD/8ZDFa/P6CmwXc6hBzoLY6Kg==} engines: {node: '>=16.0.0'} @@ -7519,8 +7528,8 @@ packages: - utf-8-validate dev: false - /@hypercerts-org/sdk@0.9.1-viem(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): - resolution: {integrity: sha512-OWGHBiONrSOJ0si3fBpaLpF8qdNJFQXgPekhKyE2rVWs76YfqrJzMjCxODsi0lq59JCGb1TyuAq28GLASvG3aw==} + /@hypercerts-org/sdk@1.0.0-alpha.0(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): + resolution: {integrity: sha512-qjPSmEI5MFDFSLrzxL7O+JIYrJHK6jh4qBxDwTgvQMQdBRWPQweYEkGwTZ4vYQvlN6gtTqu9WWk+73WF7D2oCQ==} dependencies: '@ethereum-attestation-service/eas-sdk': 1.2.2-beta.0(ts-node@10.9.1)(typescript@5.1.6) '@ethersproject/abstract-signer': 5.7.0 @@ -7531,10 +7540,10 @@ packages: '@graphql-mesh/graphql': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2) '@graphql-mesh/http': 0.96.14(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/runtime@0.96.13)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/merger-bare': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/runtime': 0.96.13(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/runtime': 0.96.13(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) '@hypercerts-org/contracts': 0.8.11 '@openzeppelin/merkle-tree': 1.0.5 From d467682125cac7a2b037063b4e89d00696d2dfbf Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 14:29:06 +0100 Subject: [PATCH 35/49] fix(sdk): chainId config --- frontend/lib/parsing.test.ts | 44 ++++++++-------- frontend/lib/parsing.ts | 7 ++- sdk/.graphclient/index.ts | 58 ++++++++++----------- sdk/.graphclient/schema.graphql | 4 +- sdk/.graphclientrc.yml | 6 +-- sdk/package.json | 2 +- sdk/src/client.ts | 20 ++++++-- sdk/src/constants.ts | 4 ++ sdk/src/indexer.ts | 7 +-- sdk/src/indexer/queries/claims.graphql | 6 +-- sdk/src/indexer/queries/fractions.graphql | 6 +-- sdk/src/storage.ts | 6 +-- sdk/src/types/client.ts | 4 +- sdk/src/utils/config.ts | 43 ++++------------ sdk/src/utils/resolvers.ts | 4 +- sdk/test/client.test.ts | 20 ++++---- sdk/test/client/allowlist.minting.test.ts | 4 +- sdk/test/client/burn.test.ts | 4 +- sdk/test/client/minting.test.ts | 4 +- sdk/test/client/split.merge.test.ts | 4 +- sdk/test/evaluations/evaluator.test.ts | 9 +--- sdk/test/storage.test.ts | 12 ----- sdk/test/utils/config.test.ts | 61 +++++++---------------- 23 files changed, 152 insertions(+), 187 deletions(-) diff --git a/frontend/lib/parsing.test.ts b/frontend/lib/parsing.test.ts index 2b14fe6f..f98ec4d1 100644 --- a/frontend/lib/parsing.test.ts +++ b/frontend/lib/parsing.test.ts @@ -11,9 +11,9 @@ describe("allowlist", () => { true, ); expect(resultDeduped).toEqual([ - { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 100 }, - { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50 }, - { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40 }, + { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 100n }, + { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50n }, + { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40n }, ]); const resultNotDeduped = parseAllowlistCsv( @@ -25,9 +25,9 @@ describe("allowlist", () => { false, ); expect(resultNotDeduped).toEqual([ - { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 100 }, - { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50 }, - { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40 }, + { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 100n }, + { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50n }, + { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40n }, ]); }); @@ -43,9 +43,9 @@ describe("allowlist", () => { true, ); expect(result).toEqual([ - { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 200 }, - { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50 }, - { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 80 }, + { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 200n }, + { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50n }, + { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 80n }, ]); }); @@ -61,11 +61,11 @@ describe("allowlist", () => { false, ); expect(result).toEqual([ - { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 100 }, - { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50 }, - { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40 }, - { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 100 }, - { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40 }, + { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 100n }, + { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50n }, + { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40n }, + { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 100n }, + { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40n }, ]); }); @@ -85,10 +85,10 @@ describe("allowlist", () => { ], ); expect(result).toEqual([ - { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 100 }, - { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50 }, - { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40 }, - { address: "0x22e4b9b003cc7b7149cf2135dfce2baddc7a534f", units: 570 }, + { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 100n }, + { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50n }, + { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40n }, + { address: "0x22e4b9b003cc7b7149cf2135dfce2baddc7a534f", units: 570n }, ]); }); @@ -112,10 +112,10 @@ describe("allowlist", () => { ], ); expect(result).toEqual([ - { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 290 }, - { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50 }, - { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40 }, - { address: "0x22e4b9b003cc7b7149cf2135dfce2baddc7a534f", units: 380 }, + { address: "0x20326e144532f17f76aca759e61e19af20a58ef3", units: 290n }, + { address: "0x15c7281842a45465b4cbb8f89111d99e36e5bab8", units: 50n }, + { address: "0x1cca19b823afa773b09708d94d2ee6ff96c60057", units: 40n }, + { address: "0x22e4b9b003cc7b7149cf2135dfce2baddc7a534f", units: 380n }, ]); }); diff --git a/frontend/lib/parsing.ts b/frontend/lib/parsing.ts index cefc9b17..ced8d3f4 100644 --- a/frontend/lib/parsing.ts +++ b/frontend/lib/parsing.ts @@ -56,12 +56,15 @@ export function parseAllowlistCsv( } // Combine CSV data with manually added addresses const csvTotalPercentage = 1.0 - addTotalPercentage; - const totalSupply = csvTotalSupply / BigInt(csvTotalPercentage); + + const percentageBigInt = BigInt(Math.floor(csvTotalPercentage * 100)); // convert percentage to BigInt + const creatorSupply = (csvTotalSupply * 100n) / percentageBigInt; // calculate total supply + // TODO risk over overflow on units - casting bigint to number const data = csvData.concat( add.map((x) => ({ address: x.address.trim().toLowerCase(), - units: BigInt(Math.floor(Number(totalSupply) * x.percentage)), + units: creatorSupply, })), ); diff --git a/sdk/.graphclient/index.ts b/sdk/.graphclient/index.ts index ea5a9a56..95f59d60 100644 --- a/sdk/.graphclient/index.ts +++ b/sdk/.graphclient/index.ts @@ -282,7 +282,7 @@ export type Claim = { creator?: Maybe; owner?: Maybe; totalUnits?: Maybe; - chainName: Scalars['String']; + graphName: Scalars['String']; }; export type ClaimToken = { @@ -291,7 +291,7 @@ export type ClaimToken = { claim: Claim; owner: Scalars['Bytes']; units: Scalars['BigInt']; - chainName: Scalars['String']; + graphName: Scalars['String']; }; export type ClaimToken_filter = { @@ -681,21 +681,21 @@ export type ResolversParentTypes = ResolversObject<{ export type entityDirectiveArgs = { }; -export type entityDirectiveResolver = DirectiveResolverFn; +export type entityDirectiveResolver = DirectiveResolverFn; export type subgraphIdDirectiveArgs = { id: Scalars['String']; }; -export type subgraphIdDirectiveResolver = DirectiveResolverFn; +export type subgraphIdDirectiveResolver = DirectiveResolverFn; export type derivedFromDirectiveArgs = { field: Scalars['String']; }; -export type derivedFromDirectiveResolver = DirectiveResolverFn; +export type derivedFromDirectiveResolver = DirectiveResolverFn; -export type QueryResolvers = ResolversObject<{ +export type QueryResolvers = ResolversObject<{ allowlist?: Resolver, ParentType, ContextType, RequireFields>; allowlists?: Resolver, ParentType, ContextType, RequireFields>; claim?: Resolver, ParentType, ContextType, RequireFields>; @@ -705,7 +705,7 @@ export type QueryResolvers, ParentType, ContextType, Partial>; }>; -export type SubscriptionResolvers = ResolversObject<{ +export type SubscriptionResolvers = ResolversObject<{ allowlist?: SubscriptionResolver, "allowlist", ParentType, ContextType, RequireFields>; allowlists?: SubscriptionResolver, "allowlists", ParentType, ContextType, RequireFields>; claim?: SubscriptionResolver, "claim", ParentType, ContextType, RequireFields>; @@ -715,7 +715,7 @@ export type SubscriptionResolvers, "_meta", ParentType, ContextType, Partial>; }>; -export type AllowlistResolvers = ResolversObject<{ +export type AllowlistResolvers = ResolversObject<{ id?: Resolver; root?: Resolver; claim?: Resolver; @@ -734,7 +734,7 @@ export interface BytesScalarConfig extends GraphQLScalarTypeConfig = ResolversObject<{ +export type ClaimResolvers = ResolversObject<{ id?: Resolver; creation?: Resolver; tokenID?: Resolver; @@ -743,17 +743,17 @@ export type ClaimResolvers, ParentType, ContextType>; owner?: Resolver, ParentType, ContextType>; totalUnits?: Resolver, ParentType, ContextType>; - chainName?: Resolver; + graphName?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }>; -export type ClaimTokenResolvers = ResolversObject<{ +export type ClaimTokenResolvers = ResolversObject<{ id?: Resolver; tokenID?: Resolver; claim?: Resolver; owner?: Resolver; units?: Resolver; - chainName?: Resolver; + graphName?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }>; @@ -761,21 +761,21 @@ export interface Int8ScalarConfig extends GraphQLScalarTypeConfig = ResolversObject<{ +export type _Block_Resolvers = ResolversObject<{ hash?: Resolver, ParentType, ContextType>; number?: Resolver; timestamp?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; }>; -export type _Meta_Resolvers = ResolversObject<{ +export type _Meta_Resolvers = ResolversObject<{ block?: Resolver; deployment?: Resolver; hasIndexingErrors?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }>; -export type Resolvers = ResolversObject<{ +export type Resolvers = ResolversObject<{ Query?: QueryResolvers; Subscription?: SubscriptionResolvers; Allowlist?: AllowlistResolvers; @@ -789,7 +789,7 @@ export type Resolvers; }>; -export type DirectiveResolvers = ResolversObject<{ +export type DirectiveResolvers = ResolversObject<{ entity?: entityDirectiveResolver; subgraphId?: subgraphIdDirectiveResolver; derivedFrom?: derivedFromDirectiveResolver; @@ -852,7 +852,7 @@ sources[0] = { handler: hypercertsHandler, transforms: hypercertsTransforms } -const additionalTypeDefs = [parse("extend type Claim {\n chainName: String!\n}\n\nextend type ClaimToken {\n chainName: String!\n}"),] as any[]; +const additionalTypeDefs = [parse("extend type Claim {\n graphName: String!\n}\n\nextend type ClaimToken {\n graphName: String!\n}"),] as any[]; additionalEnvelopPlugins[0] = await UsePollingLive({ ...({ "defaultInterval": 5000 @@ -968,7 +968,7 @@ export type ClaimsByOwnerQueryVariables = Exact<{ }>; -export type ClaimsByOwnerQuery = { claims: Array> }; +export type ClaimsByOwnerQuery = { claims: Array> }; export type RecentClaimsQueryVariables = Exact<{ orderDirection?: InputMaybe; @@ -977,14 +977,14 @@ export type RecentClaimsQueryVariables = Exact<{ }>; -export type RecentClaimsQuery = { claims: Array> }; +export type RecentClaimsQuery = { claims: Array> }; export type ClaimByIdQueryVariables = Exact<{ id: Scalars['ID']; }>; -export type ClaimByIdQuery = { claim?: Maybe> }; +export type ClaimByIdQuery = { claim?: Maybe> }; export type ClaimTokensByOwnerQueryVariables = Exact<{ owner?: InputMaybe; @@ -995,7 +995,7 @@ export type ClaimTokensByOwnerQueryVariables = Exact<{ export type ClaimTokensByOwnerQuery = { claimTokens: Array<( - Pick + Pick & { claim: Pick } )> }; @@ -1007,7 +1007,7 @@ export type ClaimTokensByClaimQueryVariables = Exact<{ }>; -export type ClaimTokensByClaimQuery = { claimTokens: Array> }; +export type ClaimTokensByClaimQuery = { claimTokens: Array> }; export type ClaimTokenByIdQueryVariables = Exact<{ claimTokenId: Scalars['ID']; @@ -1015,7 +1015,7 @@ export type ClaimTokenByIdQueryVariables = Exact<{ export type ClaimTokenByIdQuery = { claimToken?: Maybe<( - Pick + Pick & { claim: Pick } )> }; @@ -1028,7 +1028,7 @@ export const ClaimsByOwnerDocument = gql` first: $first orderDirection: $orderDirection ) { - chainName + graphName contract tokenID creator @@ -1042,7 +1042,7 @@ export const ClaimsByOwnerDocument = gql` export const RecentClaimsDocument = gql` query RecentClaims($orderDirection: OrderDirection, $first: Int, $skip: Int) { claims(orderDirection: $orderDirection, orderBy: creation, first: $first) { - chainName + graphName contract tokenID creator @@ -1056,7 +1056,7 @@ export const RecentClaimsDocument = gql` export const ClaimByIdDocument = gql` query ClaimById($id: ID!) { claim(id: $id) { - chainName + graphName contract tokenID creator @@ -1075,7 +1075,7 @@ export const ClaimTokensByOwnerDocument = gql` first: $first orderDirection: $orderDirection ) { - chainName + graphName id owner tokenID @@ -1097,7 +1097,7 @@ export const ClaimTokensByClaimDocument = gql` first: $first orderDirection: $orderDirection ) { - chainName + graphName id owner tokenID @@ -1108,7 +1108,7 @@ export const ClaimTokensByClaimDocument = gql` export const ClaimTokenByIdDocument = gql` query ClaimTokenById($claimTokenId: ID!) { claimToken(id: $claimTokenId) { - chainName + graphName id owner tokenID diff --git a/sdk/.graphclient/schema.graphql b/sdk/.graphclient/schema.graphql index 8694426f..56dc3bc8 100644 --- a/sdk/.graphclient/schema.graphql +++ b/sdk/.graphclient/schema.graphql @@ -281,7 +281,7 @@ type Claim { creator: Bytes owner: Bytes totalUnits: BigInt - chainName: String! + graphName: String! } type ClaimToken { @@ -290,7 +290,7 @@ type ClaimToken { claim: Claim! owner: Bytes! units: BigInt! - chainName: String! + graphName: String! } input ClaimToken_filter { diff --git a/sdk/.graphclientrc.yml b/sdk/.graphclientrc.yml index bf07ad3d..9087a374 100644 --- a/sdk/.graphclientrc.yml +++ b/sdk/.graphclientrc.yml @@ -8,10 +8,10 @@ sources: additionalTypeDefs: | extend type Claim { - chainName: String! + graphName: String! } extend type ClaimToken { - chainName: String! + graphName: String! } additionalResolvers: @@ -21,7 +21,7 @@ documents: - ./src/indexer/queries/*.graphql codegen: - contextType: "MeshContext & { graphUrl: string, chainName: string }" + contextType: "MeshContext & { graphUrl: string, graphName: string }" plugins: - pollingLive: diff --git a/sdk/package.json b/sdk/package.json index e78056b7..853c6f14 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@hypercerts-org/sdk", - "version": "1.0.0-alpha.0", + "version": "1.0.0-alpha.3", "description": "SDK for hypercerts protocol", "repository": "git@github.com:hypercerts-org/hypercerts.git", "author": "Hypercerts team", diff --git a/sdk/src/client.ts b/sdk/src/client.ts index b6db6762..63b24c01 100644 --- a/sdk/src/client.ts +++ b/sdk/src/client.ts @@ -20,11 +20,23 @@ import logger from "./utils/logger"; import { validateAllowlist, validateMetaData, verifyMerkleProof, verifyMerkleProofs } from "./validator"; /** - * Hypercerts client factory - * @dev Creates a Hypercerts client instance - * @notice The client is readonly if the storage is readonly (no nft.storage/web3.storage keys) - * or if nog walletClient was found. + * The `HypercertClient` is a core class in the hypercerts SDK, providing a high-level interface to interact with the hypercerts system. + * + * It encapsulates the logic for storage, evaluation, indexing, and wallet interactions, abstracting the complexity and providing a simple API for users. + * The client is read-only if the storage is read-only (no nft.storage/web3.storage keys) or if no walletClient was found. + * + * Here's an example of how to create a new instance of `HypercertClient`: + * + * ```typescript + * const config: Partial = { + * id: 5 + * }; + * + * const client = new HypercertClient(config); + * ``` + * * @param config - Hypercerts client configuration + * @dev Creates a Hypercerts client instance */ export default class HypercertClient implements HypercertClientInterface { readonly _config; diff --git a/sdk/src/constants.ts b/sdk/src/constants.ts index 691ad658..05307613 100644 --- a/sdk/src/constants.ts +++ b/sdk/src/constants.ts @@ -10,18 +10,22 @@ const DEFAULT_GRAPH_BASE_URL = "https://api.thegraph.com/subgraphs/name/hypercer const DEPLOYMENTS: { [key in SupportedChainIds]: Partial } = { 5: { contractAddress: "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", + graphName: "hypercerts-testnet", graphUrl: `${DEFAULT_GRAPH_BASE_URL}/hypercerts-testnet`, } as const, 10: { contractAddress: "0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07", + graphName: "hypercerts-optimism-mainnet", graphUrl: `${DEFAULT_GRAPH_BASE_URL}/hypercerts-optimism-mainnet`, } as const, 42220: { contractAddress: "0x16ba53b74c234c870c61efc04cd418b8f2865959", + graphName: "hypercerts-arbitrum", graphUrl: `${DEFAULT_GRAPH_BASE_URL}/hypercerts-celo`, }, 11155111: { contractAddress: "0xa16DFb32Eb140a6f3F2AC68f41dAd8c7e83C4941", + graphName: "hypercerts-sepolia", graphUrl: `${DEFAULT_GRAPH_BASE_URL}/hypercerts-sepolia`, } as const, }; diff --git a/sdk/src/indexer.ts b/sdk/src/indexer.ts index 5fea7ba7..c3438f45 100644 --- a/sdk/src/indexer.ts +++ b/sdk/src/indexer.ts @@ -1,6 +1,6 @@ import { getBuiltGraphSDK, Sdk as GraphClient } from "../.graphclient"; import { defaultQueryParams } from "./indexer/utils"; -import { HypercertIndexerInterface, QueryParams } from "./types"; +import { HypercertClientConfig, HypercertIndexerInterface, QueryParams } from "./types"; /** * A class that provides indexing functionality for Hypercerts. @@ -14,9 +14,10 @@ export default class HypercertIndexer implements HypercertIndexerInterface { * Creates a new instance of the `HypercertIndexer` class. * @param options The configuration options for the indexer. */ - constructor(options: { graphUrl?: string }) { + constructor(options: Partial) { this._graphClient = getBuiltGraphSDK({ - graphUrl: options.graphUrl || "https://api.thegraph.com/subgraphs/name/hypercerts-admin/hypercerts-testnet", + graphUrl: options.graphUrl, + graphName: options.graphName, }); } diff --git a/sdk/src/indexer/queries/claims.graphql b/sdk/src/indexer/queries/claims.graphql index 776ee260..9e143ae8 100644 --- a/sdk/src/indexer/queries/claims.graphql +++ b/sdk/src/indexer/queries/claims.graphql @@ -1,6 +1,6 @@ query ClaimsByOwner($owner: Bytes = "", $orderDirection: OrderDirection, $first: Int, $skip: Int) { claims(where: { owner: $owner }, skip: $skip, first: $first, orderDirection: $orderDirection) { - chainName + graphName contract tokenID creator @@ -13,7 +13,7 @@ query ClaimsByOwner($owner: Bytes = "", $orderDirection: OrderDirection, $first: query RecentClaims($orderDirection: OrderDirection, $first: Int, $skip: Int) { claims(orderDirection: $orderDirection, orderBy: creation, first: $first) { - chainName + graphName contract tokenID creator @@ -26,7 +26,7 @@ query RecentClaims($orderDirection: OrderDirection, $first: Int, $skip: Int) { query ClaimById($id: ID!) { claim(id: $id) { - chainName + graphName contract tokenID creator diff --git a/sdk/src/indexer/queries/fractions.graphql b/sdk/src/indexer/queries/fractions.graphql index 20eb8ad0..df07f421 100644 --- a/sdk/src/indexer/queries/fractions.graphql +++ b/sdk/src/indexer/queries/fractions.graphql @@ -1,6 +1,6 @@ query ClaimTokensByOwner($owner: Bytes = "", $orderDirection: OrderDirection, $first: Int, $skip: Int) { claimTokens(where: { owner: $owner }, skip: $skip, first: $first, orderDirection: $orderDirection) { - chainName + graphName id owner tokenID @@ -16,7 +16,7 @@ query ClaimTokensByOwner($owner: Bytes = "", $orderDirection: OrderDirection, $f query ClaimTokensByClaim($claimId: String!, $orderDirection: OrderDirection, $first: Int, $skip: Int) { claimTokens(where: { claim: $claimId }, skip: $skip, first: $first, orderDirection: $orderDirection) { - chainName + graphName id owner tokenID @@ -26,7 +26,7 @@ query ClaimTokensByClaim($claimId: String!, $orderDirection: OrderDirection, $fi query ClaimTokenById($claimTokenId: ID!) { claimToken(id: $claimTokenId) { - chainName + graphName id owner tokenID diff --git a/sdk/src/storage.ts b/sdk/src/storage.ts index c501e640..89d91a4d 100644 --- a/sdk/src/storage.ts +++ b/sdk/src/storage.ts @@ -35,8 +35,8 @@ export default class HypercertsStorage implements HypercertStorageInterface { * @param overrides The configuration overrides for the storage. */ constructor(overrides: Partial) { - const { nftStorageToken } = getNftStorageToken(overrides); - const { web3StorageToken } = getWeb3StorageToken(overrides); + const nftStorageToken = getNftStorageToken(overrides); + const web3StorageToken = getWeb3StorageToken(overrides); if (!nftStorageToken || !web3StorageToken) { logger.warn("HypercertsStorage is read only", "storage"); @@ -50,7 +50,7 @@ export default class HypercertsStorage implements HypercertStorageInterface { logger.warn(`Web3 Storage API key is missing or invalid: ${web3StorageToken}`); } } else { - this.nftStorageClient = new NFTStorage({ token: nftStorageToken || "" }); + this.nftStorageClient = new NFTStorage({ token: nftStorageToken.nftStorageToken || "" }); this.web3StorageClient = new Web3Storage({ web3StorageToken }); this.readonly = false; } diff --git a/sdk/src/types/client.ts b/sdk/src/types/client.ts index 22beb6e2..0dd1082d 100644 --- a/sdk/src/types/client.ts +++ b/sdk/src/types/client.ts @@ -19,11 +19,13 @@ export type SupportedOverrides = { /** * Represents a deployment of a contract on a specific network. */ -export type Deployment = Chain & { +export type Deployment = { + chain: Partial; /** The address of the deployed contract. */ contractAddress: string; /** The url to the subgraph that indexes the contract events. Override for localized testing */ graphUrl: string; + graphName: string; }; /** diff --git a/sdk/src/utils/config.ts b/sdk/src/utils/config.ts index 85a04fc2..e69943cc 100644 --- a/sdk/src/utils/config.ts +++ b/sdk/src/utils/config.ts @@ -31,35 +31,34 @@ export const getConfig = (overrides: Partial) => { let baseDeployment: (Partial & { unsafeForceOverrideConfig?: boolean }) | undefined; if (overrides.unsafeForceOverrideConfig) { - if (!overrides.id || !overrides.contractAddress || !overrides.graphUrl) { + if (!overrides.chain?.id || !overrides.contractAddress || !overrides.graphUrl) { throw new InvalidOrMissingError( - `attempted to override with chainId=${overrides.id}, but requires chainName, graphUrl, and contractAddress to be set`, + `attempted to override with chainId=${overrides.chain?.id}, but requires chainName, graphUrl, and contractAddress to be set`, { - chainID: overrides.id?.toString(), + chainID: overrides.chain?.id?.toString(), graphUrl: overrides.graphUrl, contractAddress: overrides.contractAddress, }, ); } baseDeployment = { - ...chain, - id: overrides.id, + ...{ ...chain, id: overrides.chain?.id }, contractAddress: overrides.contractAddress, graphUrl: overrides.graphUrl, unsafeForceOverrideConfig: overrides.unsafeForceOverrideConfig, }; } else { //TODO doo many casts - baseDeployment = overrides.id - ? (getDeployment(overrides.id as SupportedChainIds) as Partial & { + baseDeployment = overrides.chain?.id + ? (getDeployment(overrides.chain?.id as SupportedChainIds) as Partial & { unsafeForceOverrideConfig?: boolean; }) : chain?.id ? (getDeployment(chain.id as SupportedChainIds) as Partial & { unsafeForceOverrideConfig?: boolean }) : undefined; if (!baseDeployment) { - throw new UnsupportedChainError(`Default config for chainId=${overrides.id} is missing in SDK`, { - chainID: overrides.id, + throw new UnsupportedChainError(`Default config for chainId=${overrides.chain?.id} is missing in SDK`, { + chainID: overrides.chain?.id, }); } @@ -97,11 +96,7 @@ const getDeployment = (chainId: SupportedChainIds) => { }; const getChainConfig = (overrides: Partial) => { - const chainId = overrides?.id - ? overrides.id - : process.env.DEFAULT_CHAIN_ID - ? parseInt(process.env.DEFAULT_CHAIN_ID) - : undefined; + const chainId = overrides?.chain?.id ? overrides.chain?.id : undefined; if (!chainId) { throw new ConfigurationError("No chainId specified in config or environment variables"); @@ -189,32 +184,12 @@ export const getNftStorageToken = (overrides: Partial) => if (overrides.nftStorageToken) { return { nftStorageToken: overrides.nftStorageToken }; } - - if (process.env.NFT_STORAGE_TOKEN) { - return { nftStorageToken: process.env.NFT_STORAGE_TOKEN }; - } - - if (process.env.NEXT_PUBLIC_NFT_STORAGE_TOKEN) { - return { nftStorageToken: process.env.NEXT_PUBLIC_NFT_STORAGE_TOKEN }; - } - - return {}; }; export const getWeb3StorageToken = (overrides: Partial) => { if (overrides.web3StorageToken) { return { web3StorageToken: overrides.web3StorageToken }; } - - if (process.env.WEB3_STORAGE_TOKEN) { - return { web3StorageToken: process.env.WEB3_STORAGE_TOKEN }; - } - - if (process.env.NEXT_PUBLIC_WEB3_STORAGE_TOKEN) { - return { web3StorageToken: process.env.NEXT_PUBLIC_WEB3_STORAGE_TOKEN }; - } - - return {}; }; const getEasContractAddress = (overrides: Partial) => { diff --git a/sdk/src/utils/resolvers.ts b/sdk/src/utils/resolvers.ts index 0641e565..3c52ea6d 100644 --- a/sdk/src/utils/resolvers.ts +++ b/sdk/src/utils/resolvers.ts @@ -2,9 +2,9 @@ import { Resolvers } from "../../.graphclient"; export const resolvers: Resolvers = { Claim: { - chainName: (root, args, context) => context.chainName, // The value we provide in the config + graphName: (root, args, context) => context.graphName, // The value we provide in the config }, ClaimToken: { - chainName: (root, args, context) => context.chainName, // The value we provide in the config + graphName: (root, args, context) => context.graphName, // The value we provide in the config }, }; diff --git a/sdk/test/client.test.ts b/sdk/test/client.test.ts index 85e8c566..6f9e124e 100644 --- a/sdk/test/client.test.ts +++ b/sdk/test/client.test.ts @@ -12,7 +12,7 @@ describe("HypercertClient setup tests", () => { it("should be able to create a new read only instance when missing storage keys", () => { const readOnlyClient = new HypercertClient({ - id: 5, + chain: { id: 5 }, publicClient, }); @@ -21,8 +21,13 @@ describe("HypercertClient setup tests", () => { }); it("should be able to create a new instance", () => { - const config = { id: 5, publicClient, walletClient, nftStorageToken: "test", web3StorageToken: "test" }; - const client = new HypercertClient(config); + const client = new HypercertClient({ + chain: { id: 5 }, + publicClient, + walletClient, + nftStorageToken: "test", + web3StorageToken: "test", + }); expect(client).to.be.an.instanceOf(HypercertClient); //TODO currently only publicClient added as a test, also add other flows @@ -32,7 +37,7 @@ describe("HypercertClient setup tests", () => { it("should throw an error when the chainId is not supported", () => { const falseChainId = 1337; try { - new HypercertClient({ id: falseChainId }); + new HypercertClient({ chain: { id: falseChainId } }); expect.fail("Should throw UnsupportedChainError"); } catch (e) { expect(e).to.be.instanceOf(UnsupportedChainError); @@ -44,12 +49,7 @@ describe("HypercertClient setup tests", () => { }); it("should throw an error when executing write method in readonly mode", async () => { - sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: null }); - sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN: null }); - sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: null }); - sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN: null }); - - const client = new HypercertClient({ id: 5 }); + const client = new HypercertClient({ chain: { id: 5 } }); // mintClaim try { diff --git a/sdk/test/client/allowlist.minting.test.ts b/sdk/test/client/allowlist.minting.test.ts index 54126e62..efc6ac2f 100644 --- a/sdk/test/client/allowlist.minting.test.ts +++ b/sdk/test/client/allowlist.minting.test.ts @@ -15,9 +15,11 @@ describe("Allows for minting claims from an allowlist", () => { const wallet = walletClient; const userAddress = wallet.account?.address; const client = new HypercertClient({ - id: 5, + chain: { id: 5 }, walletClient, publicClient, + nftStorageToken: "test", + web3StorageToken: "test", }); const readSpy = sinon.stub(publicClient, "readContract"); diff --git a/sdk/test/client/burn.test.ts b/sdk/test/client/burn.test.ts index e127cbf5..64b2d877 100644 --- a/sdk/test/client/burn.test.ts +++ b/sdk/test/client/burn.test.ts @@ -9,9 +9,11 @@ describe("burn fraction tokens in HypercertClient", () => { const wallet = walletClient; const userAddress = wallet.account?.address; const client = new HypercertClient({ - id: 5, + chain: { id: 5 }, walletClient, publicClient, + nftStorageToken: "test", + web3StorageToken: "test", }); const fractionId = 9868188640707215440437863615521278132232n; diff --git a/sdk/test/client/minting.test.ts b/sdk/test/client/minting.test.ts index 518b973c..1136704d 100644 --- a/sdk/test/client/minting.test.ts +++ b/sdk/test/client/minting.test.ts @@ -19,9 +19,11 @@ describe("mintClaim in HypercertClient", () => { const storeBlobMock = sinon.stub(NFTStorage, "storeBlob").resolves(mockCorrectMetadataCid); const client = new HypercertClient({ - id: 5, + chain: { id: 5 }, walletClient, publicClient, + nftStorageToken: "test", + web3StorageToken: "test", }); const readSpy = sinon.stub(publicClient, "readContract"); diff --git a/sdk/test/client/split.merge.test.ts b/sdk/test/client/split.merge.test.ts index f963b8c2..57d19762 100644 --- a/sdk/test/client/split.merge.test.ts +++ b/sdk/test/client/split.merge.test.ts @@ -13,9 +13,11 @@ describe("splitClaimUnits in HypercertClient", () => { let writeSpy = sinon.stub(walletClient, "writeContract"); const client = new HypercertClient({ - id: 5, + chain: { id: 5 }, walletClient, publicClient, + nftStorageToken: "test", + web3StorageToken: "test", }); const fractionId = 9868188640707215440437863615521278132232n; diff --git a/sdk/test/evaluations/evaluator.test.ts b/sdk/test/evaluations/evaluator.test.ts index 780c20d2..542abd21 100644 --- a/sdk/test/evaluations/evaluator.test.ts +++ b/sdk/test/evaluations/evaluator.test.ts @@ -9,7 +9,7 @@ import { getEvaluationData, publicClient, walletClient } from "../helpers.js"; describe("HypercertEvaluator", () => { const signer = walletClient.account; const evaluator = new HypercertEvaluator({ - id: 5, + chain: { id: 5 }, easContractAddress: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e", publicClient, }); @@ -63,15 +63,10 @@ describe("HypercertEvaluator", () => { }); it("should throw an error for readonly storage", async () => { - sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: null }); - sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN: null }); - sinon.stub(process, "env").value({ NEXT_PUBLIC_NFT_STORAGE_TOKEN: null }); - sinon.stub(process, "env").value({ NEXT_PUBLIC_WEB3_STORAGE_TOKEN: null }); - const evaluation: HypercertEvaluationSchema = getEvaluationData({ creator: signer?.address }); const readonlyEvaluator = new HypercertEvaluator({ - id: 5, + chain: { id: 5 }, easContractAddress: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e", publicClient, }); diff --git a/sdk/test/storage.test.ts b/sdk/test/storage.test.ts index 0d5e2be9..110da473 100644 --- a/sdk/test/storage.test.ts +++ b/sdk/test/storage.test.ts @@ -6,13 +6,6 @@ import { StorageError } from "../src/types/errors"; import { reloadEnv } from "./setup-env"; describe("HypercertsStorage", () => { - beforeAll(() => { - delete process.env.NFT_STORAGE_TOKEN; - delete process.env.WEB3_STORAGE_TOKEN; - delete process.env.NEXT_PUBLIC_NFT_STORAGE_TOKEN; - delete process.env.NEXT_PUBLIC_WEB3_STORAGE_TOKEN; - }); - afterAll(() => { reloadEnv(); }); @@ -41,11 +34,6 @@ describe("HypercertsStorage", () => { }); it("should throw an error when executing write method in readonly mode", async () => { - delete process.env.NFT_STORAGE_TOKEN; - delete process.env.WEB3_STORAGE_TOKEN; - delete process.env.NEXT_PUBLIC_NFT_STORAGE_TOKEN; - delete process.env.NEXT_PUBLIC_WEB3_STORAGE_TOKEN; - const client = new HypercertsStorage({}); // storeMetadata diff --git a/sdk/test/utils/config.test.ts b/sdk/test/utils/config.test.ts index b605be45..f27c44e5 100644 --- a/sdk/test/utils/config.test.ts +++ b/sdk/test/utils/config.test.ts @@ -18,7 +18,7 @@ describe("Config: contractAddress", () => { it("should return the contract address specified by overrides", () => { const overrides: Partial = { - id: 5, + chain: { id: 5 }, contractAddress: "0x1234567890123456789012345678901234567890", }; const config = getConfig(overrides); @@ -26,7 +26,7 @@ describe("Config: contractAddress", () => { }); it("should throw an error when the contract address specified by overrides is invalid", () => { - const overrides: Partial = { id: 5, contractAddress: "invalid-address" }; + const overrides: Partial = { chain: { id: 5 }, contractAddress: "invalid-address" }; try { getConfig(overrides); } catch (e) { @@ -43,13 +43,13 @@ describe("Config: graphUrl", () => { }); it("should return the default graphUrl when no overrides are specified", () => { - const result = getConfig({ id: 5 }); + const result = getConfig({ chain: { id: 5 } }); expect(result.graphUrl).to.equal("https://api.thegraph.com/subgraphs/name/hypercerts-admin/hypercerts-testnet"); }); it("should return the config specified by overrides", () => { const overrides: Partial = { - id: 5, + chain: { id: 5 }, graphUrl: "https://api.example.com", contractAddress: "0x1234567890123456789012345678901234567890", unsafeForceOverrideConfig: true, @@ -60,7 +60,7 @@ describe("Config: graphUrl", () => { it("should throw an error when the graph URL specified by overrides is invalid", () => { const overrides: Partial = { - id: 5, + chain: { id: 5 }, graphUrl: "incorrect-url", contractAddress: "0x1234567890123456789012345678901234567890", unsafeForceOverrideConfig: true, @@ -77,7 +77,7 @@ describe("Config: graphUrl", () => { it("should throw an error when the graph URL specified by overrides is missing", () => { const overrides: Partial = { - id: 5, + chain: { id: 5 }, contractAddress: "0x1234567890123456789012345678901234567890", unsafeForceOverrideConfig: true, }; @@ -101,18 +101,13 @@ describe("Config: nftStorageToken & web3storageToken", () => { reloadEnv(); }); it("should return an empty object when no overrides or environment variables are specified", () => { - sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); - - const result = getConfig({ id: 5 }); - expect(result).to.deep.include({ - id: 5, - nftStorageToken: "NFTSTOR", - }); + const result = getConfig({ chain: { id: 5 } }); + expect(result.nftStorageToken).to.be.undefined; }); it("should return the nftStorageToken specified by overrides", () => { const overrides: Partial = { - id: 5, + chain: { id: 5 }, nftStorageToken: "NFTSTOR", web3StorageToken: "WEB3STOR", }; @@ -124,16 +119,11 @@ describe("Config: nftStorageToken & web3storageToken", () => { }); it("should return the nftStorageToken specified by the NFT_STORAGE_TOKEN environment variable", () => { - sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: "NFTSTOR" }); - const result = getConfig({ id: 5 }); - expect(result).to.deep.include({ - nftStorageToken: "NFTSTOR", - }); + const result = getConfig({ chain: { id: 5 }, nftStorageToken: "NFTSTOR" }); + expect(result.nftStorageToken).to.be.eq("NFTSTOR"); }); it("should not throw an error when the nftStorageToken specified by overrides is invalid", () => { - sinon.stub(process, "env").value({ NFT_STORAGE_TOKEN: null }); - - const overrides: Partial = { id: 5 }; + const overrides: Partial = { chain: { id: 5 }, nftStorageToken: undefined }; expect(() => getConfig(overrides)).to.not.throw(); }); }); @@ -147,7 +137,7 @@ describe("Config: getPublicClient", () => { it("should return the operator specified by overrides", () => { const overrides: Partial = { - id: 5, + chain: { id: 5 }, publicClient, }; const result = getConfig(overrides); @@ -164,7 +154,7 @@ describe("Config: getWalletClient", () => { it("should return the operator specified by overrides", () => { const overrides: Partial = { - id: 5, + chain: { id: 5 }, walletClient, }; const result = getConfig(overrides); @@ -180,37 +170,24 @@ describe("Config: web3StorageToken", () => { }); it("should return an empty object when no overrides or environment variables are specified", () => { - const WEB3_STORAGE_TOKEN = "WEB3"; - sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); - const result = getConfig({ id: 5 }); - expect(result).to.deep.include({ - web3StorageToken: WEB3_STORAGE_TOKEN, - }); + const result = getConfig({ chain: { id: 5 } }); + expect(result.web3StorageToken).to.be.undefined; }); it("should return the web3StorageToken specified by overrides", () => { const overrides: Partial = { - id: 5, + chain: { id: 5 }, web3StorageToken: "WEB3STOR", }; + const result = getConfig(overrides); expect(result).to.deep.include({ web3StorageToken: overrides.web3StorageToken, }); }); - it("should return the web3StorageToken specified by the WEB3_STORAGE_TOKEN environment variable", () => { - const WEB3_STORAGE_TOKEN = "WEB3"; - sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN }); - const result = getConfig({ id: 5 }); - expect(result).to.deep.include({ - web3StorageToken: WEB3_STORAGE_TOKEN, - }); - }); - it("should not throw an error when the web3StorageToken specified by overrides is invalid", () => { - sinon.stub(process, "env").value({ WEB3_STORAGE_TOKEN: null }); - const overrides: Partial = { id: 5 }; + const overrides: Partial = { chain: { id: 5 }, web3StorageToken: undefined }; expect(() => getConfig(overrides)).to.not.throw(); }); }); From c8f73a539cad8f0370aa047bb18333ad82195d02 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 14:49:54 +0100 Subject: [PATCH 36/49] chore(parse): fix parse calc --- frontend/lib/parsing.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/lib/parsing.ts b/frontend/lib/parsing.ts index ced8d3f4..6daccd78 100644 --- a/frontend/lib/parsing.ts +++ b/frontend/lib/parsing.ts @@ -27,10 +27,12 @@ export function parseAllowlistCsv( console.error("Errors parsing allowlist:", errors); throw new InvalidDataError("Errors parsing allowlist"); } + + console.log(rawData); // Get the addresses and units from the CSV const csvData = rawData.map((row: any) => ({ address: row["address"].trim().toLowerCase(), - units: BigInt((row["fractions"].trim(), 10)), + units: BigInt(row["fractions"].trim()), })); const csvTotalSupply = csvData.reduce( (accum, curr) => accum + curr.units, @@ -55,8 +57,10 @@ export function parseAllowlistCsv( } } // Combine CSV data with manually added addresses + // 0.75 const csvTotalPercentage = 1.0 - addTotalPercentage; + // 75 const percentageBigInt = BigInt(Math.floor(csvTotalPercentage * 100)); // convert percentage to BigInt const creatorSupply = (csvTotalSupply * 100n) / percentageBigInt; // calculate total supply From 14f29d3bea99fc93c1d8d7f05351195d0dc960f0 Mon Sep 17 00:00:00 2001 From: jipstavenuiter Date: Mon, 6 Nov 2023 15:24:04 +0100 Subject: [PATCH 37/49] fix parse allowlist csv tests --- frontend/lib/parsing.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/frontend/lib/parsing.ts b/frontend/lib/parsing.ts index 6daccd78..8315f860 100644 --- a/frontend/lib/parsing.ts +++ b/frontend/lib/parsing.ts @@ -61,14 +61,19 @@ export function parseAllowlistCsv( const csvTotalPercentage = 1.0 - addTotalPercentage; // 75 - const percentageBigInt = BigInt(Math.floor(csvTotalPercentage * 100)); // convert percentage to BigInt - const creatorSupply = (csvTotalSupply * 100n) / percentageBigInt; // calculate total supply + const csvTotalPercentageBigInt = BigInt(Math.floor(csvTotalPercentage * 100)); // convert percentage to BigInt + const addTotalPercentageBigInt = BigInt(Math.floor(addTotalPercentage * 100)); // convert percentage to BigInt + const creatorSupply = + (((csvTotalSupply * 100n) / csvTotalPercentageBigInt) * + addTotalPercentageBigInt) / + 100n; + const totalSupply = csvTotalSupply + creatorSupply; // calculate total supply // TODO risk over overflow on units - casting bigint to number const data = csvData.concat( add.map((x) => ({ address: x.address.trim().toLowerCase(), - units: creatorSupply, + units: (totalSupply * BigInt(Math.floor(x.percentage * 100))) / 100n, })), ); From c123b62a3d857170944d890e2416de34ee19e065 Mon Sep 17 00:00:00 2001 From: jipstavenuiter Date: Mon, 6 Nov 2023 15:29:09 +0100 Subject: [PATCH 38/49] fix injected chain id in config --- frontend/lib/config.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/lib/config.ts b/frontend/lib/config.ts index 5ceac794..e82c0a5a 100644 --- a/frontend/lib/config.ts +++ b/frontend/lib/config.ts @@ -12,7 +12,9 @@ export const DOMAIN = requireEnv( export const isProduction = DOMAIN === "hypercerts.org"; -export const DEFAULT_CHAIN_ID = process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID; +export const DEFAULT_CHAIN_ID = process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID + ? parseInt(process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID, 10) + : undefined; export const CONTRACT_ADDRESS = process.env.NEXT_PUBLIC_CONTRACT_ADDRESS; From 9f8b7f46486758e51161387b25476b5f4e77dd7f Mon Sep 17 00:00:00 2001 From: jipstavenuiter Date: Mon, 6 Nov 2023 15:53:57 +0100 Subject: [PATCH 39/49] update component config.tsx --- frontend/components/config.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/components/config.tsx b/frontend/components/config.tsx index bdd293e0..51eef3e9 100644 --- a/frontend/components/config.tsx +++ b/frontend/components/config.tsx @@ -20,11 +20,14 @@ export interface ConfigProps { export function Config(props: ConfigProps) { const { className, children } = props; const { client: hypercertClient } = useHypercertClient(); + const chainId = hypercertClient.config.chain?.id + ? Number(hypercertClient.config.chain.id) + : undefined; const data: ConfigData = { domain: DOMAIN, - chainId: Number(hypercertClient._config.chainId), - graphUrl: hypercertClient._config.graphUrl, + chainId, + graphUrl: hypercertClient.config.graphUrl, supabaseTable: SUPABASE_TABLE, }; return ( From ff07f54334c5d013dfbc6b9a9351e3efb09588e4 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 15:23:45 +0100 Subject: [PATCH 40/49] chore(bump): updated sdk alpha --- frontend/package.json | 2 +- pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index c9e0ee14..3ca22cde 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,7 +25,7 @@ "@graphprotocol/client-cli": "^2.2.16", "@hypercerts-org/contracts": "0.9.0", "@hypercerts-org/observabletreemap": "workspace: *", - "@hypercerts-org/sdk": "1.0.0-alpha.0", + "@hypercerts-org/sdk": "1.0.0-alpha.2", "@mui/icons-material": "^5.11.9", "@mui/material": "^5.11.2", "@mui/x-date-pickers": "^5.0.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2cc8bf90..974d13d3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -312,8 +312,8 @@ importers: specifier: 'workspace: *' version: link:../vendor/observabletreemap '@hypercerts-org/sdk': - specifier: 1.0.0-alpha.0 - version: 1.0.0-alpha.0(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) + specifier: 1.0.0-alpha.2 + version: 1.0.0-alpha.2(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) '@mui/icons-material': specifier: ^5.11.9 version: 5.14.15(@mui/material@5.14.15)(@types/react@18.2.33)(react@18.2.0) @@ -7528,8 +7528,8 @@ packages: - utf-8-validate dev: false - /@hypercerts-org/sdk@1.0.0-alpha.0(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): - resolution: {integrity: sha512-qjPSmEI5MFDFSLrzxL7O+JIYrJHK6jh4qBxDwTgvQMQdBRWPQweYEkGwTZ4vYQvlN6gtTqu9WWk+73WF7D2oCQ==} + /@hypercerts-org/sdk@1.0.0-alpha.2(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): + resolution: {integrity: sha512-inIvYmL5L9vpyOnO0PP9qvYOXNSVAUFAiBaLfYa8ci8VAz6aLLqX9f6FoCh2xfbKkLeD6jXf4vZqdjW/GHUAFg==} dependencies: '@ethereum-attestation-service/eas-sdk': 1.2.2-beta.0(ts-node@10.9.1)(typescript@5.1.6) '@ethersproject/abstract-signer': 5.7.0 From e8858e7c116fe180ff3092abab79760424fd77d3 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 15:26:49 +0100 Subject: [PATCH 41/49] chore(run): sanity check passed --- graph/tests/.latest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graph/tests/.latest.json b/graph/tests/.latest.json index bce35982..9bf8a349 100644 --- a/graph/tests/.latest.json +++ b/graph/tests/.latest.json @@ -1,4 +1,4 @@ { "version": "0.6.0", - "timestamp": 1699126393078 + "timestamp": 1699280746839 } From 71d101ed9f7e64cfff5bc04420e38dd57347a8ef Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 15:53:40 +0100 Subject: [PATCH 42/49] chore(build): graphSDK --- frontend/components/config.tsx | 7 +++++-- frontend/components/dapp-state.tsx | 4 ---- frontend/components/hypercert-fetcher.tsx | 2 +- frontend/hooks/hypercerts-client.ts | 25 +++++------------------ frontend/lib/config.ts | 9 ++++---- frontend/package.json | 2 +- pnpm-lock.yaml | 8 ++++---- sdk/src/utils/config.ts | 4 ++-- 8 files changed, 22 insertions(+), 39 deletions(-) diff --git a/frontend/components/config.tsx b/frontend/components/config.tsx index 51eef3e9..dc799b63 100644 --- a/frontend/components/config.tsx +++ b/frontend/components/config.tsx @@ -24,10 +24,13 @@ export function Config(props: ConfigProps) { ? Number(hypercertClient.config.chain.id) : undefined; + console.log(chainId); + console.log("Config: ", hypercertClient.config); + const data: ConfigData = { domain: DOMAIN, - chainId, - graphUrl: hypercertClient.config.graphUrl, + chainId: chainId, + graphUrl: hypercertClient?.config.graphUrl, supabaseTable: SUPABASE_TABLE, }; return ( diff --git a/frontend/components/dapp-state.tsx b/frontend/components/dapp-state.tsx index 56e1947e..6b4e661a 100644 --- a/frontend/components/dapp-state.tsx +++ b/frontend/components/dapp-state.tsx @@ -1,6 +1,5 @@ import { useAccountLowerCase } from "../hooks/account"; import useCheckWriteable from "../hooks/checkWriteable"; -import { DEFAULT_CHAIN_ID } from "../lib/config"; import { claimedRecently } from "./claim-all-fractions-button"; import { PlasmicCanvasContext } from "@plasmicapp/loader-nextjs"; import { DataProvider } from "@plasmicapp/loader-nextjs"; @@ -15,7 +14,6 @@ const ALL_CHAINS = [optimism, goerli, hardhat, sepolia]; export interface DappStateData { myAddress?: string; - defaultChainId?: number; chain?: Chain; chains?: Chain[]; waitToClaim?: boolean; @@ -25,7 +23,6 @@ export interface DappStateData { //TODO revert to testnet data. Needed to override for local dev of WC-wagmi-safe integration export const DEFAULT_TEST_DATA: DappStateData = { myAddress: "0x22E4b9b003Cc7B7149CF2135dfCe2BaddC7a534f".toLowerCase(), - defaultChainId: 10, chain: optimism, chains: ALL_CHAINS, waitToClaim: false, @@ -63,7 +60,6 @@ export function DappState(props: DappStateProps) { myAddress: address, chain, chains, - defaultChainId: DEFAULT_CHAIN_ID, waitToClaim, writeable, }; diff --git a/frontend/components/hypercert-fetcher.tsx b/frontend/components/hypercert-fetcher.tsx index fd3076b5..db0c5f3f 100644 --- a/frontend/components/hypercert-fetcher.tsx +++ b/frontend/components/hypercert-fetcher.tsx @@ -79,7 +79,7 @@ export function HypercertFetcher(props: HypercertFetcherProps) { }, [useQueryString, byClaimId, byMetadataUri]); // Show when loading - if (!ignoreLoading && !!loading && !data) { + if (!client && !ignoreLoading && !!loading && !data) { return
{loading}
; } diff --git a/frontend/hooks/hypercerts-client.ts b/frontend/hooks/hypercerts-client.ts index 9f892c82..aae0d081 100644 --- a/frontend/hooks/hypercerts-client.ts +++ b/frontend/hooks/hypercerts-client.ts @@ -1,35 +1,20 @@ import React, { useEffect } from "react"; import { - DEFAULT_CHAIN_ID, NFT_STORAGE_TOKEN, WEB3_STORAGE_TOKEN, - CONTRACT_ADDRESS, - UNSAFE_FORCE_OVERRIDE_CONFIG, + NEXT_PUBLIC_DEFAULT_CHAIN_ID, } from "../lib/config"; import { HypercertClient, HypercertClientConfig } from "@hypercerts-org/sdk"; import { useWalletClient, useNetwork } from "wagmi"; const clientConfig: Partial = { - id: DEFAULT_CHAIN_ID ? Number(DEFAULT_CHAIN_ID) : 5, + chain: { id: Number(NEXT_PUBLIC_DEFAULT_CHAIN_ID) }, nftStorageToken: NFT_STORAGE_TOKEN, web3StorageToken: WEB3_STORAGE_TOKEN, }; -// TODO - make overrides explicit in loading config -function loadOverridingConfig(clientConfig: Partial) { - if (CONTRACT_ADDRESS) { - clientConfig.contractAddress = CONTRACT_ADDRESS; - } - - if (UNSAFE_FORCE_OVERRIDE_CONFIG) { - clientConfig.unsafeForceOverrideConfig = UNSAFE_FORCE_OVERRIDE_CONFIG; - } - - return clientConfig; -} - -const defaultClient = new HypercertClient(loadOverridingConfig(clientConfig)); +const defaultClient = new HypercertClient(clientConfig); export const useHypercertClient = () => { const { chain } = useNetwork(); @@ -49,11 +34,11 @@ export const useHypercertClient = () => { try { const config: Partial = { - id: chain.id, + chain: { id: chain.id }, walletClient, }; - const client = new HypercertClient(loadOverridingConfig(config)); + const client = new HypercertClient({ ...clientConfig, ...config }); setClient(client); } catch (e) { console.error(e); diff --git a/frontend/lib/config.ts b/frontend/lib/config.ts index e82c0a5a..6ebe8eed 100644 --- a/frontend/lib/config.ts +++ b/frontend/lib/config.ts @@ -12,11 +12,10 @@ export const DOMAIN = requireEnv( export const isProduction = DOMAIN === "hypercerts.org"; -export const DEFAULT_CHAIN_ID = process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID - ? parseInt(process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID, 10) - : undefined; - -export const CONTRACT_ADDRESS = process.env.NEXT_PUBLIC_CONTRACT_ADDRESS; +export const NEXT_PUBLIC_DEFAULT_CHAIN_ID = requireEnv( + process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID, + "NEXT_PUBLIC_DEFAULT_CHAIN_ID", +); export const NFT_STORAGE_TOKEN = requireEnv( process.env.NEXT_PUBLIC_NFT_STORAGE_TOKEN, diff --git a/frontend/package.json b/frontend/package.json index 3ca22cde..a4ecf483 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,7 +25,7 @@ "@graphprotocol/client-cli": "^2.2.16", "@hypercerts-org/contracts": "0.9.0", "@hypercerts-org/observabletreemap": "workspace: *", - "@hypercerts-org/sdk": "1.0.0-alpha.2", + "@hypercerts-org/sdk": "1.0.0-alpha.3", "@mui/icons-material": "^5.11.9", "@mui/material": "^5.11.2", "@mui/x-date-pickers": "^5.0.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 974d13d3..66d33f9c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -312,8 +312,8 @@ importers: specifier: 'workspace: *' version: link:../vendor/observabletreemap '@hypercerts-org/sdk': - specifier: 1.0.0-alpha.2 - version: 1.0.0-alpha.2(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) + specifier: 1.0.0-alpha.3 + version: 1.0.0-alpha.3(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) '@mui/icons-material': specifier: ^5.11.9 version: 5.14.15(@mui/material@5.14.15)(@types/react@18.2.33)(react@18.2.0) @@ -7528,8 +7528,8 @@ packages: - utf-8-validate dev: false - /@hypercerts-org/sdk@1.0.0-alpha.2(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): - resolution: {integrity: sha512-inIvYmL5L9vpyOnO0PP9qvYOXNSVAUFAiBaLfYa8ci8VAz6aLLqX9f6FoCh2xfbKkLeD6jXf4vZqdjW/GHUAFg==} + /@hypercerts-org/sdk@1.0.0-alpha.3(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): + resolution: {integrity: sha512-QTzqwdABd2gaLBfxsDINY1UIREmy3JEX7yAYYWxip5KVCy+X9JTIWZySgMuUAEnUqvuSXAZQ6VxTYTBk7lm1jw==} dependencies: '@ethereum-attestation-service/eas-sdk': 1.2.2-beta.0(ts-node@10.9.1)(typescript@5.1.6) '@ethersproject/abstract-signer': 5.7.0 diff --git a/sdk/src/utils/config.ts b/sdk/src/utils/config.ts index e69943cc..d8ad86d3 100644 --- a/sdk/src/utils/config.ts +++ b/sdk/src/utils/config.ts @@ -42,7 +42,7 @@ export const getConfig = (overrides: Partial) => { ); } baseDeployment = { - ...{ ...chain, id: overrides.chain?.id }, + chain: { ...chain, id: overrides.chain?.id }, contractAddress: overrides.contractAddress, graphUrl: overrides.graphUrl, unsafeForceOverrideConfig: overrides.unsafeForceOverrideConfig, @@ -62,7 +62,7 @@ export const getConfig = (overrides: Partial) => { }); } - baseDeployment = { ...chain, ...baseDeployment }; + baseDeployment = { ...baseDeployment, chain }; } const config: Partial = { From d88b6b9c612d5d771afd0c5985540162441a965c Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 18:32:07 +0100 Subject: [PATCH 43/49] feat(fe): plasmic rendering issues. --- frontend/package.json | 2 +- pnpm-lock.yaml | 8 ++++---- sdk/package.json | 2 +- sdk/src/storage.ts | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index a4ecf483..29549417 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,7 +25,7 @@ "@graphprotocol/client-cli": "^2.2.16", "@hypercerts-org/contracts": "0.9.0", "@hypercerts-org/observabletreemap": "workspace: *", - "@hypercerts-org/sdk": "1.0.0-alpha.3", + "@hypercerts-org/sdk": "1.0.0-alpha.5", "@mui/icons-material": "^5.11.9", "@mui/material": "^5.11.2", "@mui/x-date-pickers": "^5.0.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 66d33f9c..2d9b0d33 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -312,8 +312,8 @@ importers: specifier: 'workspace: *' version: link:../vendor/observabletreemap '@hypercerts-org/sdk': - specifier: 1.0.0-alpha.3 - version: 1.0.0-alpha.3(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) + specifier: 1.0.0-alpha.5 + version: 1.0.0-alpha.5(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) '@mui/icons-material': specifier: ^5.11.9 version: 5.14.15(@mui/material@5.14.15)(@types/react@18.2.33)(react@18.2.0) @@ -7528,8 +7528,8 @@ packages: - utf-8-validate dev: false - /@hypercerts-org/sdk@1.0.0-alpha.3(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): - resolution: {integrity: sha512-QTzqwdABd2gaLBfxsDINY1UIREmy3JEX7yAYYWxip5KVCy+X9JTIWZySgMuUAEnUqvuSXAZQ6VxTYTBk7lm1jw==} + /@hypercerts-org/sdk@1.0.0-alpha.5(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): + resolution: {integrity: sha512-t1Q0w/dWbZa2Xn8x3QkS6Mp8nKTOGRaURZHyVvGFCbyWeL2/vTe+3ZEIH0R6xApwXRUvNm0ZFOf8vFJHZQB61A==} dependencies: '@ethereum-attestation-service/eas-sdk': 1.2.2-beta.0(ts-node@10.9.1)(typescript@5.1.6) '@ethersproject/abstract-signer': 5.7.0 diff --git a/sdk/package.json b/sdk/package.json index 853c6f14..63c6449e 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@hypercerts-org/sdk", - "version": "1.0.0-alpha.3", + "version": "1.0.0-alpha.5", "description": "SDK for hypercerts protocol", "repository": "git@github.com:hypercerts-org/hypercerts.git", "author": "Hypercerts team", diff --git a/sdk/src/storage.ts b/sdk/src/storage.ts index 89d91a4d..80fa94ac 100644 --- a/sdk/src/storage.ts +++ b/sdk/src/storage.ts @@ -56,15 +56,15 @@ export default class HypercertsStorage implements HypercertStorageInterface { } } - getFromIPFS = async (cidOrIpfsUri: string) => { + getFromIPFS = async (cidOrIpfsUri: string, timeout = 10000) => { const nftStorageGatewayLink = this.getNftStorageGatewayUri(cidOrIpfsUri); const web3StorageGatewayLink = this.getWeb3StorageGatewayUri(cidOrIpfsUri); logger.debug(`Getting metadata ${cidOrIpfsUri} at ${nftStorageGatewayLink}`); - const res = await axios.get(nftStorageGatewayLink, { timeout: 5000 }).catch(() => { + const res = await axios.get(nftStorageGatewayLink, { timeout }).catch(() => { logger.debug(`${nftStorageGatewayLink} timed out.`); logger.debug(`Getting metadata ${cidOrIpfsUri} at ${web3StorageGatewayLink}`); - return axios.get(web3StorageGatewayLink, { timeout: 5000 }); + return axios.get(web3StorageGatewayLink, { timeout }); }); if (!res || !res.data) { From 2cd075f646ca3a1f08d2a48e74639b145f86d903 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 18:44:05 +0100 Subject: [PATCH 44/49] feat(sdk): web3 token --- frontend/hooks/hypercerts-client.ts | 5 +- frontend/package.json | 2 +- pnpm-lock.yaml | 131 +++++++++++++--------------- sdk/package.json | 2 +- sdk/src/storage.ts | 2 +- 5 files changed, 68 insertions(+), 74 deletions(-) diff --git a/frontend/hooks/hypercerts-client.ts b/frontend/hooks/hypercerts-client.ts index aae0d081..4a42e611 100644 --- a/frontend/hooks/hypercerts-client.ts +++ b/frontend/hooks/hypercerts-client.ts @@ -34,11 +34,12 @@ export const useHypercertClient = () => { try { const config: Partial = { + ...clientConfig, chain: { id: chain.id }, walletClient, }; - const client = new HypercertClient({ ...clientConfig, ...config }); + const client = new HypercertClient(config); setClient(client); } catch (e) { console.error(e); @@ -48,5 +49,7 @@ export const useHypercertClient = () => { setIsLoading(false); }, [chain?.id, walletClient, walletClientLoading]); + console.log(client); + return { client, isLoading }; }; diff --git a/frontend/package.json b/frontend/package.json index 29549417..7c9186ee 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,7 +25,7 @@ "@graphprotocol/client-cli": "^2.2.16", "@hypercerts-org/contracts": "0.9.0", "@hypercerts-org/observabletreemap": "workspace: *", - "@hypercerts-org/sdk": "1.0.0-alpha.5", + "@hypercerts-org/sdk": "1.0.0-alpha.6", "@mui/icons-material": "^5.11.9", "@mui/material": "^5.11.2", "@mui/x-date-pickers": "^5.0.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d9b0d33..203d74fe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -304,7 +304,7 @@ importers: version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) '@graphprotocol/client-cli': specifier: ^2.2.16 - version: 2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) + version: 2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) '@hypercerts-org/contracts': specifier: 0.9.0 version: 0.9.0(typescript@5.1.6) @@ -312,8 +312,8 @@ importers: specifier: 'workspace: *' version: link:../vendor/observabletreemap '@hypercerts-org/sdk': - specifier: 1.0.0-alpha.5 - version: 1.0.0-alpha.5(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) + specifier: 1.0.0-alpha.6 + version: 1.0.0-alpha.6(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4) '@mui/icons-material': specifier: ^5.11.9 version: 5.14.15(@mui/material@5.14.15)(@types/react@18.2.33)(react@18.2.0) @@ -5757,6 +5757,24 @@ packages: '@trufflesuite/bigint-buffer': 1.1.9 dev: true + /@graphprotocol/client-add-source-name@1.0.20(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): + resolution: {integrity: sha512-JJ++BVg4fhNCbLej105uHpabZesLsCSo9p43ZKSTT1VUdbuZtarzyIHC3uUmbvCfWQMVTCJEBZGx4l41oooOiw==} + peerDependencies: + '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 + '@graphql-tools/delegate': ^9.0.32 + '@graphql-tools/utils': ^9.2.1 + '@graphql-tools/wrap': ^9.4.2 + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) + graphql: 16.8.1 + lodash: 4.17.21 + tslib: 2.6.2 + dev: false + /@graphprotocol/client-add-source-name@1.0.20(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): resolution: {integrity: sha512-JJ++BVg4fhNCbLej105uHpabZesLsCSo9p43ZKSTT1VUdbuZtarzyIHC3uUmbvCfWQMVTCJEBZGx4l41oooOiw==} peerDependencies: @@ -5794,7 +5812,7 @@ packages: tslib: 2.6.2 dev: true - /@graphprotocol/client-auto-pagination@1.1.18(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): + /@graphprotocol/client-auto-pagination@1.1.18(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1): resolution: {integrity: sha512-p8eEyeBcqxCXLxC7CNgIhLSCd7bjiKToKnrwYPShVb26gIG2JdAmD3/mpjuR+QaMA4chN/EO5t+TGvq6KnFx9g==} peerDependencies: '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 @@ -5803,7 +5821,7 @@ packages: '@graphql-tools/wrap': ^9.4.2 graphql: ^15.2.0 || ^16.0.0 dependencies: - '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) '@graphql-tools/wrap': 9.4.2(graphql@16.8.1) @@ -5831,15 +5849,15 @@ packages: tslib: 2.6.2 dev: true - /@graphprotocol/client-auto-type-merging@1.0.25(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1): + /@graphprotocol/client-auto-type-merging@1.0.25(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1): resolution: {integrity: sha512-kpiX2s804mpP3EVL0EdJfxeHWBTdg6SglIyEvSZ5T1OWyGDeMhr19D+gVIAlo22/PiBUkBDd0JfqppLsliPZ1A==} peerDependencies: '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 '@graphql-tools/delegate': ^9.0.32 graphql: ^15.2.0 || ^16.0.0 dependencies: - '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/transform-type-merging': 0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) graphql: 16.8.1 tslib: 2.6.2 @@ -5889,19 +5907,19 @@ packages: tslib: 2.6.2 dev: true - /@graphprotocol/client-cli@2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): + /@graphprotocol/client-cli@2.2.22(@babel/core@7.23.2)(@envelop/core@3.0.6)(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6): resolution: {integrity: sha512-PIi8rFibYZVup+0jb08399RmbGF1ZrqUe6RXzLtKZBT57OWIMWwsFvdJyUAdr8Y8f0rrMn6A+Oy4nP1lf3hc1g==} hasBin: true peerDependencies: graphql: ^15.2.0 || ^16.0.0 dependencies: - '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) - '@graphprotocol/client-auto-pagination': 1.1.18(@graphql-mesh/types@0.95.8)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) - '@graphprotocol/client-auto-type-merging': 1.0.25(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) + '@graphprotocol/client-add-source-name': 1.0.20(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) + '@graphprotocol/client-auto-pagination': 1.1.18(@graphql-mesh/types@0.93.2)(@graphql-tools/delegate@9.0.35)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(graphql@16.8.1) + '@graphprotocol/client-auto-type-merging': 1.0.25(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-block-tracking': 1.0.14(@graphql-tools/delegate@9.0.35)(graphql@16.8.1) '@graphprotocol/client-polling-live': 1.1.1(@envelop/core@3.0.6)(@graphql-tools/merge@8.4.2)(graphql@16.8.1) '@graphql-mesh/cli': 0.82.35(@babel/core@7.23.2)(@types/node@18.18.7)(graphql-tag@2.12.6)(graphql@16.8.1)(react-native@0.72.6) - '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/graphql': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2) graphql: 16.8.1 tslib: 2.6.2 transitivePeerDependencies: @@ -6402,7 +6420,7 @@ packages: graphql: 16.8.1 path-browserify: 1.0.1 - /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2): + /@graphql-mesh/graphql@0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/store@0.93.1)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-1G2/1jkl1VPWhsZsUBwFQI5d9OxxEc+CMxy5ef0qI2WEXqIocOxMhEY53cc+tCSbuXR99rxos+KD/8Z6ZasaOQ==} peerDependencies: '@graphql-mesh/cross-helpers': ^0.3.4 @@ -6414,10 +6432,10 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) - '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/store': 0.93.1(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/string-interpolation': 0.4.4(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/url-loader': 7.17.18(@types/node@18.18.7)(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) @@ -6645,7 +6663,7 @@ packages: graphql: 16.8.1 tslib: 2.6.2 - /@graphql-mesh/runtime@0.96.13(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): + /@graphql-mesh/runtime@0.96.13(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-eZIW/gdEVLvCLEEae8e3lny7d89CFfDyu0Z0xu4yVEdYeVpG9Ki2mDYFHztusIIkZikecvdsoM9MZX6LYcPOkg==} engines: {node: '>=16.0.0'} peerDependencies: @@ -6661,8 +6679,8 @@ packages: '@envelop/graphql-jit': 8.0.1(@envelop/core@5.0.0)(graphql@16.8.1) '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) '@graphql-mesh/string-interpolation': 0.5.3(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/batch-delegate': 9.0.0(graphql@16.8.1) '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) '@graphql-tools/executor': 1.2.0(graphql@16.8.1) @@ -6721,26 +6739,6 @@ packages: graphql: 16.8.1 tslib: 2.6.2 - /@graphql-mesh/store@0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-29lpMcvqS1DM9alUOCyj6he2V7ZzG/DZxkerRefT8Mo5FexwJZI3LeI0YHNSY9Cq0x8KzRoH1TWcTTN/1PDRRw==} - engines: {node: '>=16.0.0'} - peerDependencies: - '@graphql-mesh/cross-helpers': ^0.4.1 - '@graphql-mesh/types': ^0.95.8 - '@graphql-mesh/utils': ^0.95.8 - '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: '*' - tslib: ^2.4.0 - dependencies: - '@graphql-inspector/core': 5.0.1(graphql@16.8.1) - '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) - '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - graphql: 16.8.1 - tslib: 2.6.2 - dev: false - /@graphql-mesh/store@0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-29lpMcvqS1DM9alUOCyj6he2V7ZzG/DZxkerRefT8Mo5FexwJZI3LeI0YHNSY9Cq0x8KzRoH1TWcTTN/1PDRRw==} engines: {node: '>=16.0.0'} @@ -6785,6 +6783,22 @@ packages: lodash.get: 4.4.2 tslib: 2.6.2 + /@graphql-mesh/transform-type-merging@0.93.1(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(graphql@16.8.1)(tslib@2.6.2): + resolution: {integrity: sha512-CUrqCMaEqO1LDusv59UPqmQju3f+LpEGxFu7CydMiIvbfKDDDrf8+dF3OVU7d/ZOMRxB6hR80JsQF0SVeXPCOQ==} + peerDependencies: + '@graphql-mesh/types': ^0.93.1 + '@graphql-mesh/utils': ^0.93.1 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/types': 0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.93.2(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) + '@graphql-tools/stitching-directives': 2.3.34(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + dev: false + /@graphql-mesh/transform-type-merging@0.93.1(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-CUrqCMaEqO1LDusv59UPqmQju3f+LpEGxFu7CydMiIvbfKDDDrf8+dF3OVU7d/ZOMRxB6hR80JsQF0SVeXPCOQ==} peerDependencies: @@ -6794,11 +6808,12 @@ packages: tslib: ^2.4.0 dependencies: '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-tools/delegate': 9.0.35(graphql@16.8.1) '@graphql-tools/stitching-directives': 2.3.34(graphql@16.8.1) graphql: 16.8.1 tslib: 2.6.2 + dev: true /@graphql-mesh/types@0.93.2(@graphql-mesh/store@0.93.1)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-113DuJzmR7aj2EMnLPu33ktCe5k7+Mk0BxFfmQViUH+mkr6i4JMsWvPKs9dTODSYuSuwvAZ90Vw2l3QyMrbFVA==} @@ -6855,30 +6870,6 @@ packages: tiny-lru: 8.0.2 tslib: 2.6.2 - /@graphql-mesh/utils@0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): - resolution: {integrity: sha512-gH2/kXvxMHVWMX8DppIIZpFfSUaoKDJ6eQHFoAAsdabGE+vLtVk0OEYqMGVGtD/8ZDFa/P6CmwXc6hBzoLY6Kg==} - engines: {node: '>=16.0.0'} - peerDependencies: - '@graphql-mesh/cross-helpers': ^0.4.1 - '@graphql-mesh/types': ^0.95.8 - '@graphql-tools/utils': ^9.2.1 || ^10.0.0 - graphql: '*' - tslib: ^2.4.0 - dependencies: - '@graphql-mesh/cross-helpers': 0.3.4(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(react-native@0.72.6) - '@graphql-mesh/string-interpolation': 0.5.3(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) - '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - '@whatwg-node/fetch': 0.9.14 - dset: 3.1.3 - graphql: 16.8.1 - js-yaml: 4.1.0 - lodash.get: 4.4.2 - lodash.topath: 4.5.2 - tiny-lru: 11.2.3 - tslib: 2.6.2 - /@graphql-mesh/utils@0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2): resolution: {integrity: sha512-gH2/kXvxMHVWMX8DppIIZpFfSUaoKDJ6eQHFoAAsdabGE+vLtVk0OEYqMGVGtD/8ZDFa/P6CmwXc6hBzoLY6Kg==} engines: {node: '>=16.0.0'} @@ -7528,8 +7519,8 @@ packages: - utf-8-validate dev: false - /@hypercerts-org/sdk@1.0.0-alpha.5(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): - resolution: {integrity: sha512-t1Q0w/dWbZa2Xn8x3QkS6Mp8nKTOGRaURZHyVvGFCbyWeL2/vTe+3ZEIH0R6xApwXRUvNm0ZFOf8vFJHZQB61A==} + /@hypercerts-org/sdk@1.0.0-alpha.6(@envelop/core@3.0.6)(@graphql-tools/delegate@9.0.35)(@graphql-tools/merge@8.4.2)(@graphql-tools/utils@9.2.1)(@graphql-tools/wrap@9.4.2)(@types/node@18.18.7)(node-fetch@3.3.2)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2)(typescript@5.1.6)(uint8arraylist@2.4.3)(zod@3.22.4): + resolution: {integrity: sha512-WnZJfKGGqaQAPasvKjAuQ1eyWJT8kfY5Z445SjeFU8xWDelLRGuwaMT1w+B3e16YbZFQXBr/eB/dabMVb9ZPrQ==} dependencies: '@ethereum-attestation-service/eas-sdk': 1.2.2-beta.0(ts-node@10.9.1)(typescript@5.1.6) '@ethersproject/abstract-signer': 5.7.0 @@ -7540,10 +7531,10 @@ packages: '@graphql-mesh/graphql': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(@types/node@18.18.7)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2) '@graphql-mesh/http': 0.96.14(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/runtime@0.96.13)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/merger-bare': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/runtime': 0.96.13(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/runtime': 0.96.13(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.93.2)(@graphql-mesh/utils@0.93.2)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/store': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-mesh/utils@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-mesh/types': 0.95.8(@graphql-mesh/store@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) - '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.3.4)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) + '@graphql-mesh/utils': 0.95.8(@graphql-mesh/cross-helpers@0.4.1)(@graphql-mesh/types@0.95.8)(@graphql-tools/utils@9.2.1)(graphql@16.8.1)(tslib@2.6.2) '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) '@hypercerts-org/contracts': 0.8.11 '@openzeppelin/merkle-tree': 1.0.5 diff --git a/sdk/package.json b/sdk/package.json index 63c6449e..91b39d68 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@hypercerts-org/sdk", - "version": "1.0.0-alpha.5", + "version": "1.0.0-alpha.6", "description": "SDK for hypercerts protocol", "repository": "git@github.com:hypercerts-org/hypercerts.git", "author": "Hypercerts team", diff --git a/sdk/src/storage.ts b/sdk/src/storage.ts index 80fa94ac..19bab0e8 100644 --- a/sdk/src/storage.ts +++ b/sdk/src/storage.ts @@ -51,7 +51,7 @@ export default class HypercertsStorage implements HypercertStorageInterface { } } else { this.nftStorageClient = new NFTStorage({ token: nftStorageToken.nftStorageToken || "" }); - this.web3StorageClient = new Web3Storage({ web3StorageToken }); + this.web3StorageClient = new Web3Storage({ token: web3StorageToken.web3StorageToken || "" }); this.readonly = false; } } From 53412d121f0a75b64735f05fcd2df3aa30f3f7b0 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 18:56:51 +0100 Subject: [PATCH 45/49] chore(defender): removed api_key sep network conf --- .../src/auto-tasks/batch-mint-claims-from-allowlists.ts | 8 -------- defender/src/networks.ts | 1 - 2 files changed, 9 deletions(-) diff --git a/defender/src/auto-tasks/batch-mint-claims-from-allowlists.ts b/defender/src/auto-tasks/batch-mint-claims-from-allowlists.ts index 558983f6..578f6aa8 100644 --- a/defender/src/auto-tasks/batch-mint-claims-from-allowlists.ts +++ b/defender/src/auto-tasks/batch-mint-claims-from-allowlists.ts @@ -13,14 +13,6 @@ import { BigNumber, ethers } from "ethers"; import fetch from "node-fetch"; export async function handler(event: AutotaskEvent) { - console.log( - "Event: ", - JSON.stringify( - { ...event, secrets: "HIDDEN", credentials: "HIDDEN" }, - null, - 2, - ), - ); const network = getNetworkConfigFromName(event.autotaskName); const { SUPABASE_URL, SUPABASE_SECRET_API_KEY } = event.secrets; const ALCHEMY_KEY = event.secrets[network.alchemyKeyEnvName]; diff --git a/defender/src/networks.ts b/defender/src/networks.ts index ffbc1fba..80aa187b 100644 --- a/defender/src/networks.ts +++ b/defender/src/networks.ts @@ -30,7 +30,6 @@ export const NETWORKS: SupportedNetworks = { { networkKey: "sepolia", contractAddress: "0xa16DFb32Eb140a6f3F2AC68f41dAd8c7e83C4941", - alchemyKeyEnvName: "ALCHEMY_SEPOLIA_KEY", chainId: 11155111, rpc: "https://rpc.sepolia.org", }, From 2d902b0f007ac3c901f653c6647ede376144efea Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 19:19:49 +0100 Subject: [PATCH 46/49] chore(defender): remove verbose log batch action --- frontend/hooks/hypercerts-client.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/hooks/hypercerts-client.ts b/frontend/hooks/hypercerts-client.ts index 4a42e611..e26c39ae 100644 --- a/frontend/hooks/hypercerts-client.ts +++ b/frontend/hooks/hypercerts-client.ts @@ -49,7 +49,5 @@ export const useHypercertClient = () => { setIsLoading(false); }, [chain?.id, walletClient, walletClientLoading]); - console.log(client); - return { client, isLoading }; }; From 3e4390183acf9f10d38610398cb2fe4c3bf32610 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 19:21:47 +0100 Subject: [PATCH 47/49] chore(gha): deduplicate runs - now on all push --- .github/workflows/ci-default.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/ci-default.yml b/.github/workflows/ci-default.yml index 7c338fa1..9febf105 100644 --- a/.github/workflows/ci-default.yml +++ b/.github/workflows/ci-default.yml @@ -21,11 +21,6 @@ env: on: # A push occurs to one of the matched branches. push: - pull_request: - branches: - - main - - develop - - develop-contracts # Allows you to run this workflow manually from the Actions tab workflow_dispatch: From e143ec66a5884b0da1883dc3df198a307b5bd470 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 19:27:42 +0100 Subject: [PATCH 48/49] chore(lint): lint fe lib --- frontend/lib/hypercert.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/lib/hypercert.test.ts b/frontend/lib/hypercert.test.ts index 7920637b..a2d4c549 100644 --- a/frontend/lib/hypercert.test.ts +++ b/frontend/lib/hypercert.test.ts @@ -23,7 +23,7 @@ function genClaimTokens( id: id, tokenID: tokenID, owner: owner, - chainName: options?.chainName ?? "test", + graphName: options?.chainName ?? "test", units: options?.units ?? "100", }); } @@ -37,7 +37,7 @@ function genClaim(totalUnits: string): Claim { contract: randomAddress(), tokenID: randomTokenID(), totalUnits: totalUnits, - chainName: "test", + graphName: "test", }; } From acaeca5030525b1b2602edb28282ab3549aad925 Mon Sep 17 00:00:00 2001 From: bitbeckers Date: Mon, 6 Nov 2023 19:36:17 +0100 Subject: [PATCH 49/49] chore(gha): cleaned up env vars --- .github/workflows/ci-default.yml | 2 ++ sdk/test/storage/web3.storage.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-default.yml b/.github/workflows/ci-default.yml index 9febf105..a52e21bf 100644 --- a/.github/workflows/ci-default.yml +++ b/.github/workflows/ci-default.yml @@ -7,6 +7,8 @@ env: NEXT_PUBLIC_DEFAULT_CHAIN_ID: ${{ vars.NEXT_PUBLIC_DEFAULT_CHAIN_ID }} NEXT_PUBLIC_CONTRACT_ADDRESS: ${{ vars.NEXT_PUBLIC_CONTRACT_ADDRESS }} NEXT_PUBLIC_GRAPH_URL: ${{ vars.NEXT_PUBLIC_GRAPH_URL }} + NFT_STORAGE_TOKEN: ${{ secrets.NEXT_PUBLIC_NFT_STORAGE_TOKEN }} + WEB3_STORAGE_TOKEN: ${{ secrets.NEXT_PUBLIC_NFT_STORAGE_TOKEN }} NEXT_PUBLIC_NFT_STORAGE_TOKEN: ${{ secrets.NEXT_PUBLIC_NFT_STORAGE_TOKEN }} NEXT_PUBLIC_WEB3_STORAGE_TOKEN: ${{ secrets.NEXT_PUBLIC_NFT_STORAGE_TOKEN }} NEXT_PUBLIC_SUPABASE_URL: ${{ vars.NEXT_PUBLIC_SUPABASE_URL }} diff --git a/sdk/test/storage/web3.storage.test.ts b/sdk/test/storage/web3.storage.test.ts index 9fa8d0ed..e5845098 100644 --- a/sdk/test/storage/web3.storage.test.ts +++ b/sdk/test/storage/web3.storage.test.ts @@ -3,8 +3,8 @@ import { jest } from "@jest/globals"; // @ts-ignore import { Web3Storage } from "web3.storage"; -import HypercertsStorage from "../../src/storage.js"; -import { mockDataSets } from "../helpers.js"; +import HypercertsStorage from "../../src/storage"; +import { mockDataSets } from "../helpers"; describe("Web3.Storage Client", () => { const { hypercertData, hypercertMetadata } = mockDataSets;