diff --git a/.gas-snapshot b/.gas-snapshot index 589d377c..18b671ac 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,52 +1,32 @@ -TestRMM01:testFuzz_changeParameters(uint16,uint16,uint16) (runs: 10000, μ: 363354, ~: 363518) -TestRMM01:testFuzz_createPool(uint16,uint16,uint16,uint16,uint16,uint128,uint128) (runs: 10000, μ: 201062, ~: 190373) -TestRMM01:testFuzz_fund_then_draw(uint64) (runs: 10000, μ: 640427, ~: 640432) -TestRMM01:test_allocate_balances_increase() (gas: 747698) -TestRMM01:test_allocate_does_not_modify_timestamp() (gas: 721218) -TestRMM01:test_allocate_liquidity_overflow_reverts() (gas: 333599) -TestRMM01:test_allocate_modifies_liquidity() (gas: 731248) -TestRMM01:test_allocate_non_existent_pool_reverts() (gas: 46168) -TestRMM01:test_allocate_reserves_increase() (gas: 748973) -TestRMM01:test_allocate_reserves_increase_six_decimals() (gas: 749333) -TestRMM01:test_allocate_zero_liquidity_reverts() (gas: 333596) -TestRMM01:test_changeParameters_priority_fee_success() (gas: 363537) -TestRMM01:test_claim_credits_balance_asset() (gas: 1739536) -TestRMM01:test_claim_get_balance_returns_fee_amount_asset() (gas: 1126889) -TestRMM01:test_claim_get_balance_returns_fee_amount_quote() (gas: 1267102) -TestRMM01:test_claim_position_owed_amounts_returns_zero() (gas: 1138770) -TestRMM01:test_claim_small_liquidity_does_not_steal_fees() (gas: 1835588) -TestRMM01:test_claim_succeeds() (gas: 1552908) -TestRMM01:test_createPair_fetch_pair_data_returns_token_data() (gas: 1482969) -TestRMM01:test_createPair_fetch_pair_id_returns_non_zero() (gas: 1478372) -TestRMM01:test_createPair_nonce_increments_returns_one() (gas: 1478880) -TestRMM01:test_createPair_success() (gas: 1476912) -TestRMM01:test_createPool_non_controlled_default_jit() (gas: 183374) -TestRMM01:test_deallocate_max() (gas: 900263) -TestRMM01:test_deposit_ether_balance_equals_zero() (gas: 159134) -TestRMM01:test_deposit_ether_balance_of_weth_equals_msg_value() (gas: 159696) -TestRMM01:test_deposit_increases_user_weth_balance() (gas: 167619) -TestRMM01:test_deposit_reserve_equals_msg_value() (gas: 164251) -TestRMM01:test_deposit_weth_total_supply_equals_msg_value() (gas: 161475) -TestRMM01:test_draw_max_balance() (gas: 557773) -TestRMM01:test_draw_reduces_user_balance() (gas: 557859) -TestRMM01:test_draw_weth_transfers_ether() (gas: 242314) -TestRMM01:test_fund_increases_user_balance() (gas: 482493) -TestRMM01:test_fund_max_balance() (gas: 482492) -TestRMM01:test_revert_changeParameters_invalid_fee() (gas: 348973) -TestRMM01:test_revert_changeParameters_invalid_jit() (gas: 348576) -TestRMM01:test_revert_changeParameters_not_controller() (gas: 347545) -TestRMM01:test_revert_changeParameters_priority_fee_above_max() (gas: 360133) -TestRMM01:test_revert_claim_no_position() (gas: 336074) -TestRMM01:test_revert_createPair_asset_lower_decimal_bound() (gas: 1387955) -TestRMM01:test_revert_createPair_asset_upper_decimal_bound() (gas: 1388031) -TestRMM01:test_revert_createPair_exists() (gas: 346704) -TestRMM01:test_revert_createPair_quote_lower_decimal_bound() (gas: 1388035) -TestRMM01:test_revert_createPair_quote_upper_decimal_bound() (gas: 1388111) -TestRMM01:test_revert_createPair_same_token() (gas: 699838) -TestRMM01:test_revert_createPool_above_max_pairs() (gas: 1033031) -TestRMM01:test_revert_createPool_above_max_pools() (gas: 27892) -TestRMM01:test_revert_createPool_priority_fee_invalid_fee() (gas: 65236) -TestRMM01:test_revert_createPool_zero_price() (gas: 19257) -TestRMM01:test_revert_draw_greater_than_balance() (gas: 339917) -TestRMM01:test_swap_increases_user_balance_token_out() (gas: 1107628) -TestRMM01:test_version() (gas: 6969) \ No newline at end of file +TestGas:test_gas_chain_allocate_deallocate_from_portfolio_balance() (gas: 155363) +TestGas:test_gas_chain_create_allocate_from_portfolio() (gas: 460784) +TestGas:test_gas_chain_swap_allocate_from_portfolio() (gas: 327801) +TestGas:test_gas_chain_swap_deallocate_create_allocate_from_portfolio() (gas: 470302) +TestGas:test_gas_create_pool_allocate_transfer_from_wallet() (gas: 460492) +TestGas:test_gas_multi_allocate_10() (gas: 853389) +TestGas:test_gas_multi_allocate_100() (gas: 7461628) +TestGas:test_gas_multi_allocate_2() (gas: 395302) +TestGas:test_gas_multi_allocate_25() (gas: 1769294) +TestGas:test_gas_multi_allocate_2_pairs() (gas: 515736) +TestGas:test_gas_multi_allocate_5() (gas: 564596) +TestGas:test_gas_multi_allocate_50() (gas: 3460599) +TestGas:test_gas_multi_create_pool_100() (gas: 264444) +TestGas:test_gas_multi_deallocate_10() (gas: 448246) +TestGas:test_gas_multi_deallocate_100() (gas: 4156306) +TestGas:test_gas_multi_deallocate_2() (gas: 264442) +TestGas:test_gas_multi_deallocate_25() (gas: 857111) +TestGas:test_gas_multi_deallocate_2_pool_2_pair() (gas: 365064) +TestGas:test_gas_multi_deallocate_5() (gas: 330573) +TestGas:test_gas_multi_deallocate_50() (gas: 1724360) +TestGas:test_gas_multi_swap_10() (gas: 1100287) +TestGas:test_gas_multi_swap_100() (gas: 12966986) +TestGas:test_gas_multi_swap_2() (gas: 389117) +TestGas:test_gas_multi_swap_25() (gas: 2788271) +TestGas:test_gas_multi_swap_5() (gas: 641773) +TestGas:test_gas_multi_swap_50() (gas: 5859558) +TestGas:test_gas_single_allocate() (gas: 339512) +TestGas:test_gas_single_allocate_from_portfolio_balance() (gas: 339459) +TestGas:test_gas_single_deallocate() (gas: 244731) +TestGas:test_gas_single_swap() (gas: 307095) +TestGas:test_gas_single_swap_from_portfolio_balance() (gas: 305376) +TestGas:test_gas_single_swap_from_wallet() (gas: 307011) \ No newline at end of file diff --git a/.github/workflows/gas.yaml b/.github/workflows/gas.yaml index 7f17b27b..377453d2 100644 --- a/.github/workflows/gas.yaml +++ b/.github/workflows/gas.yaml @@ -16,6 +16,6 @@ jobs: with: version: nightly - - name: Run gas profiling for RMM01Portfolio + - name: Run gas profiling run: FOUNDRY_PROFILE=optimized forge test --gas-report --match-contract TestGas diff --git a/.github/workflows/optimized.yaml b/.github/workflows/optimized.yaml index ade7c2bf..e0a34d1f 100644 --- a/.github/workflows/optimized.yaml +++ b/.github/workflows/optimized.yaml @@ -19,5 +19,5 @@ jobs: - name: Run build run: FOUNDRY_PROFILE=optimized forge build --sizes --skip test - - name: Run tests RMM01Portfolio + - name: Run tests run: FOUNDRY_PROFILE=optimized forge test diff --git a/README.md b/README.md index 62a036ca..768ea51e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,62 @@ -> Beta: Not production ready. Pending on-going audits. +> Beta: Portfolio is experimental software. Use at your own risk. # Portfolio by Primitive +[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/primitivefinance/portfolio#contributing) [![](https://dcbadge.vercel.app/api/server/primitive?style=flat)](https://discord.gg/primitive) [![Twitter Badge](https://badgen.net/badge/icon/twitter?icon=twitter&label)](https://twitter.com/primitivefi) Portfolio is an automated market making protocol for implementing custom liquidity distribution strategies at the lowest cost possible. -[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/primitivefinance/portfolio#contributing) [![](https://dcbadge.vercel.app/api/server/primitive?style=flat)](https://discord.gg/primitive) [![Twitter Badge](https://badgen.net/badge/icon/twitter?icon=twitter&label)](https://twitter.com/primitivefi) +## Table of Contents + +- [Overview](#overview) +- [Deployments](#deployments) +- [Security](#security) +- [Install](#install) +- [Documentation](#documentation) +- [Resources](#resources) +- [Contributing](#contributing) +- [License](#license) + +## Overview + +Portfolio is an automated market making protocol for creating custom liquidity distribution strategies at the lowest cost possible. Each pool in Portfolio can be created with a default strategy or custom strategy that defines a trading function, determining the available prices offered by the provider's liquidity. These pools all exist within the single Portfolio smart contract resulting in significantly lower gas costs for liquidity providers and swappers. + +Read the local [docs](./docs/src/), hosted docs [docs.primitive.xyz](https://docs.primitive.xyz), or the [formal specification](https://primitive.xyz/whitepaper) for more information. + + +## Deployments + +### Canonical Cross-chain Deployment Addresses + +| Contract | Canonical cross-chain address | +| -------------------- | -------------------------------------------- | +| Portfolio 1.3.0-beta | `0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1` | +| Portfolio 1.4.0-beta | `todo` | + +### Deployments by Chain + +| Network | Portfolio 1.3.0-beta | Portfolio v1.4.0-beta | +| -------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| Ethereum | [0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1](https://etherscan.io/address/0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1 ) | todo | +| Base | n/a | todo | +| Sepolia | [0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1](https://sepolia.etherscan.io/address/0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1) | todo | -## Installation +# Security + +[Visit Primitive Security](https://www.primitive.xyz/security) to view a comprehensive overview of the security initiatives of Portfolio. + +## Audits + +| Security Firm | Date | Review Time | Status | Final Commit w/ Fixes | +| ------------------------------------------------------------------------------------------------------------- | ---------- | ----------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| [ChainSecurity](https://github.com/primitivefinance/security/blob/main/audits/portfolio/chainsecurity.pdf) | 2022-05-31 | 8-weeks | Completed | [c6f692f41c1d20ac09acb832923bd46500fd8e06](https://github.com/primitivefinance/portfolio/commit/c6f692f41c1d20ac09acb832923bd46500fd8e06) | +| [Trail of Bits](https://github.com/primitivefinance/security/blob/main/audits/portfolio/trailofbits.pdf) | 2023-01-31 | 8-weeks | Completed | n/a | +| [Spearbit #1](https://github.com/primitivefinance/security/blob/main/audits/portfolio/spearbit.pdf) | 2023-03-31 | 5-weeks | Completed | [tag/v1.1.0-beta](https://github.com/primitivefinance/portfolio/releases/tag/v1.1.0-beta) | +| [Spearbit #1 Extension](https://github.com/primitivefinance/security/blob/main/audits/portfolio/spearbit.pdf) | 2023-05-12 | 2-weeks | Competed | [36e9efa28332fa03f6d5910edda2fec2f5937190](https://github.com/primitivefinance/portfolio/commit/36e9efa28332fa03f6d5910edda2fec2f5937190 ) | +| Spearbit #2 | 2023-07-78 | 2-weeks | Completed | [tag/v1.4.0-beta-spearbit-2023-08-complete](https://github.com/primitivefinance/portfolio/releases/tag/v1.4.0-beta-spearbit-2023-08-complete) | + +## Install + +To install locally and compile contracts: #### [Required] Foundry. [Source](https://github.com/foundry-rs/foundry). If not installed, run the following: @@ -17,26 +67,40 @@ curl -L https://foundry.paradigm.xyz | bash # Restart terminal or reload `PATH`, then run foundryup foundryup ``` +#### [Required] Install Deps +```bash +forge install +``` -### Install & Run +#### Usage +##### Testing ```bash -forge install & forge test +FOUNDRY_PROFILE=test forge test ``` -# Security +##### Building +```bash +FOUNDRY_PROFILE=optimized forge build --skip test +``` -[Visit Primitive Security](https://www.primitive.xyz/security) to view a comprehensive overview of the security initiatives of Portfolio. +##### Coverage + +[Optional] Install coverage gutters [vs code extension](https://github.com/ryanluker/vscode-coverage-gutters). + +Then run this to generate a coverage report: + +```bash +forge coverage --report lcov +``` + +### Install Artifacts via NPM +To install the artifacts to use in your own project: -## Audits -| Security Firm | Review Time | Status | -| ------------------ | ----------- | --------- | -| ChainSecurity | 8-weeks | Completed | -| Trail of Bits | 8-weeks | Completed | -| Spearbit | 5-weeks | Completed | -| Spearbit Extension | 2-weeks | Competed | -| Spearbit Extension #2 | 2-weeks | Pending | +```bash +npm install @primitivexyz/portfolio +``` # Documentation @@ -73,15 +137,7 @@ cd docs mdbook serve --open ``` -## coverage - -[Optional] Install coverage gutters [vs code extension](https://github.com/ryanluker/vscode-coverage-gutters). - -Then run this to generate a coverage report: -```bash -forge coverage --report lcov -``` ## Resources @@ -113,3 +169,8 @@ When making a pull request: - New tests for all new features or code paths. - If making a modification to third-party dependencies, yarn audit passes. - A descriptive summary of the PR has been provided. + + +## Copyright + +[AGPL-3.0](./LICENSE) © 2023 Primitive Bits, Inc. \ No newline at end of file diff --git a/contracts/PortfolioRegistry.sol b/contracts/PortfolioRegistry.sol new file mode 100644 index 00000000..34cca726 --- /dev/null +++ b/contracts/PortfolioRegistry.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity ^0.8.4; + +import "./interfaces/IERC20.sol"; +import "./interfaces/IPortfolioRegistry.sol"; +import "solmate/auth/Owned.sol"; + +interface PortfolioLike { + function setProtocolFee(uint256) external; + function claimFee(address, uint256) external; +} + +/// @dev Basic registry with a single owner. +contract PortfolioRegistry is IPortfolioRegistry, Owned { + constructor(address owner_) Owned(owner_) { } + + function controller() external view returns (address) { + return owner; + } + + function setFee(address portfolio, uint256 fee) external onlyOwner { + PortfolioLike(portfolio).setProtocolFee(fee); + } + + function claimFee( + address portfolio, + address token, + uint256 amount + ) public onlyOwner { + PortfolioLike(portfolio).claimFee(token, amount); + } + + function withdraw(address token, uint256 amount) external onlyOwner { + require(amount > 0, "SimpleRegistry/invalid-amount"); + require( + IERC20(token).transfer(msg.sender, amount), + "SimpleRegistry/transfer-failed" + ); + } +} diff --git a/contracts/PositionRenderer.sol b/contracts/PositionRenderer.sol index 9a9782b5..ec0e1674 100644 --- a/contracts/PositionRenderer.sol +++ b/contracts/PositionRenderer.sol @@ -2,36 +2,102 @@ pragma solidity ^0.8.4; import "openzeppelin/utils/Base64.sol"; -import "openzeppelin/utils/Strings.sol"; import "solmate/tokens/ERC20.sol"; -import "solmate/utils/SafeCastLib.sol"; + +import "./libraries/StringsLib.sol"; +import "./libraries/AssemblyLib.sol"; +import { PoolIdLib } from "./libraries/PoolLib.sol"; import "./interfaces/IPortfolio.sol"; -import "./interfaces/IStrategy.sol"; import "./strategies/NormalStrategy.sol"; -/// @dev Contract to render a position. +/** + * @title + * PositionRenderer + * + * @author + * Primitive™ + * + * @dev + * Prepares the metadata and generates the visual representation of the + * liquidity pool tokens. + * This contract is not meant to be called directly. + */ contract PositionRenderer { - using Strings for *; - using SafeCastLib for *; + using StringsLib for *; + + struct Pair { + address asset; + string assetSymbol; + string assetName; + uint8 assetDecimals; + address quote; + string quoteSymbol; + string quoteName; + uint8 quoteDecimals; + } + + struct Pool { + uint256 poolId; + uint128 virtualX; + uint128 virtualY; + uint16 feeBasisPoints; + uint16 priorityFeeBasisPoints; + address controller; + address strategy; + uint256 spotPriceWad; + bool hasDefaultStrategy; + } + + struct Config { + uint128 strikePriceWad; + uint32 volatilityBasisPoints; + uint32 durationSeconds; + uint32 creationTimestamp; + bool isPerpetual; + } + + struct Properties { + Pair pair; + Pool pool; + Config config; + } + string private constant PRIMITIVE_LOGO = + ''; + + string private constant STYLE_0 = + ""; + + /** + * @dev Returns the metadata of the required liquidity pool token, following + * the ERC-1155 standard. + * @param id Id of the required pool. + * @return Minified Base64-encoded JSON containing the metadata. + */ function uri(uint256 id) external view returns (string memory) { + Properties memory properties = _getProperties(id); + return string.concat( "data:application/json;base64,", Base64.encode( bytes( abi.encodePacked( '{"name":"', - _generateName(id), - '","image":"', - _generateImage(), + _generateName(properties), + '","animation_url":"data:text/html;base64,', + Base64.encode(bytes(_generateHTML(properties))), '","license":"MIT","creator":"primitive.eth",', - '"description":"Concentrated liquidity tokens of a two-token AMM",', + '"description":"This NFT represents a liquidity position in a Portfolio pool. The owner of this NFT can modify or redeem this position.\\n\\n', + unicode"⚠️ WARNING: Transferring this NFT makes the new recipient the owner of the position.", + '",', '"properties":{', - _generatePair(id), + _generatePair(properties), ",", - _generatePool(id), + _generatePool(properties), ",", - _generateConfig(id), + _generateConfig(properties), "}}" ) ) @@ -39,113 +105,504 @@ contract PositionRenderer { ); } - function _generateName(uint256 id) private view returns (string memory) { - (address tokenAsset,, address tokenQuote,) = IPortfolio(msg.sender) - .pairs(PoolId.wrap(id.safeCastTo64()).pairId()); - - return string.concat( - "Primitive Portfolio LP ", - ERC20(tokenAsset).symbol(), - "-", - ERC20(tokenQuote).symbol() + /** + * @dev Returns the data associated with the asset / quote pair. + * @param id Id of the pair associated with the required pool. + */ + function _getPair(uint256 id) internal view returns (Pair memory) { + ( + address tokenAsset, + uint8 decimalsAsset, + address tokenQuote, + uint8 decimalsQuote + ) = IPortfolio(msg.sender).pairs( + uint24(PoolIdLib.pairId(PoolId.wrap(uint64(id)))) ); + + return Pair({ + asset: tokenAsset, + assetSymbol: ERC20(tokenAsset).symbol(), + assetName: ERC20(tokenAsset).name(), + assetDecimals: decimalsAsset, + quote: tokenQuote, + quoteSymbol: ERC20(tokenQuote).symbol(), + quoteName: ERC20(tokenQuote).name(), + quoteDecimals: decimalsQuote + }); + } + + /** + * @dev Returns the data associated with the current pool. + * @param id Id of the required pool. + */ + function _getPool(uint256 id) internal view returns (Pool memory) { + ( + uint128 virtualX, + uint128 virtualY, + , + , + uint16 feeBasisPoints, + uint16 priorityFeeBasisPoints, + address controller, + address strategy + ) = IPortfolio(msg.sender).pools(uint64(id)); + + uint256 spotPriceWad = IPortfolio(msg.sender).getSpotPrice(uint64(id)); + + return Pool({ + poolId: id, + virtualX: virtualX, + virtualY: virtualY, + feeBasisPoints: feeBasisPoints, + priorityFeeBasisPoints: priorityFeeBasisPoints, + controller: controller, + strategy: strategy, + spotPriceWad: spotPriceWad, + hasDefaultStrategy: strategy + == IPortfolio(msg.sender).DEFAULT_STRATEGY() + }); + } + + /** + * @dev Returns the data associated with the current pool config. + * @param id Id of the required pool. + */ + function _getConfig( + uint256 id, + address strategy + ) internal view returns (Config memory) { + ( + uint128 strikePriceWad, + uint32 volatilityBasisPoints, + uint32 durationSeconds, + uint32 creationTimestamp, + bool isPerpetual + ) = NormalStrategy(strategy).configs(uint64(id)); + + return Config({ + strikePriceWad: strikePriceWad, + volatilityBasisPoints: volatilityBasisPoints, + durationSeconds: durationSeconds, + creationTimestamp: creationTimestamp, + isPerpetual: isPerpetual + }); } - function _generateImage() private pure returns (string memory) { + /** + * @dev Returns all data associated with the current pool packed within a + * struct. + * @param id Id of the required pool. + */ + function _getProperties(uint256 id) + private + view + returns (Properties memory) + { + Pair memory pair = _getPair(id); + Pool memory pool = _getPool(id); + Config memory config = _getConfig(id, pool.strategy); + + return Properties({ pair: pair, pool: pool, config: config }); + } + + /** + * @dev Generates the name of the NFT. + */ + function _generateName(Properties memory properties) + private + pure + returns (string memory) + { return string.concat( - "data:image/svg+xml;base64,", - Base64.encode( - bytes( - '' - ) - ) + "Primitive Portfolio LP ", + properties.pair.assetSymbol, + "-", + properties.pair.quoteSymbol ); } - function _generatePair(uint256 id) private view returns (string memory) { - (address tokenAsset,, address tokenQuote,) = IPortfolio(msg.sender) - .pairs(PoolId.wrap(id.safeCastTo64()).pairId()); - + /** + * @dev Outputs all the data associated with the current pair in JSON format. + */ + function _generatePair(Properties memory properties) + private + pure + returns (string memory) + { return string.concat( '"asset_name":"', - ERC20(tokenAsset).name(), + properties.pair.assetName, '",', '"asset_symbol":"', - ERC20(tokenAsset).symbol(), + properties.pair.assetSymbol, '",', '"asset_address":"', - Strings.toHexString(tokenAsset), + properties.pair.asset.toHexString(), '",', '"quote_name":"', - ERC20(tokenQuote).name(), + properties.pair.quoteName, '",', '"quote_symbol":"', - ERC20(tokenQuote).symbol(), + properties.pair.quoteSymbol, '",', '"quote_address":"', - Strings.toHexString(tokenQuote), + properties.pair.quote.toHexString(), '"' ); } - function _generatePool(uint256 id) private view returns (string memory) { - ( - , - , - , - , - uint16 feeBasisPoints, - uint16 priorityFeeBasisPoints, - address controller, - address strategy - ) = IPortfolio(msg.sender).pools(uint64(id)); - + /** + * @dev Outputs all the data associated with the current pool in JSON format. + */ + function _generatePool(Properties memory properties) + private + pure + returns (string memory) + { return string.concat( + '"asset_reserves":"', + (properties.pool.virtualX).toString(), + '",', + '"quote_reserves":"', + (properties.pool.virtualY).toString(), + '",', + '"spot_price_wad":"', + (properties.pool.spotPriceWad).toString(), + '",', '"fee_basis_points":"', - feeBasisPoints.toString(), + properties.pool.feeBasisPoints.toString(), '",', '"priority_fee_basis_points":"', - priorityFeeBasisPoints.toString(), + properties.pool.priorityFeeBasisPoints.toString(), '",', '"controller":"', - Strings.toHexString(controller), + StringsLib.toHexString(properties.pool.controller), '",', '"strategy":"', - Strings.toHexString(strategy), + StringsLib.toHexString(properties.pool.strategy), '"' ); } - function _generateConfig(uint256 id) private view returns (string memory) { - (,,,,,,, address strategy) = IPortfolio(msg.sender).pools(uint64(id)); - - if (strategy == address(0)) { - strategy = IPortfolio(msg.sender).DEFAULT_STRATEGY(); - } - - ( - uint128 strikePriceWad, - uint32 volatilityBasisPoints, - uint32 durationSeconds, - uint32 creationTimestamp, - bool isPerpetual - ) = NormalStrategy(strategy).configs(uint64(id)); - + /** + * @dev Outputs all the data associated with the current pool config in JSON + * format. + */ + function _generateConfig(Properties memory properties) + private + pure + returns (string memory) + { return string.concat( '"strike_price_wad":"', - strikePriceWad.toString(), + (properties.config.strikePriceWad).toString(), '",', '"volatility_basis_points":"', - volatilityBasisPoints.toString(), + properties.config.volatilityBasisPoints.toString(), '",', '"duration_seconds":"', - durationSeconds.toString(), + properties.config.durationSeconds.toString(), '",', '"creation_timestamp":"', - creationTimestamp.toString(), + properties.config.creationTimestamp.toString(), '",', '"is_perpetual":', - isPerpetual ? "true" : "false" + properties.config.isPerpetual ? "true" : "false" + ); + } + + /** + * @dev Generates the visual representation of the NFT in HTML. + */ + function _generateHTML(Properties memory properties) + private + view + returns (string memory) + { + string memory color0 = StringsLib.toHexColor( + bytes3( + keccak256( + abi.encode(properties.pool.poolId, properties.pair.asset) + ) + ) + ); + string memory color1 = StringsLib.toHexColor( + bytes3( + keccak256( + abi.encode(properties.pool.poolId, properties.pair.quote) + ) + ) + ); + + string memory title = string.concat( + properties.pair.assetSymbol, + "-", + properties.pair.quoteSymbol, + " Portfolio LP" + ); + + return string.concat( + '', + title, + "", + STYLE_0, + color0, + ",", + color1, + STYLE_1, + "", + '
', + '', + _generateStats(properties), + _generateFooter(properties), + "" + ); + } + + /** + * @dev Generates a element representing a stat. + * @param label Name of the stat. + * @param amount Full amount (including the decimals). + * @param decimals Decimals of the token. + * @param symbol Ticker of the token. + */ + function _generateStat( + string memory label, + uint256 amount, + uint8 decimals, + string memory symbol + ) private pure returns (string memory) { + return string.concat( + '', + label, + "
", + " ", + symbol, + "" + ); + } + + /** + * @dev Generates a element representing a percentage stat. + * @param label Name of the stat. + * @param amount Full amount (using a 10,000 base). + */ + function _generatePercentStat( + string memory label, + uint256 amount + ) private pure returns (string memory) { + return string.concat( + '', + label, + "
", + " %" + ); + } + + /** + * @dev Generates a element containing the title. + */ + function _generateTitle(Properties memory properties) + private + view + returns (string memory) + { + return string.concat( + '', + string.concat( + properties.pair.assetSymbol, "-", properties.pair.quoteSymbol + ), + '
', + properties.config.isPerpetual + ? "Perpetual pool" + : ( + properties.config.creationTimestamp + + properties.config.durationSeconds + ).toCountdown(), + "" + ); + } + + /** + * @dev Generates the stats element. + */ + function _generateStats(Properties memory properties) + private + view + returns (string memory) + { + return string.concat( + '
', + "", + _generateTitle(properties), + "", + _generateSpotPrice(properties), + _generateStrikePrice(properties), + "", + _generateAssetReserves(properties), + _generateQuoteReserves(properties), + "", + _generatePoolValuation(properties), + _generateSwapFee(properties), + "
", + PRIMITIVE_LOGO, + "
" + ); + } + + /** + * @dev Generates the spot price element. + */ + function _generateSpotPrice(Properties memory properties) + internal + pure + returns (string memory) + { + return string.concat( + _generateStat( + "Spot Price", + AssemblyLib.scaleFromWadDown( + properties.pool.spotPriceWad, properties.pair.quoteDecimals + ), + properties.pair.quoteDecimals, + properties.pair.quoteSymbol + ) + ); + } + + /** + * @dev Generates the strike price element. + */ + function _generateStrikePrice(Properties memory properties) + internal + pure + returns (string memory) + { + return string.concat( + _generateStat( + "Strike Price", + AssemblyLib.scaleFromWadDown( + properties.config.strikePriceWad, + properties.pair.quoteDecimals + ), + properties.pair.quoteDecimals, + properties.pair.quoteSymbol + ) + ); + } + + /** + * @dev Calculates the asset reserves and generates the element. + */ + function _generateAssetReserves(Properties memory properties) + internal + pure + returns (string memory) + { + return string.concat( + _generateStat( + "Asset Reserves", + AssemblyLib.scaleFromWadDown( + properties.pool.virtualX, properties.pair.assetDecimals + ), + properties.pair.assetDecimals, + properties.pair.assetSymbol + ) + ); + } + + /** + * @dev Calculates the quote reserves and generates the element. + */ + function _generateQuoteReserves(Properties memory properties) + internal + pure + returns (string memory) + { + return string.concat( + _generateStat( + "Asset Reserves", + AssemblyLib.scaleFromWadDown( + properties.pool.virtualY, properties.pair.quoteDecimals + ), + properties.pair.quoteDecimals, + properties.pair.quoteSymbol + ) + ); + } + + /** + * @dev Calculates the pool valuation and generates the element. + */ + function _generatePoolValuation(Properties memory properties) + internal + pure + returns (string memory) + { + uint256 poolValuation = AssemblyLib.scaleFromWadDown( + properties.pool.virtualX, properties.pair.assetDecimals + ) + * AssemblyLib.scaleFromWadDown( + properties.pool.spotPriceWad, properties.pair.quoteDecimals + ) / 10 ** properties.pair.assetDecimals + + AssemblyLib.scaleFromWadDown( + properties.pool.virtualY, properties.pair.quoteDecimals + ); + + return string.concat( + _generateStat( + "Pool Valuation", + poolValuation, + properties.pair.quoteDecimals, + properties.pair.quoteSymbol + ) + ); + } + + /** + * @dev Generates the swap fee element. + */ + function _generateSwapFee(Properties memory properties) + internal + pure + returns (string memory) + { + return string.concat( + _generatePercentStat("Swap Fee", properties.pool.feeBasisPoints) + ); + } + + /** + * @dev Generates the footer
element. + */ + function _generateFooter(Properties memory properties) + internal + pure + returns (string memory) + { + string memory controlledLabel = properties.pool.controller == address(0) + ? "This pool is not controlled" + : string.concat( + "This pool is controlled by ", + properties.pool.controller.toHexString() + ); + + return ( + string.concat( + '

', + controlledLabel, + " and uses ", + properties.pool.hasDefaultStrategy + ? "the default strategy." + : "a custom strategy.", + "

" + ) ); } } diff --git a/contracts/libraries/StringsLib.sol b/contracts/libraries/StringsLib.sol new file mode 100644 index 00000000..9c1cb578 --- /dev/null +++ b/contracts/libraries/StringsLib.sol @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.19; + +import { Math } from "openzeppelin/utils/math/Math.sol"; + +/** + * @dev Modified version of: + * OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) + * + * Some of these functions are not really optimized, but since they are not + * supposed to be used onchain it doesn't really matter. + */ +library StringsLib { + bytes16 private constant _SYMBOLS = "0123456789abcdef"; + uint8 private constant _ADDRESS_LENGTH = 20; + + /** + * @dev The `value` string doesn't fit in the specified `length`. + */ + error StringsInsufficientHexLength(uint256 value, uint256 length); + + /** + * @dev Converts a `uint256` to its ASCII `string` decimal representation. + */ + function toString(uint256 value) internal pure returns (string memory) { + unchecked { + uint256 length = Math.log10(value) + 1; + string memory buffer = new string(length); + uint256 ptr; + /// @solidity memory-safe-assembly + assembly { + ptr := add(buffer, add(32, length)) + } + while (true) { + ptr--; + /// @solidity memory-safe-assembly + assembly { + mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) + } + value /= 10; + if (value == 0) break; + } + return buffer; + } + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. + */ + function toHexString(uint256 value) internal pure returns (string memory) { + unchecked { + return toHexString(value, Math.log256(value) + 1); + } + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. + */ + function toHexString( + uint256 value, + uint256 length + ) internal pure returns (string memory) { + uint256 localValue = value; + bytes memory buffer = new bytes(2 * length + 2); + buffer[0] = "0"; + buffer[1] = "x"; + for (uint256 i = 2 * length + 1; i > 1; --i) { + buffer[i] = _SYMBOLS[localValue & 0xf]; + localValue >>= 4; + } + if (localValue != 0) { + revert StringsInsufficientHexLength(value, length); + } + return string(buffer); + } + + /** + * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. + */ + function toHexString(address addr) internal pure returns (string memory) { + return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); + } + + function toHexColor(bytes3 value) internal pure returns (string memory) { + bytes memory result = new bytes(6); + + for (uint256 i = 0; i < 3; i++) { + result[i * 2] = _SYMBOLS[uint8(value[i] >> 4)]; + result[i * 2 + 1] = _SYMBOLS[uint8(value[i] & 0x0F)]; + } + + return string.concat("#", string(result)); + } + + function toCountdown(uint256 deadline) + internal + view + returns (string memory) + { + uint256 timeLeft = deadline - block.timestamp; + uint256 daysLeft = timeLeft / 86400; + uint256 hoursLeft = (timeLeft % 86400) / 3600; + uint256 minutesLeft = (timeLeft % 3600) / 60; + uint256 secondsLeft = timeLeft % 60; + + // TODO: Fix the plurals + if (daysLeft >= 1) { + return (string.concat("Expires in ", toString(daysLeft), " days")); + } + + if (hoursLeft >= 1) { + return (string.concat("Expires in ", toString(hoursLeft), " hours")); + } + + if (minutesLeft >= 1) { + return ( + string.concat("Expires in ", toString(minutesLeft), " minutes") + ); + } + + return (string.concat("Expires in ", toString(secondsLeft), " seconds")); + } +} diff --git a/contracts/test/ERC20Wrapper.sol b/contracts/test/ERC20Wrapper.sol new file mode 100644 index 00000000..1c5ee720 --- /dev/null +++ b/contracts/test/ERC20Wrapper.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity 0.8.19; + +import "solmate/tokens/ERC20.sol"; +import "solmate/tokens/ERC1155.sol"; + +contract ERC20Wrapper is ERC20, ERC1155TokenReceiver { + address immutable PORTFOLIO; + uint256[] public POOL_IDS; + + constructor( + address portfolio_, + uint64[] memory poolIds_, + string memory name_, + string memory symbol_ + ) ERC20(name_, symbol_, 18) { + PORTFOLIO = portfolio_; + POOL_IDS = poolIds_; + } + + function mint(address to, uint256 amount) external { + uint256[] memory amounts = new uint256[](POOL_IDS.length); + + for (uint256 i = 0; i < POOL_IDS.length; i++) { + amounts[i] = amount; + } + + ERC1155(PORTFOLIO).safeBatchTransferFrom( + msg.sender, address(this), POOL_IDS, amounts, "" + ); + + _mint(to, amount); + } + + function burn(address to, uint256 amount) external { + _burn(msg.sender, amount); + + uint256[] memory amounts = new uint256[](POOL_IDS.length); + + for (uint256 i = 0; i < POOL_IDS.length; i++) { + amounts[i] = amount; + } + + ERC1155(PORTFOLIO).safeBatchTransferFrom( + address(this), to, POOL_IDS, amounts, "" + ); + } +} diff --git a/lib/nugu b/lib/nugu index a154d73d..71fbe1e7 160000 --- a/lib/nugu +++ b/lib/nugu @@ -1 +1 @@ -Subproject commit a154d73d07cd0a099d5c9e78f9f91c9c2e505fe2 +Subproject commit 71fbe1e7e1441147886e70425cbb4f6b645ee286 diff --git a/package.json b/package.json index 017a9546..b02b842c 100644 --- a/package.json +++ b/package.json @@ -2,14 +2,17 @@ "name": "@primitivexyz/portfolio", "license": "AGPL-3.0-only", "version": "v1.4.0-beta", - "description": "Onchain protocol for low cost portfolio management using automated market making strategies.", + "description": "Portfolio is an automated market making protocol for implementing custom liquidity distribution strategies at the lowest cost possible. ", "publishConfig": { "access": "public" }, "files": [ "contracts/**/*.sol", + "optimized-out/NormalStrategy.sol/NormalStrategy.json", "optimized-out/Portfolio.sol/Portfolio.json", - "optimized-out/RMM01Portfolio.sol/RMM01Portfolio.json", + "optimized-out/PositionRenderer.sol/PositionRenderer.json", + "optimized-out/IStrategy.sol/IStrategy.json", + "optimized-out/INormalStrategy.sol/INormalStrategy.json", "optimized-out/IPortfolio.sol/IPortfolio.json", "optimized-out/IPortfolioRegistry.sol/IPortfolioRegistry.json" ], diff --git a/scripts/Deploy.s.sol b/scripts/Deploy.s.sol index b06b578d..63abc30e 100644 --- a/scripts/Deploy.s.sol +++ b/scripts/Deploy.s.sol @@ -9,58 +9,114 @@ import "../contracts/test/SimpleRegistry.sol"; import "../contracts/Portfolio.sol"; import "../contracts/PositionRenderer.sol"; +// This script allows you to deploy the Portfolio contract and its dependencies, +// you can learn how to use it in our documentation: +// https://docs.primitive.xyz/protocol/contracts/deployments#deploying-portfolio contract Deploy is Script { - function run(address weth, address registry) external { + function printJSON( + string memory name, + address at, + string memory status, + bool isLast + ) private view { + console.log( + string.concat( + '"%s":{"address":"%s","status":"%s"}', isLast ? "" : "," + ), + name, + at, + status + ); + } + + function deployIfNecessary( + NuguFactory nugu, + address deployer, + string memory name, + bytes memory creationCode, + bytes32 salt + ) private returns (address at) { + at = nugu.getDeployed(deployer, salt); + + if (at.code.length == 0) { + nugu.deploy(salt, creationCode, 0); + printJSON(name, at, "deployed", false); + } else { + printJSON(name, at, "skipped", false); + } + } + + function run(address factory, address weth, address registry) external { + console.log("{"); uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); vm.startBroadcast(deployerPrivateKey); // Here we specify the factory we want to use - NuguFactory factory = - NuguFactory(0x0000A79C3D8124ED3a7F8EC8427E4DC43a2B154d); + NuguFactory nugu = NuguFactory(factory); - // Let's check if the contract is deployed on this network + // Let's check if the factory contract is deployed on this network, if + // it's not, it's better to avoid deploying it from here, as the address + // is canonical across all networks, we need a specific script for that. require( - address(factory).code.length > 0, + address(nugu).code.length > 0, "Nugu Factory not deployed on this network!" ); // If no WETH address is provided, we deploy a new contract if (weth == address(0)) { - weth = factory.deploy(keccak256("WETH"), type(WETH).creationCode, 0); + deployIfNecessary( + nugu, + vm.addr(deployerPrivateKey), + "WETH", + type(WETH).creationCode, + keccak256("WETH") + ); + } else { + printJSON("WETH", weth, "reused", false); } // Same thing for the Portfolio registry if (registry == address(0)) { - registry = factory.deploy( - keccak256("SimpleRegistry"), + deployIfNecessary( + nugu, + vm.addr(deployerPrivateKey), + "Registry", type(SimpleRegistry).creationCode, - 0 + keccak256(type(SimpleRegistry).creationCode) ); + } else { + printJSON("Registry", registry, "reused", false); } // First we deploy the PositionRenderer contract - address positionRenderer = factory.deploy( - keccak256("PositionRenderer"), + address positionRenderer = deployIfNecessary( + nugu, + vm.addr(deployerPrivateKey), + "PositionRenderer", type(PositionRenderer).creationCode, - 0 + keccak256(type(PositionRenderer).creationCode) ); // Then we can deploy the Portfolio contract - address portfolio = factory.deploy( - keccak256("Portfolio"), + address portfolio = deployIfNecessary( + nugu, + vm.addr(deployerPrivateKey), + "Portfolio", abi.encodePacked( type(Portfolio).creationCode, abi.encode(weth, registry, positionRenderer) ), - 0 + 0x8B9A3E646B237114DA81624C540FBA61A7E7FFFEA48B90454E66F547AA5B706C ); - console.log(unicode"🚀 Contracts deployed!"); - console.log("WETH:", weth); - console.log("Registry:", registry); - console.log("PositionRenderer:", positionRenderer); - console.log("Portfolio:", portfolio); + printJSON( + "NormalStrategy", + Portfolio(payable(portfolio)).DEFAULT_STRATEGY(), + "deployed", + true + ); vm.stopBroadcast(); + console.log("}"); } } diff --git a/scripts/Prepare.s.sol b/scripts/Prepare.s.sol new file mode 100644 index 00000000..1920ee32 --- /dev/null +++ b/scripts/Prepare.s.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; +import "solmate/tokens/WETH.sol"; +import "nugu/NuguFactory.sol"; + +import "../contracts/PortfolioRegistry.sol"; +import "../contracts/Portfolio.sol"; +import "../contracts/PositionRenderer.sol"; + +// This script prepares all the transaction data that must be used to deploy +// Portfolio and its dependency contracts. +// +// Here are the steps to use it: +// 1. Be sure to update all the constants below: contract addresses and salts. +// 2. Run the script with: +// `forge script ./scripts/Prepare.s.sol --via-ir --optimizer-runs 0`. +// +// If you want to deploy from a Safe Wallet, you can follow the steps below: +// 3. Visit https://app.safe.global/, click on your multisig wallet, then on +// "New transaction" and finally "Transaction builder". +// 4. Paste the address of the Nugu factory and enable the "custom data". +// 5. Then for each data generated by this script (3 in total), you'll need to +// copy and paste it into the "data" field of the transaction builder and click +// the "Add transaction" button. +// 6. After that, a total of 3 transactions must compose the batch. You can then +// hit "Create Batch", and either "Simulate" or directly "Send Batch". +// 7. Last step is simply to follow the instructions to send the transaction. +// +// If you want to deploy from a hardware wallet, you can follow the steps below: +// 3. Visit any website allowing you to send a transaction with custom data (such +// as https://www.myetherwallet.com/). +// 4. Paste the address of the Nugu factory as a recipient, paste the first custom +// data that was generated and send the transaction. +// 5. Repeat step 4 for all the data generated by this script (3 in total). + +address constant MULTISIG_WALLET = 0x8cDb0095ceddb092aD592aCE2971e4f364b5E8eE; +address constant NUGU_ADDRESS = 0xe50ea0e9849cb17829907Acaf764af8F37d4938E; +address constant WETH_ADDRESS = 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6; + +bytes32 constant REGISTRY_SALT = keccak256("REGISTRY0"); +bytes32 constant POSITION_RENDERER_SALT = keccak256("POSITION_RENDERER0"); +bytes32 constant PORTFOLIO_SALT = keccak256("PORTFOLIO0"); + +contract Deploy is Script { + bytes internal constant PROXY_BYTECODE = + hex"67363d3d37363d34f03d5260086018f3"; + bytes32 internal constant PROXY_BYTECODE_HASH = keccak256(PROXY_BYTECODE); + + function run() external { + bytes memory registryDeployData = abi.encodeCall( + NuguFactory.deploy, + ( + REGISTRY_SALT, + abi.encodePacked( + type(PortfolioRegistry).creationCode, + abi.encode(MULTISIG_WALLET) + ), + 0 + ) + ); + + bytes memory positionRendererDeployData = abi.encodeCall( + NuguFactory.deploy, + (POSITION_RENDERER_SALT, type(PositionRenderer).creationCode, 0) + ); + + address predictedRegistryAddress = + getDeployed(NUGU_ADDRESS, MULTISIG_WALLET, REGISTRY_SALT); + + address predictedPositionRendererAddress = + getDeployed(NUGU_ADDRESS, MULTISIG_WALLET, POSITION_RENDERER_SALT); + + bytes memory portfolioDeployData = abi.encodeCall( + NuguFactory.deploy, + ( + PORTFOLIO_SALT, + abi.encodePacked( + type(Portfolio).creationCode, + abi.encode( + WETH_ADDRESS, + predictedRegistryAddress, + predictedPositionRendererAddress + ) + ), + 0 + ) + ); + + console.log("\nRegistry deploy data:"); + console.logBytes(registryDeployData); + + console.log("\nPositionRenderer deploy data:"); + console.logBytes(positionRendererDeployData); + + console.log("\nPortfolio deploy data:"); + console.logBytes(portfolioDeployData); + } + + function getDeployed( + address factory, + address deployer, + bytes32 salt + ) internal view returns (address) { + salt = keccak256(abi.encodePacked(deployer, salt)); + + address proxy = Bytes32AddressLib.fromLast20Bytes( + keccak256( + abi.encodePacked( + bytes1(0xFF), factory, salt, PROXY_BYTECODE_HASH + ) + ) + ); + + return Bytes32AddressLib.fromLast20Bytes( + keccak256(abi.encodePacked(hex"d694", proxy, hex"01")) + ); + } +} diff --git a/scripts/TestDeploy.s.sol b/scripts/TestDeploy.s.sol new file mode 100644 index 00000000..67a946c6 --- /dev/null +++ b/scripts/TestDeploy.s.sol @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; +import "solmate/test/utils/mocks/MockERC20.sol"; + +import "../contracts/test/SimpleRegistry.sol"; +import "../contracts/Portfolio.sol"; +import "../contracts/PositionRenderer.sol"; +import "../contracts/libraries/AssemblyLib.sol"; + +contract TestDeploy is Script { + function run() external { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + address sender = vm.addr(deployerPrivateKey); + console.log("Sender:", sender); + vm.startBroadcast(deployerPrivateKey); + + MockERC20 usdt = new MockERC20("USDT", "USDT", 18); + MockERC20 dai = new MockERC20("DAI", "DAI", 18); + MockERC20 weth = new MockERC20("Wrapped Ether", "WETH", 18); + MockERC20 usdc = new MockERC20("USD Coin", "USDC", 6); + + address registry = address(new SimpleRegistry()); + address positionRenderer = address(new PositionRenderer()); + Portfolio portfolio = + new Portfolio(address(weth), registry, positionRenderer); + + // USDT - DAI + + uint64 poolId = _createPool( + portfolio, + address(usdt), + address(dai), + AssemblyLib.scaleToWad(1 ether, 18) + ); + _allocate(sender, portfolio, poolId, usdt, dai, 1000 ether, 1000 ether); + + // USDT - USDC + + poolId = _createPool( + portfolio, + address(usdt), + address(usdc), + AssemblyLib.scaleToWad(1 * 10 ** 6, 6) + ); + _allocate( + sender, portfolio, poolId, usdt, usdc, 2000 ether, 2000 * 10 ** 6 + ); + + // WETH - USDC + poolId = _createPool( + portfolio, + address(weth), + address(usdc), + AssemblyLib.scaleToWad(2000 * 10 ** 6, 6) + ); + _allocate( + sender, portfolio, poolId, weth, usdc, 2 ether, 4000 * 10 ** 6 + ); + + console.log(unicode"🚀 Contracts deployed!"); + console.log("Portfolio:", address(portfolio)); + + vm.stopBroadcast(); + } + + function _createPool( + Portfolio portfolio, + address asset, + address quote, + uint256 price + ) public returns (uint64) { + uint24 pairId = portfolio.getPairId(asset, quote); + + if (pairId == 0) pairId = portfolio.createPair(asset, quote); + + (bytes memory strategyData, uint256 initialX, uint256 initialY) = + INormalStrategy(portfolio.DEFAULT_STRATEGY()).getStrategyData( + price, 1_00, 3 days, false, price + ); + + uint64 poolId = portfolio.createPool( + pairId, + initialX, + initialY, + 100, + 0, + address(0), + address(0), + strategyData + ); + + return poolId; + } + + function _allocate( + address sender, + Portfolio portfolio, + uint64 poolId, + MockERC20 asset, + MockERC20 quote, + uint128 amount0, + uint128 amount1 + ) public { + asset.mint(sender, amount0); + asset.approve(address(portfolio), amount0); + quote.mint(sender, amount1); + quote.approve(address(portfolio), amount1); + + uint128 deltaLiquidity = + portfolio.getMaxLiquidity(poolId, amount0, amount1); + + (uint128 deltaAsset, uint128 deltaQuote) = + portfolio.getLiquidityDeltas(poolId, int128(deltaLiquidity)); + + portfolio.allocate( + false, sender, poolId, deltaLiquidity, deltaAsset, deltaQuote + ); + } +} diff --git a/test/ETHSP.t.sol b/test/ETHSP.t.sol new file mode 100644 index 00000000..029420a1 --- /dev/null +++ b/test/ETHSP.t.sol @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.4; + +import "solmate/test/utils/mocks/MockERC20.sol"; +import "solmate/utils/SafeCastLib.sol"; +import "../contracts/test/ERC20Wrapper.sol"; + +import "./Setup.sol"; + +using SafeCastLib for uint256; + +function to128(uint256 x) pure returns (uint128 y) { + y = x.safeCastTo128(); +} + +contract ETHSP is Setup { + using { to128 } for uint256; + using NormalConfiguration for Configuration; + + Configuration CONFIG; + + address TOKEN_0; + address TOKEN_1; + address TOKEN_2; + address TOKEN_3; + + uint64 TRANCHE_A_POOL; + uint64 TRANCHE_B_POOL; + + address TRANCHE_A_TOKEN; + address TRANCHE_B_TOKEN; + + address ETHSP_TOKEN; + + address PRIMARY_MARKET_USER; + + function create_actor() public { + PRIMARY_MARKET_USER = address(0x0444); + } + + modifier usePrimaryMarketUser() { + vm.startPrank(PRIMARY_MARKET_USER); + _; + vm.stopPrank(); + } + + /// @dev ETHSP is a pool of two liquidity pool tokens. + function test_ethsp() public { + create_actor(); + + _create_tokens(); + _create_pairs(); + _create_tranche_pools(); + _tokenize_tranches(); + _tokenize_ethsp(); + + approve_tokens(); + allocate(); + issue(); + rebalance(); + } + + function approve_tokens() public usePrimaryMarketUser { + // Approves tokens to subject (portfolio) + MockERC20(TOKEN_0).approve(address(subject()), type(uint256).max); + MockERC20(TOKEN_1).approve(address(subject()), type(uint256).max); + MockERC20(TOKEN_2).approve(address(subject()), type(uint256).max); + MockERC20(TOKEN_3).approve(address(subject()), type(uint256).max); + + // Approve tokenized pools to subject (portfolio) + MockERC20(TRANCHE_A_TOKEN).approve( + address(subject()), type(uint256).max + ); + MockERC20(TRANCHE_B_TOKEN).approve( + address(subject()), type(uint256).max + ); + MockERC20(ETHSP_TOKEN).approve(address(subject()), type(uint256).max); + } + + function allocate() public usePrimaryMarketUser { + // Allocate 10 liquidity to each tranche + uint256 amount = 10 ether; + + bytes[] memory calls = new bytes[](2); + calls[0] = abi.encodeWithSelector( + IPortfolioActions.allocate.selector, + false, + PRIMARY_MARKET_USER, + TRANCHE_A_POOL, + amount, + type(uint128).max, + type(uint128).max + ); + + calls[1] = abi.encodeWithSelector( + IPortfolioActions.allocate.selector, + false, + PRIMARY_MARKET_USER, + TRANCHE_B_POOL, + amount, + type(uint128).max, + type(uint128).max + ); + + subject().multicall(calls); + } + + function issue() public usePrimaryMarketUser { + // Gets amounts of liquidity to wrap into ETHSP token. + uint256 amount = 1 ether; + ERC1155(address(subject())).setApprovalForAll(ETHSP_TOKEN, true); + ERC1155(address(subject())).setApprovalForAll(ETHSP_TOKEN, true); + ERC20Wrapper(ETHSP_TOKEN).mint(PRIMARY_MARKET_USER, amount); + } + + function rebalance() public usePrimaryMarketUser { + // Assume I receive 1 ETHSP token. + // For example, I purchase it on a DEX for $0.9, + // but the underlying assets are worth $1.0. + // I want to redeem it for the underlying assest and sell it into the market. + + uint256[4] memory startBalances = [ + MockERC20(TOKEN_0).balanceOf(PRIMARY_MARKET_USER), + MockERC20(TOKEN_1).balanceOf(PRIMARY_MARKET_USER), + MockERC20(TOKEN_2).balanceOf(PRIMARY_MARKET_USER), + MockERC20(TOKEN_3).balanceOf(PRIMARY_MARKET_USER) + ]; + + // Redeem ETHSP + uint256 amount = 1 ether; + ERC20Wrapper(ETHSP_TOKEN).burn(PRIMARY_MARKET_USER, amount); + + // Remove liquidity from both ERC115 pool tokens. + bytes[] memory calls = new bytes[](2); + calls[0] = abi.encodeWithSelector( + IPortfolioActions.deallocate.selector, + false, + TRANCHE_A_POOL, + amount, + 0, + 0 + ); + calls[1] = abi.encodeWithSelector( + IPortfolioActions.deallocate.selector, + false, + TRANCHE_B_POOL, + amount, + 0, + 0 + ); + + subject().multicall(calls); + + uint256[4] memory endBalances = [ + MockERC20(TOKEN_0).balanceOf(PRIMARY_MARKET_USER), + MockERC20(TOKEN_1).balanceOf(PRIMARY_MARKET_USER), + MockERC20(TOKEN_2).balanceOf(PRIMARY_MARKET_USER), + MockERC20(TOKEN_3).balanceOf(PRIMARY_MARKET_USER) + ]; + + uint256[4] memory deltas = [ + endBalances[0] - startBalances[0], + endBalances[1] - startBalances[1], + endBalances[2] - startBalances[2], + endBalances[3] - startBalances[3] + ]; + + console2.log("ethsp delta: -", amount); + for (uint256 i; i < deltas.length; i++) { + emit delta(i, deltas[i]); + } + + // Send the tokens to pay the DEX, or anyone else, back! + } + + event delta(uint256 i, uint256 amt); + + function _create_tokens() internal { + // Basket A + TOKEN_0 = address(new MockERC20("Token0", "0", 18)); + TOKEN_1 = address(new MockERC20("Token1", "1", 18)); + + // Basket B + TOKEN_2 = address(new MockERC20("Token2", "2", 18)); + TOKEN_3 = address(new MockERC20("Token3", "3", 18)); + + // Labels + vm.label(TOKEN_0, "Token0"); + vm.label(TOKEN_1, "Token1"); + vm.label(TOKEN_2, "Token2"); + vm.label(TOKEN_3, "Token3"); + + // Mint some tokens to primary market user. + MockERC20(TOKEN_0).mint(PRIMARY_MARKET_USER, 1_000_000_000 ether); + MockERC20(TOKEN_1).mint(PRIMARY_MARKET_USER, 1_000_000_000 ether); + MockERC20(TOKEN_2).mint(PRIMARY_MARKET_USER, 1_000_000_000 ether); + MockERC20(TOKEN_3).mint(PRIMARY_MARKET_USER, 1_000_000_000 ether); + } + + function _create_pairs() internal { + // Create both pairs + uint24 TRANCHE_A_PAIR = subject().createPair(TOKEN_0, TOKEN_1); + uint24 TRANCHE_B_PAIR = subject().createPair(TOKEN_2, TOKEN_3); + } + + function _create_tranche_pools() internal { + // Create both pools + uint256 volatility_bps = 1000; + uint256 duration_sec = SECONDS_PER_YEAR; + uint256 strike_price = 2000 ether; + uint256 last_price = 1800 ether; + uint256 fee_bps = 10; + uint256 priority_fee_bps = 0; + + // Pool config is specific to the NormalStrategy. + PortfolioConfig memory POOL_CONFIG = PortfolioConfig({ + strikePriceWad: strike_price.to128(), + volatilityBasisPoints: volatility_bps.safeCastTo32(), + durationSeconds: duration_sec.safeCastTo32(), + isPerpetual: false, + creationTimestamp: uint32(block.timestamp) + }); + + // Makes a defaut config which defines the Portfolio pool state. + CONFIG = configure(); + // Edits the fee of the pool. + CONFIG = CONFIG.edit("feeBasisPoints", abi.encode(fee_bps)).edit( + "priorityFeeBasisPoints", abi.encode(priority_fee_bps) + ); + // Adds the strategy specific arguments to the config, by computing the reserves and also encoding the strategy data. + CONFIG = CONFIG.combine(POOL_CONFIG); + // Updates the strategy to have the reserves match a price. + CONFIG = CONFIG.editStrategy("priceWad", abi.encode(last_price)); + // Applies the respective tokens to each config. + Configuration memory TRANCHE_A_CONFIG = CONFIG.edit( + "asset", abi.encode(TOKEN_0) + ).edit("quote", abi.encode(TOKEN_1)); + + Configuration memory TRANCHE_B_CONFIG = CONFIG.edit( + "asset", abi.encode(TOKEN_2) + ).edit("quote", abi.encode(TOKEN_3)); + // Creates the pools with the configs. + TRANCHE_A_POOL = TRANCHE_A_CONFIG.activate( + address(subject()), NormalConfiguration.validateNormalStrategy + ); + TRANCHE_B_POOL = TRANCHE_B_CONFIG.activate( + address(subject()), NormalConfiguration.validateNormalStrategy + ); + } + + function _tokenize_tranches() public { + uint64[] memory a_pools = new uint64[](1); + a_pools[0] = TRANCHE_A_POOL; + TRANCHE_A_TOKEN = address( + new ERC20Wrapper( + address(subject()), + a_pools, + "ETHSP Tranche A", + "ETHSP-A" + ) + ); + + uint64[] memory b_pools = new uint64[](1); + b_pools[0] = TRANCHE_B_POOL; + TRANCHE_B_TOKEN = address( + new ERC20Wrapper( + address(subject()), + b_pools, + "ETHSP Tranche B", + "ETHSP-B" + ) + ); + + // Labels + vm.label(TRANCHE_A_TOKEN, "ETHSP Tranche A"); + vm.label(TRANCHE_B_TOKEN, "ETHSP Tranche B"); + } + + function _tokenize_ethsp() public { + uint64[] memory ethsp_pools = new uint64[](2); + ethsp_pools[0] = TRANCHE_A_POOL; + ethsp_pools[1] = TRANCHE_B_POOL; + ETHSP_TOKEN = address( + new ERC20Wrapper( + address(subject()), + ethsp_pools, + "ETHSP", + "ETHSP" + ) + ); + + // Labels + vm.label(ETHSP_TOKEN, "ETHSP"); + } +} diff --git a/test/TestPortfolioUri.t.sol b/test/TestPortfolioBalanceOf.t.sol similarity index 60% rename from test/TestPortfolioUri.t.sol rename to test/TestPortfolioBalanceOf.t.sol index 9dca2951..396941fc 100644 --- a/test/TestPortfolioUri.t.sol +++ b/test/TestPortfolioBalanceOf.t.sol @@ -1,48 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.4; -import "openzeppelin/utils/Base64.sol"; import "solmate/tokens/ERC1155.sol"; +import "../contracts/libraries/AssemblyLib.sol"; import "./Setup.sol"; +import "../contracts/strategies/NormalStrategy.sol"; -contract TestPortfolioUri is Setup { - function test_uri() public defaultConfig useActor usePairTokens(10 ether) { - subject().allocate( - false, - address(this), - ghost().poolId, - 1 ether, - type(uint128).max, - type(uint128).max - ); - - string memory uri = ERC1155(address(subject())).uri(ghost().poolId); - console.log(uri); - } - - function test_balanceOf_allocating_sets_balance() - public - defaultConfig - useActor - usePairTokens(10 ether) - { - uint128 liquidity = 1 ether; - - subject().allocate( - false, - address(this), - ghost().poolId, - liquidity, - type(uint128).max, - type(uint128).max - ); - - assertEq( - ERC1155(address(subject())).balanceOf(address(this), ghost().poolId), - liquidity - BURNED_LIQUIDITY - ); - } - +contract TestPortfolioBalanceOf is Setup { function test_balanceOf_allocating_increases_balance() public defaultConfig diff --git a/test/TestPortfolioRegistry.t.sol b/test/TestPortfolioRegistry.t.sol new file mode 100644 index 00000000..25d7a544 --- /dev/null +++ b/test/TestPortfolioRegistry.t.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.4; + +import "forge-std/Test.sol"; +import "../contracts/PortfolioRegistry.sol"; + +contract TestPortfolioRegistry is Test { + PortfolioRegistry public registry; + + function test_controller() public { + registry = new PortfolioRegistry(address(this)); + assertEq(registry.controller(), address(this)); + } +} diff --git a/test/TestPositionRendererUri.t.sol b/test/TestPositionRendererUri.t.sol new file mode 100644 index 00000000..cf3346d7 --- /dev/null +++ b/test/TestPositionRendererUri.t.sol @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.4; + +import "solmate/tokens/ERC1155.sol"; +import "../contracts/libraries/AssemblyLib.sol"; +import "./Setup.sol"; +import "../contracts/strategies/NormalStrategy.sol"; + +contract TestPositionRendererUri is Setup { + struct MetaContext { + address asset; + address quote; + uint256 strikePriceWad; + uint256 durationSeconds; + uint16 swapFee; + bool isPerpetual; + uint256 priceWad; + address controller; + address strategy; + uint16 prioritySwapFee; + } + + function _createPool(MetaContext memory ctx) + public + returns (uint64 poolId) + { + uint24 pairId = subject().getPairId(ctx.asset, ctx.quote); + + if (pairId == 0) { + pairId = subject().createPair(ctx.asset, ctx.quote); + } + + (bytes memory strategyData, uint256 initialX, uint256 initialY) = + INormalStrategy(subject().DEFAULT_STRATEGY()).getStrategyData( + ctx.strikePriceWad, + 1_00, // volatilityBasisPoints + ctx.durationSeconds, + ctx.isPerpetual, + ctx.priceWad + ); + + poolId = subject().createPool( + pairId, + initialX, + initialY, + ctx.swapFee, + ctx.prioritySwapFee, + ctx.controller, + ctx.strategy, + strategyData + ); + } + + function _allocate( + MetaContext memory ctx, + uint64 poolId, + uint256 amount0, + uint256 amount1 + ) public { + MockERC20(ctx.asset).mint(address(this), amount0); + MockERC20(ctx.asset).approve(address(subject()), amount0); + MockERC20(ctx.quote).mint(address(this), amount1); + MockERC20(ctx.quote).approve(address(subject()), amount1); + + uint128 deltaLiquidity = + subject().getMaxLiquidity(poolId, amount0, amount1); + + (uint128 deltaAsset, uint128 deltaQuote) = + subject().getLiquidityDeltas(poolId, int128(deltaLiquidity)); + + subject().allocate( + false, address(this), poolId, deltaLiquidity, deltaAsset, deltaQuote + ); + } + + function test_uri() public { + MetaContext memory ctx = MetaContext({ + asset: address(new MockERC20("Ethereum", "ETH", 18)), + quote: address(new MockERC20("USD Coin", "USDC", 6)), + strikePriceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + durationSeconds: 86_400 * 3, + swapFee: 400, + isPerpetual: false, + priceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + controller: address(0), + strategy: address(0), + prioritySwapFee: 0 + }); + + uint64 poolId = _createPool(ctx); + _allocate(ctx, poolId, 1 ether, 2_000 * 10 ** 6); + console.log(ERC1155(address(subject())).uri(poolId)); + } + + function test_uri_controlled_pool() public { + MetaContext memory ctx = MetaContext({ + asset: address(new MockERC20("Ethereum", "ETH", 18)), + quote: address(new MockERC20("USD Coin", "USDC", 6)), + strikePriceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + durationSeconds: 86_400 * 3, + swapFee: 400, + isPerpetual: false, + priceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + controller: address(this), + strategy: address(0), + prioritySwapFee: 200 + }); + + uint64 poolId = _createPool(ctx); + _allocate(ctx, poolId, 1 ether, 2_000 * 10 ** 6); + console.log(ERC1155(address(subject())).uri(poolId)); + } + + function test_uri_perpetual() public { + MetaContext memory ctx = MetaContext({ + asset: address(new MockERC20("Ethereum", "ETH", 18)), + quote: address(new MockERC20("USD Coin", "USDC", 6)), + strikePriceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + durationSeconds: 86_400 * 3, + swapFee: 400, + isPerpetual: true, + priceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + controller: address(0), + strategy: address(0), + prioritySwapFee: 0 + }); + + uint64 poolId = _createPool(ctx); + _allocate(ctx, poolId, 1 ether, 2_000 * 10 ** 6); + console.log(ERC1155(address(subject())).uri(poolId)); + } + + function test_uri_custom_strategy() public { + MetaContext memory ctx = MetaContext({ + asset: address(new MockERC20("Ethereum", "ETH", 18)), + quote: address(new MockERC20("USD Coin", "USDC", 6)), + strikePriceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + durationSeconds: 86_400 * 3, + swapFee: 400, + isPerpetual: false, + priceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + controller: address(0), + strategy: address(new NormalStrategy(address(subject()))), + prioritySwapFee: 0 + }); + + uint64 poolId = _createPool(ctx); + _allocate(ctx, poolId, 1 ether, 2_000 * 10 ** 6); + console.log(ERC1155(address(subject())).uri(poolId)); + } + + function test_uri_controlled_custom_strategy() public { + MetaContext memory ctx = MetaContext({ + asset: address(new MockERC20("Ethereum", "ETH", 18)), + quote: address(new MockERC20("USD Coin", "USDC", 6)), + strikePriceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + durationSeconds: 86_400 * 3, + swapFee: 400, + isPerpetual: false, + priceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + controller: address(this), + strategy: address(new NormalStrategy(address(subject()))), + prioritySwapFee: 100 + }); + + uint64 poolId = _createPool(ctx); + _allocate(ctx, poolId, 1 ether, 2_000 * 10 ** 6); + console.log(ERC1155(address(subject())).uri(poolId)); + } + + function test_uri_many_pools() public { + MetaContext memory ctx = MetaContext({ + asset: address(new MockERC20("Ethereum", "ETH", 18)), + quote: address(new MockERC20("USD Coin", "USDC", 6)), + strikePriceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + durationSeconds: 86_400 * 3, + swapFee: 400, + isPerpetual: false, + priceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6), + controller: address(0), + strategy: address(0), + prioritySwapFee: 0 + }); + + _createPool(ctx); + _createPool(ctx); + uint64 poolId = _createPool(ctx); + _allocate(ctx, poolId, 1 ether, 2_000 * 10 ** 6); + console.log(ERC1155(address(subject())).uri(poolId)); + } +} diff --git a/yarn.lock b/yarn.lock index f607f54a..5b7de8ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,36 +3,37 @@ "@babel/code-frame@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.10.tgz#1c20e612b768fefa75f6e90d6ecb86329247f0a3" + integrity sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA== dependencies: - "@babel/highlight" "^7.18.6" + "@babel/highlight" "^7.22.10" + chalk "^2.4.2" -"@babel/helper-validator-identifier@^7.18.6": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-validator-identifier@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" + integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== +"@babel/highlight@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.10.tgz#02a3f6d8c1cb4521b2fd0ab0da8f4739936137d7" + integrity sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ== dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" + "@babel/helper-validator-identifier" "^7.22.5" + chalk "^2.4.2" js-tokens "^4.0.0" "@commitlint/cli@^17.4.2": - version "17.4.2" - resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-17.4.2.tgz#8600c83abb7e84191fd59528fc14f436496fb00b" - integrity sha512-0rPGJ2O1owhpxMIXL9YJ2CgPkdrFLKZElIZHXDN8L8+qWK1DGH7Q7IelBT1pchXTYTuDlqkOTdh//aTvT3bSUA== - dependencies: - "@commitlint/format" "^17.4.0" - "@commitlint/lint" "^17.4.2" - "@commitlint/load" "^17.4.2" - "@commitlint/read" "^17.4.2" - "@commitlint/types" "^17.4.0" + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-17.7.0.tgz#c62213abdf47764704c8dc3d2ca5f53fb1fa1371" + integrity sha512-28PNJaGuBQZNoz3sd+6uO3b4+5PY+vWzyBfy5JOvFB7QtoZVXf2FYTQs5VO1cn7yAd3y9/0Rx0x6Vx82W/zhuA== + dependencies: + "@commitlint/format" "^17.4.4" + "@commitlint/lint" "^17.7.0" + "@commitlint/load" "^17.7.0" + "@commitlint/read" "^17.5.1" + "@commitlint/types" "^17.4.4" execa "^5.0.0" lodash.isfunction "^3.0.9" resolve-from "5.0.0" @@ -46,20 +47,20 @@ dependencies: conventional-changelog-conventionalcommits "^5.0.0" -"@commitlint/config-validator@^17.4.0": - version "17.4.0" - resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-17.4.0.tgz#2cb229672a22476cf1f21bedbfcd788e5da5b54f" - integrity sha512-Sa/+8KNpDXz4zT4bVbz2fpFjvgkPO6u2V2fP4TKgt6FjmOw2z3eEX859vtfeaTav/ukBw0/0jr+5ZTZp9zCBhA== +"@commitlint/config-validator@^17.6.7": + version "17.6.7" + resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-17.6.7.tgz#c664d42a1ecf5040a3bb0843845150f55734df41" + integrity sha512-vJSncmnzwMvpr3lIcm0I8YVVDJTzyjy7NZAeXbTXy+MPUdAr9pKyyg7Tx/ebOQ9kqzE6O9WT6jg2164br5UdsQ== dependencies: - "@commitlint/types" "^17.4.0" + "@commitlint/types" "^17.4.4" ajv "^8.11.0" -"@commitlint/ensure@^17.4.0": - version "17.4.0" - resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-17.4.0.tgz#3de65768bfccb9956ec3a0ecd8a415421bf315e5" - integrity sha512-7oAxt25je0jeQ/E0O/M8L3ADb1Cvweu/5lc/kYF8g/kXatI0wxGE5La52onnAUAWeWlsuvBNar15WcrmDmr5Mw== +"@commitlint/ensure@^17.6.7": + version "17.6.7" + resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-17.6.7.tgz#77a77a0c05e6a1c34589f59e82e6cb937101fc4b" + integrity sha512-mfDJOd1/O/eIb/h4qwXzUxkmskXDL9vNPnZ4AKYKiZALz4vHzwMxBSYtyL2mUIDeU9DRSpEUins8SeKtFkYHSw== dependencies: - "@commitlint/types" "^17.4.0" + "@commitlint/types" "^17.4.4" lodash.camelcase "^4.3.0" lodash.kebabcase "^4.1.1" lodash.snakecase "^4.1.1" @@ -71,98 +72,95 @@ resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz#4518e77958893d0a5835babe65bf87e2638f6939" integrity sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA== -"@commitlint/format@^17.4.0": - version "17.4.0" - resolved "https://registry.yarnpkg.com/@commitlint/format/-/format-17.4.0.tgz#1c80cf3a6274ff9b3d3c0dd150a97882d557aa0f" - integrity sha512-Z2bWAU5+f1YZh9W76c84J8iLIWIvvm+mzqogTz0Nsc1x6EHW0Z2gI38g5HAjB0r0I3ZjR15IDEJKhsxyblcyhA== +"@commitlint/format@^17.4.4": + version "17.4.4" + resolved "https://registry.yarnpkg.com/@commitlint/format/-/format-17.4.4.tgz#0f6e1b4d7a301c7b1dfd4b6334edd97fc050b9f5" + integrity sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ== dependencies: - "@commitlint/types" "^17.4.0" + "@commitlint/types" "^17.4.4" chalk "^4.1.0" -"@commitlint/is-ignored@^17.4.2": - version "17.4.2" - resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-17.4.2.tgz#2d40a34e071c3e595e485fafe8460457a7b7af9d" - integrity sha512-1b2Y2qJ6n7bHG9K6h8S4lBGUl6kc7mMhJN9gy1SQfUZqe92ToDjUTtgNWb6LbzR1X8Cq4SEus4VU8Z/riEa94Q== +"@commitlint/is-ignored@^17.7.0": + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-17.7.0.tgz#df9b284420bdb1aed5fdb2be44f4e98cc4826014" + integrity sha512-043rA7m45tyEfW7Zv2vZHF++176MLHH9h70fnPoYlB1slKBeKl8BwNIlnPg4xBdRBVNPaCqvXxWswx2GR4c9Hw== dependencies: - "@commitlint/types" "^17.4.0" - semver "7.3.8" + "@commitlint/types" "^17.4.4" + semver "7.5.4" -"@commitlint/lint@^17.4.2": - version "17.4.2" - resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-17.4.2.tgz#1277cb4d5395e9d6c39cbc351984bac9dcc6b7cd" - integrity sha512-HcymabrdBhsDMNzIv146+ZPNBPBK5gMNsVH+el2lCagnYgCi/4ixrHooeVyS64Fgce2K26+MC7OQ4vVH8wQWVw== +"@commitlint/lint@^17.7.0": + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-17.7.0.tgz#33f831298dc43679e4de6b088aea63d1f884c7e7" + integrity sha512-TCQihm7/uszA5z1Ux1vw+Nf3yHTgicus/+9HiUQk+kRSQawByxZNESeQoX9ujfVd3r4Sa+3fn0JQAguG4xvvbA== dependencies: - "@commitlint/is-ignored" "^17.4.2" - "@commitlint/parse" "^17.4.2" - "@commitlint/rules" "^17.4.2" - "@commitlint/types" "^17.4.0" + "@commitlint/is-ignored" "^17.7.0" + "@commitlint/parse" "^17.7.0" + "@commitlint/rules" "^17.7.0" + "@commitlint/types" "^17.4.4" -"@commitlint/load@^17.4.2": - version "17.4.2" - resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-17.4.2.tgz#551875c3e1dce6dc0375dc9c8ad551de8ba35de4" - integrity sha512-Si++F85rJ9t4hw6JcOw1i2h0fdpdFQt0YKwjuK4bk9KhFjyFkRxvR3SB2dPaMs+EwWlDrDBGL+ygip1QD6gmPw== +"@commitlint/load@^17.7.0": + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-17.7.0.tgz#2d69479bff3feec7966906988a39584aedd08574" + integrity sha512-jHKErVteyENYKkUiESNE6JYbaU4Sx58HXqv09/p7cKHzTtfyperlRvyqqTnxS8bas5Jjg4MP3MDZwdBrgRm8lw== dependencies: - "@commitlint/config-validator" "^17.4.0" + "@commitlint/config-validator" "^17.6.7" "@commitlint/execute-rule" "^17.4.0" - "@commitlint/resolve-extends" "^17.4.0" - "@commitlint/types" "^17.4.0" - "@types/node" "*" + "@commitlint/resolve-extends" "^17.6.7" + "@commitlint/types" "^17.4.4" chalk "^4.1.0" cosmiconfig "^8.0.0" - cosmiconfig-typescript-loader "^4.0.0" + cosmiconfig-typescript-loader "^5.0.0" lodash.isplainobject "^4.0.6" lodash.merge "^4.6.2" lodash.uniq "^4.5.0" resolve-from "^5.0.0" - ts-node "^10.8.1" - typescript "^4.6.4" "@commitlint/message@^17.4.2": version "17.4.2" resolved "https://registry.yarnpkg.com/@commitlint/message/-/message-17.4.2.tgz#f4753a79701ad6db6db21f69076e34de6580e22c" integrity sha512-3XMNbzB+3bhKA1hSAWPCQA3lNxR4zaeQAQcHj0Hx5sVdO6ryXtgUBGGv+1ZCLMgAPRixuc6en+iNAzZ4NzAa8Q== -"@commitlint/parse@^17.4.2": - version "17.4.2" - resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-17.4.2.tgz#b0f8a257a1f93387a497408b0b4cadba60ee3359" - integrity sha512-DK4EwqhxfXpyCA+UH8TBRIAXAfmmX4q9QRBz/2h9F9sI91yt6mltTrL6TKURMcjUVmgaB80wgS9QybNIyVBIJA== +"@commitlint/parse@^17.7.0": + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-17.7.0.tgz#aacb2d189e50ab8454154b1df150aaf20478ae47" + integrity sha512-dIvFNUMCUHqq5Abv80mIEjLVfw8QNuA4DS7OWip4pcK/3h5wggmjVnlwGCDvDChkw2TjK1K6O+tAEV78oxjxag== dependencies: - "@commitlint/types" "^17.4.0" - conventional-changelog-angular "^5.0.11" - conventional-commits-parser "^3.2.2" + "@commitlint/types" "^17.4.4" + conventional-changelog-angular "^6.0.0" + conventional-commits-parser "^4.0.0" -"@commitlint/read@^17.4.2": - version "17.4.2" - resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-17.4.2.tgz#4880a05271fb44cefa54d365a17d5753496a6de0" - integrity sha512-hasYOdbhEg+W4hi0InmXHxtD/1favB4WdwyFxs1eOy/DvMw6+2IZBmATgGOlqhahsypk4kChhxjAFJAZ2F+JBg== +"@commitlint/read@^17.5.1": + version "17.5.1" + resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-17.5.1.tgz#fec903b766e2c41e3cefa80630040fcaba4f786c" + integrity sha512-7IhfvEvB//p9aYW09YVclHbdf1u7g7QhxeYW9ZHSO8Huzp8Rz7m05aCO1mFG7G8M+7yfFnXB5xOmG18brqQIBg== dependencies: "@commitlint/top-level" "^17.4.0" - "@commitlint/types" "^17.4.0" + "@commitlint/types" "^17.4.4" fs-extra "^11.0.0" - git-raw-commits "^2.0.0" + git-raw-commits "^2.0.11" minimist "^1.2.6" -"@commitlint/resolve-extends@^17.4.0": - version "17.4.0" - resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-17.4.0.tgz#9023da6c70c4ebd173b4b0995fe29f27051da2d3" - integrity sha512-3JsmwkrCzoK8sO22AzLBvNEvC1Pmdn/65RKXzEtQMy6oYMl0Snrq97a5bQQEFETF0VsvbtUuKttLqqgn99OXRQ== +"@commitlint/resolve-extends@^17.6.7": + version "17.6.7" + resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-17.6.7.tgz#9c53a4601c96ab2dd20b90fb35c988639307735d" + integrity sha512-PfeoAwLHtbOaC9bGn/FADN156CqkFz6ZKiVDMjuC2N5N0740Ke56rKU7Wxdwya8R8xzLK9vZzHgNbuGhaOVKIg== dependencies: - "@commitlint/config-validator" "^17.4.0" - "@commitlint/types" "^17.4.0" + "@commitlint/config-validator" "^17.6.7" + "@commitlint/types" "^17.4.4" import-fresh "^3.0.0" lodash.mergewith "^4.6.2" resolve-from "^5.0.0" resolve-global "^1.0.0" -"@commitlint/rules@^17.4.2": - version "17.4.2" - resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-17.4.2.tgz#cdf203bc82af979cb319210ef9215cb1de216a9b" - integrity sha512-OGrPsMb9Fx3/bZ64/EzJehY9YDSGWzp81Pj+zJiY+r/NSgJI3nUYdlS37jykNIugzazdEXfMtQ10kmA+Kx2pZQ== +"@commitlint/rules@^17.7.0": + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-17.7.0.tgz#b97a4933c5cba11a659a19ee467f6f000f31533e" + integrity sha512-J3qTh0+ilUE5folSaoK91ByOb8XeQjiGcdIdiB/8UT1/Rd1itKo0ju/eQVGyFzgTMYt8HrDJnGTmNWwcMR1rmA== dependencies: - "@commitlint/ensure" "^17.4.0" + "@commitlint/ensure" "^17.6.7" "@commitlint/message" "^17.4.2" "@commitlint/to-lines" "^17.4.0" - "@commitlint/types" "^17.4.0" + "@commitlint/types" "^17.4.4" execa "^5.0.0" "@commitlint/to-lines@^17.4.0": @@ -177,81 +175,24 @@ dependencies: find-up "^5.0.0" -"@commitlint/types@^17.4.0": - version "17.4.0" - resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-17.4.0.tgz#c7c2b97b959f6175c164632bf26208ce417b3f31" - integrity sha512-2NjAnq5IcxY9kXtUeO2Ac0aPpvkuOmwbH/BxIm36XXK5LtWFObWJWjXOA+kcaABMrthjWu6la+FUpyYFMHRvbA== +"@commitlint/types@^17.4.4": + version "17.4.4" + resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-17.4.4.tgz#1416df936e9aad0d6a7bbc979ecc31e55dade662" + integrity sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ== dependencies: chalk "^4.1.0" -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@solidity-parser/parser@^0.14.5": - version "0.14.5" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" - integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg== - dependencies: - antlr4ts "^0.5.0-alpha.4" - -"@tsconfig/node10@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" - integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" - integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== - "@types/minimist@^1.2.0": version "1.2.2" resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== -"@types/node@*": - version "18.11.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" - integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== - "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== -JSONStream@^1.0.4: +JSONStream@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== @@ -259,16 +200,6 @@ JSONStream@^1.0.4: jsonparse "^1.2.0" through ">=2.2.7 <3" -acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.4.1: - version "8.8.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" - integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== - ajv@^8.11.0: version "8.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" @@ -298,16 +229,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -antlr4ts@^0.5.0-alpha.4: - version "0.5.0-alpha.4" - resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" - integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -342,7 +263,7 @@ camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -chalk@^2.0.0: +chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -400,13 +321,12 @@ compare-func@^2.0.0: array-ify "^1.0.0" dot-prop "^5.1.0" -conventional-changelog-angular@^5.0.11: - version "5.0.13" - resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz#896885d63b914a70d4934b59d2fe7bde1832b28c" - integrity sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA== +conventional-changelog-angular@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz#a9a9494c28b7165889144fd5b91573c4aa9ca541" + integrity sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg== dependencies: compare-func "^2.0.0" - q "^1.5.1" conventional-changelog-conventionalcommits@^5.0.0: version "5.0.0" @@ -417,38 +337,33 @@ conventional-changelog-conventionalcommits@^5.0.0: lodash "^4.17.15" q "^1.5.1" -conventional-commits-parser@^3.2.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz#a7d3b77758a202a9b2293d2112a8d8052c740972" - integrity sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q== +conventional-commits-parser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz#02ae1178a381304839bce7cea9da5f1b549ae505" + integrity sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg== dependencies: - JSONStream "^1.0.4" + JSONStream "^1.3.5" is-text-path "^1.0.1" - lodash "^4.17.15" - meow "^8.0.0" - split2 "^3.0.0" - through2 "^4.0.0" + meow "^8.1.2" + split2 "^3.2.2" -cosmiconfig-typescript-loader@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz#c4259ce474c9df0f32274ed162c0447c951ef073" - integrity sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q== +cosmiconfig-typescript-loader@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz#0d3becfe022a871f7275ceb2397d692e06045dc8" + integrity sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA== + dependencies: + jiti "^1.19.1" cosmiconfig@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.0.0.tgz#e9feae014eab580f858f8a0288f38997a7bebe97" - integrity sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ== + version "8.2.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.2.0.tgz#f7d17c56a590856cd1e7cee98734dca272b0d8fd" + integrity sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ== dependencies: import-fresh "^3.2.1" js-yaml "^4.1.0" parse-json "^5.0.0" path-type "^4.0.0" -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -476,11 +391,6 @@ decamelize@^1.1.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - dot-prop@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -547,9 +457,9 @@ find-up@^5.0.0: path-exists "^4.0.0" fs-extra@^11.0.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.0.tgz#5784b102104433bb0e090f48bfc4a30742c357ed" - integrity sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw== + version "11.1.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" + integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -570,7 +480,7 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -git-raw-commits@^2.0.0: +git-raw-commits@^2.0.11: version "2.0.11" resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723" integrity sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A== @@ -589,9 +499,9 @@ global-dirs@^0.1.1: ini "^1.3.4" graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== hard-rejection@^2.1.0: version "2.1.0" @@ -665,10 +575,10 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-core-module@^2.5.0, is-core-module@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== +is-core-module@^2.13.0, is-core-module@^2.5.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== dependencies: has "^1.0.3" @@ -704,6 +614,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +jiti@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.1.tgz#fa99e4b76a23053e0e7cde098efe1704a14c16f1" + integrity sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -826,11 +741,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - map-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" @@ -841,7 +751,7 @@ map-obj@^4.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== -meow@^8.0.0: +meow@^8.0.0, meow@^8.1.2: version "8.1.2" resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897" integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q== @@ -883,9 +793,9 @@ minimist-options@4.1.0: kind-of "^6.0.3" minimist@^1.2.6: - version "1.2.7" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== normalize-package-data@^2.5.0: version "2.5.0" @@ -991,20 +901,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -prettier-plugin-solidity@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.1.tgz#4d3375b85f97812ffcbe48d5a8b3fe914d69c91f" - integrity sha512-uD24KO26tAHF+zMN2nt1OUzfknzza5AgxjogQQrMLZc7j8xiQrDoNWNeOlfFC0YLTwo12CLD10b9niLyP6AqXg== - dependencies: - "@solidity-parser/parser" "^0.14.5" - semver "^7.3.8" - solidity-comments-extractor "^0.0.7" - -prettier@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" - integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== - punycode@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" @@ -1040,9 +936,9 @@ read-pkg@^5.2.0: type-fest "^0.6.0" readable-stream@3, readable-stream@^3.0.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -1084,11 +980,11 @@ resolve-global@1.0.0, resolve-global@^1.0.0: global-dirs "^0.1.1" resolve@^1.10.0: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -1098,14 +994,14 @@ safe-buffer@~5.2.0: integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== "semver@2 || 3 || 4 || 5": - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@7.3.8, semver@^7.3.4, semver@^7.3.8: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== +semver@7.5.4, semver@^7.3.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" @@ -1126,15 +1022,10 @@ signal-exit@^3.0.3: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -solidity-comments-extractor@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" - integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== - spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -1153,11 +1044,11 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.12" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" - integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== + version "3.0.13" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" + integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== -split2@^3.0.0: +split2@^3.0.0, split2@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== @@ -1240,25 +1131,6 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== -ts-node@^10.8.1: - version "10.9.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" - integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - type-fest@^0.18.0: version "0.18.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" @@ -1274,11 +1146,6 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -typescript@^4.6.4: - version "4.9.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" - integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== - universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" @@ -1296,11 +1163,6 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -1346,9 +1208,9 @@ yargs-parser@^21.1.1: integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs@^17.0.0: - version "17.6.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541" - integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" escalade "^3.1.1" @@ -1358,11 +1220,6 @@ yargs@^17.0.0: y18n "^5.0.5" yargs-parser "^21.1.1" -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"