From e45be6d9656b3e45bf6c75b206603be7b1b72caf Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 27 Aug 2024 10:15:42 -0400 Subject: [PATCH 01/28] Add gitignore file --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 779b258b..7d483433 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,6 @@ typechain/ test-results.json scenario-results.json +.idea/ +*.iml From d772d37559437ecc2aca508ef4302b550f5134e5 Mon Sep 17 00:00:00 2001 From: robin Date: Thu, 5 Sep 2024 14:59:40 -0400 Subject: [PATCH 02/28] Changes v1 --- .gitignore | 1 + contracts/CometProxyAdmin.sol | 119 +++- contracts/Configurator.sol | 140 +++-- contracts/ConfiguratorStorage.sol | 12 +- .../marketupdates/CometProxyAdminOld.sol | 33 ++ contracts/marketupdates/ConfiguratorOld.sol | 353 ++++++++++++ .../marketupdates/MarketUpdateProposer.sol | 201 +++++++ .../marketupdates/MarketUpdateTimelock.sol | 117 ++++ contracts/marketupdates/SafeMath.sol | 191 +++++++ contracts/test/GovernorSimple.sol | 8 +- deployments/localhost/dai/configuration.json | 26 + deployments/localhost/dai/deploy.ts | 519 ++++++++++++++++++ hardhat.config.ts | 12 +- tasks/deployment_manager/task.ts | 2 +- test/helpers.ts | 114 ++-- test/liquidation/liquidation-bot-script.ts | 2 +- test/marketupdates/existing-flow-test.ts | 353 ++++++++++++ .../market-update-comet-proxy-admin-test.ts | 506 +++++++++++++++++ .../market-update-configurator-test.ts | 470 ++++++++++++++++ .../market-update-deployment-test.ts | 377 +++++++++++++ .../market-update-proposer-test.ts | 247 +++++++++ .../market-update-timelock-test.ts | 414 ++++++++++++++ test/marketupdates/market-updates-helper.ts | 107 ++++ 23 files changed, 4214 insertions(+), 110 deletions(-) create mode 100644 contracts/marketupdates/CometProxyAdminOld.sol create mode 100644 contracts/marketupdates/ConfiguratorOld.sol create mode 100644 contracts/marketupdates/MarketUpdateProposer.sol create mode 100644 contracts/marketupdates/MarketUpdateTimelock.sol create mode 100644 contracts/marketupdates/SafeMath.sol create mode 100644 deployments/localhost/dai/configuration.json create mode 100644 deployments/localhost/dai/deploy.ts create mode 100644 test/marketupdates/existing-flow-test.ts create mode 100644 test/marketupdates/market-update-comet-proxy-admin-test.ts create mode 100644 test/marketupdates/market-update-configurator-test.ts create mode 100644 test/marketupdates/market-update-deployment-test.ts create mode 100644 test/marketupdates/market-update-proposer-test.ts create mode 100644 test/marketupdates/market-update-timelock-test.ts create mode 100644 test/marketupdates/market-updates-helper.ts diff --git a/.gitignore b/.gitignore index 7d483433..def80361 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ scenario-results.json .idea/ *.iml +deployments/localhost/dai/roots.json diff --git a/contracts/CometProxyAdmin.sol b/contracts/CometProxyAdmin.sol index 6072c292..bdd6f22e 100644 --- a/contracts/CometProxyAdmin.sol +++ b/contracts/CometProxyAdmin.sol @@ -4,27 +4,130 @@ pragma solidity 0.8.15; import "./vendor/proxy/transparent/ProxyAdmin.sol"; interface Deployable { - function deploy(address cometProxy) external returns (address); + function deploy(address cometProxy) external returns (address); } contract CometProxyAdmin is ProxyAdmin { + /// @notice Pause flag for the market update admin + bool public marketAdminPaused = false; + + /// @notice The address of the market update admin. This will be the address of a timelock contract. + address public marketAdmin; + + /// @notice address of the market admin pause guardian. We don't use `pauseGuardian` because we have `setPauseGuardian` which sets the pauseGuardian on comet. + address public marketAdminPauseGuardian; + + event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); + event MarketAdminPaused(address indexed caller, bool isMarketAdminPaused); + event SetMarketAdminPauseGuardian( + address indexed oldPauseGuardian, + address indexed newPauseGuardian + ); + error Unauthorized(); + error MarketAdminIsPaused(); + error AlreadyPaused(); + error AlreadyUnPaused(); + + /** + * @dev Throws if called by any account other than the owner and market update admin + */ + modifier ownerOrMarketAdmin() { + // using revert instead of require to keep it consistent with other calls + if (owner() != _msgSender() && marketAdmin != _msgSender()) + revert Unauthorized(); + // If the sender is the marketAdmin, check that the marketAdmin is not paused + if (_msgSender() == marketAdmin && marketAdminPaused) + revert MarketAdminIsPaused(); + _; + } + + /** + * @notice Sets a new market admin for the contract. + * @dev This function can only be called by the owner of the contract. + * If the caller is not the owner, the function will revert with an Unauthorized error. + * Note that there is no enforced zero address check on `newAdmin` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the market admin role. + * @param newAdmin The address of the new market admin. + */ + function setMarketAdmin(address newAdmin) public { + address oldAdmin = marketAdmin; + if (msg.sender != owner()) revert Unauthorized(); + marketAdmin = newAdmin; + emit SetMarketAdmin(oldAdmin, newAdmin); + } + + /** + * @notice Pauses the market admin role. + * @dev Can only be called by the owner or the market admin pause guardian. + * Reverts with Unauthorized if the caller is neither. + */ + function pauseMarketAdmin() external { + if (marketAdminPaused) revert AlreadyPaused(); + if (msg.sender != owner() && msg.sender != marketAdminPauseGuardian) + revert Unauthorized(); + marketAdminPaused = true; + emit MarketAdminPaused(msg.sender, true); + } + + /** + * @notice Unpauses the market admin role. + * @dev Can only be called by the owner. + * Reverts with Unauthorized if the caller is not the owner. + */ + function unpauseMarketAdmin() external { + if (!marketAdminPaused) revert AlreadyUnPaused(); + if (msg.sender != owner()) revert Unauthorized(); + marketAdminPaused = false; + emit MarketAdminPaused(msg.sender, false); + } + + /** + * @notice Sets a new market admin pause guardian. + * @dev Can only be called by the owner. Reverts with Unauthorized if the caller is not the owner. + * @param newPauseGuardian The address of the new market admin pause guardian. + * Note that there is no enforced zero address check on `newPauseGuadian` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the pause guadian. + */ + function setMarketAdminPauseGuardian(address newPauseGuardian) external { + if (msg.sender != owner()) revert Unauthorized(); + address oldPauseGuardian = marketAdminPauseGuardian; + marketAdminPauseGuardian = newPauseGuardian; + emit SetMarketAdminPauseGuardian(oldPauseGuardian, newPauseGuardian); + } + /** * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy * Requirements: - * - This contract must be the admin of `CometProxy` + * - This contract must be the admin or market admin of `CometProxy` */ - function deployAndUpgradeTo(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy) public virtual onlyOwner { + function deployAndUpgradeTo(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy) public virtual ownerOrMarketAdmin { address newCometImpl = configuratorProxy.deploy(address(cometProxy)); - upgrade(cometProxy, newCometImpl); + _upgrade(cometProxy, newCometImpl); } /** * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy, then call the function * Requirements: - * - This contract must be the admin of `CometProxy` + * - This contract must be the admin or market admin of `CometProxy` */ - function deployUpgradeToAndCall(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy, bytes memory data) public virtual onlyOwner { + function deployUpgradeToAndCall(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy, bytes memory data) public virtual ownerOrMarketAdmin { address newCometImpl = configuratorProxy.deploy(address(cometProxy)); - upgradeAndCall(cometProxy, newCometImpl, data); + _upgradeAndCall(cometProxy, newCometImpl, data); + } + + /** + * @dev Custom upgrade function that allows owner and marketUpdateAdmin to call it + */ + function _upgrade(TransparentUpgradeableProxy proxy, address implementation) private ownerOrMarketAdmin { + proxy.upgradeTo(implementation); + } + + /** + * @dev Custom upgradeAndCall function that allows owner and marketUpdateAdmin to call it + */ + function _upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) private ownerOrMarketAdmin { + proxy.upgradeToAndCall(implementation, data); } -} \ No newline at end of file +} diff --git a/contracts/Configurator.sol b/contracts/Configurator.sol index af200f9c..dd177cc4 100644 --- a/contracts/Configurator.sol +++ b/contracts/Configurator.sol @@ -8,7 +8,6 @@ import "./ConfiguratorStorage.sol"; contract Configurator is ConfiguratorStorage { /** Custom events **/ - event AddAsset(address indexed cometProxy, AssetConfig assetConfig); event CometDeployed(address indexed cometProxy, address indexed newComet); event GovernorTransferred(address indexed oldGovernor, address indexed newGovernor); @@ -39,17 +38,34 @@ contract Configurator is ConfiguratorStorage { event UpdateAssetLiquidationFactor(address indexed cometProxy, address indexed asset, uint64 oldLiquidationFactor, uint64 newLiquidationFactor); event UpdateAssetSupplyCap(address indexed cometProxy, address indexed asset, uint128 oldSupplyCap, uint128 newSupplyCap); - /** Custom errors **/ + event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); + event MarketAdminPaused(address indexed caller, bool isMarketAdminPaused); + event SetMarketAdminPauseGuardian(address indexed oldPauseGuardian, address indexed newPauseGuardian); + /** Custom errors **/ error AlreadyInitialized(); error AssetDoesNotExist(); error ConfigurationAlreadyExists(); error InvalidAddress(); error Unauthorized(); + error MarketAdminIsPaused(); + error AlreadyPaused(); + error AlreadyUnPaused(); /** - * @notice Constructs a new Configurator instance - **/ + * @dev Ensures that the caller is either the governor or the market admin. + * Reverts with Unauthorized if the caller is neither. If the caller is the market admin, + * it also checks if the market admin is paused, reverting with MarketAdminIsPaused if so. + * Uses revert instead of require for consistency with other calls. + */ + modifier governorOrMarketAdmin { + // using revert instead of require to keep it consistent with other calls + if(msg.sender != governor && msg.sender != marketAdmin) revert Unauthorized(); + // If the sender is the marketAdmin, check that the market admin is not paused + if (msg.sender == marketAdmin && marketAdminPaused) revert MarketAdminIsPaused(); + _; + } + constructor() { // Set a high version to prevent the implementation contract from being initialized version = type(uint256).max; @@ -67,6 +83,61 @@ contract Configurator is ConfiguratorStorage { version = 1; } + /** + * @notice Sets a new market admin. + * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the governor. + * Emits an event with the old and new market admin addresses. + * Note that there is no enforced zero address check on `newMarketAdmin` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the market admin role. + * @param newMarketAdmin The address of the new market admin. + */ + function setMarketAdmin(address newMarketAdmin) external { + if (msg.sender != governor) revert Unauthorized(); + address oldMarketAdmin = marketAdmin; + marketAdmin = newMarketAdmin; + emit SetMarketAdmin(oldMarketAdmin, newMarketAdmin); + } + + /** + * @notice Pauses the market admin role. + * @dev Can only be called by the governor or the market admin pause guardian. + * Reverts with Unauthorized if the caller is neither. + */ + function pauseMarketAdmin() external { + if (marketAdminPaused) revert AlreadyPaused(); + if (msg.sender != governor && msg.sender != marketAdminPauseGuardian) revert Unauthorized(); + marketAdminPaused = true; + emit MarketAdminPaused(msg.sender, true); + } + + /** + * @notice Unpauses the market admin role. + * @dev Can only be called by the governor. + * Reverts with Unauthorized if the caller is not the governor. + */ + function unpauseMarketAdmin() external { + if (!marketAdminPaused) revert AlreadyUnPaused(); + if (msg.sender != governor) revert Unauthorized(); + marketAdminPaused = false; + emit MarketAdminPaused(msg.sender, false); + } + + /** + * @notice Sets a new market admin pause guardian. + * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the owner. + * @param newPauseGuardian The address of the new market admin pause guardian. + * Note that there is no enforced zero address check on `newPauseGuadian` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the pause guadian. + */ + function setMarketAdminPauseGuardian(address newPauseGuardian) external { + if (msg.sender != governor) revert Unauthorized(); + address oldPauseGuardian = marketAdminPauseGuardian; + marketAdminPauseGuardian = newPauseGuardian; + emit SetMarketAdminPauseGuardian(oldPauseGuardian, newPauseGuardian); + } + /** * @notice Sets the factory for a Comet proxy * @dev Note: Only callable by governor @@ -107,7 +178,6 @@ contract Configurator is ConfiguratorStorage { function setPauseGuardian(address cometProxy, address newPauseGuardian) external { if (msg.sender != governor) revert Unauthorized(); - address oldPauseGuardian = configuratorParams[cometProxy].pauseGuardian; configuratorParams[cometProxy].pauseGuardian = newPauseGuardian; emit SetPauseGuardian(cometProxy, oldPauseGuardian, newPauseGuardian); @@ -129,65 +199,49 @@ contract Configurator is ConfiguratorStorage { emit SetExtensionDelegate(cometProxy, oldExtensionDelegate, newExtensionDelegate); } - function setSupplyKink(address cometProxy, uint64 newSupplyKink) external { - if (msg.sender != governor) revert Unauthorized(); - + function setSupplyKink(address cometProxy, uint64 newSupplyKink) external governorOrMarketAdmin { uint64 oldSupplyKink = configuratorParams[cometProxy].supplyKink; configuratorParams[cometProxy].supplyKink = newSupplyKink; emit SetSupplyKink(cometProxy, oldSupplyKink, newSupplyKink); } - function setSupplyPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external { - if (msg.sender != governor) revert Unauthorized(); - + function setSupplyPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external governorOrMarketAdmin { uint64 oldSlope = configuratorParams[cometProxy].supplyPerYearInterestRateSlopeLow; configuratorParams[cometProxy].supplyPerYearInterestRateSlopeLow = newSlope; emit SetSupplyPerYearInterestRateSlopeLow(cometProxy, oldSlope, newSlope); } - function setSupplyPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external { - if (msg.sender != governor) revert Unauthorized(); - + function setSupplyPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external governorOrMarketAdmin { uint64 oldSlope = configuratorParams[cometProxy].supplyPerYearInterestRateSlopeHigh; configuratorParams[cometProxy].supplyPerYearInterestRateSlopeHigh = newSlope; emit SetSupplyPerYearInterestRateSlopeHigh(cometProxy, oldSlope, newSlope); } - function setSupplyPerYearInterestRateBase(address cometProxy, uint64 newBase) external { - if (msg.sender != governor) revert Unauthorized(); - + function setSupplyPerYearInterestRateBase(address cometProxy, uint64 newBase) external governorOrMarketAdmin { uint64 oldBase = configuratorParams[cometProxy].supplyPerYearInterestRateBase; configuratorParams[cometProxy].supplyPerYearInterestRateBase = newBase; emit SetSupplyPerYearInterestRateBase(cometProxy, oldBase, newBase); } - function setBorrowKink(address cometProxy, uint64 newBorrowKink) external { - if (msg.sender != governor) revert Unauthorized(); - + function setBorrowKink(address cometProxy, uint64 newBorrowKink) external governorOrMarketAdmin { uint64 oldBorrowKink = configuratorParams[cometProxy].borrowKink; configuratorParams[cometProxy].borrowKink = newBorrowKink; emit SetBorrowKink(cometProxy, oldBorrowKink, newBorrowKink); } - function setBorrowPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external { - if (msg.sender != governor) revert Unauthorized(); - + function setBorrowPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external governorOrMarketAdmin { uint64 oldSlope = configuratorParams[cometProxy].borrowPerYearInterestRateSlopeLow; configuratorParams[cometProxy].borrowPerYearInterestRateSlopeLow = newSlope; emit SetBorrowPerYearInterestRateSlopeLow(cometProxy, oldSlope, newSlope); } - function setBorrowPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external { - if (msg.sender != governor) revert Unauthorized(); - + function setBorrowPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external governorOrMarketAdmin { uint64 oldSlope = configuratorParams[cometProxy].borrowPerYearInterestRateSlopeHigh; configuratorParams[cometProxy].borrowPerYearInterestRateSlopeHigh = newSlope; emit SetBorrowPerYearInterestRateSlopeHigh(cometProxy, oldSlope, newSlope); } - function setBorrowPerYearInterestRateBase(address cometProxy, uint64 newBase) external { - if (msg.sender != governor) revert Unauthorized(); - + function setBorrowPerYearInterestRateBase(address cometProxy, uint64 newBase) external governorOrMarketAdmin { uint64 oldBase = configuratorParams[cometProxy].borrowPerYearInterestRateBase; configuratorParams[cometProxy].borrowPerYearInterestRateBase = newBase; emit SetBorrowPerYearInterestRateBase(cometProxy, oldBase, newBase); @@ -201,17 +255,13 @@ contract Configurator is ConfiguratorStorage { emit SetStoreFrontPriceFactor(cometProxy, oldStoreFrontPriceFactor, newStoreFrontPriceFactor); } - function setBaseTrackingSupplySpeed(address cometProxy, uint64 newBaseTrackingSupplySpeed) external { - if (msg.sender != governor) revert Unauthorized(); - + function setBaseTrackingSupplySpeed(address cometProxy, uint64 newBaseTrackingSupplySpeed) external governorOrMarketAdmin { uint64 oldBaseTrackingSupplySpeed = configuratorParams[cometProxy].baseTrackingSupplySpeed; configuratorParams[cometProxy].baseTrackingSupplySpeed = newBaseTrackingSupplySpeed; emit SetBaseTrackingSupplySpeed(cometProxy, oldBaseTrackingSupplySpeed, newBaseTrackingSupplySpeed); } - function setBaseTrackingBorrowSpeed(address cometProxy, uint64 newBaseTrackingBorrowSpeed) external { - if (msg.sender != governor) revert Unauthorized(); - + function setBaseTrackingBorrowSpeed(address cometProxy, uint64 newBaseTrackingBorrowSpeed) external governorOrMarketAdmin { uint64 oldBaseTrackingBorrowSpeed = configuratorParams[cometProxy].baseTrackingBorrowSpeed; configuratorParams[cometProxy].baseTrackingBorrowSpeed = newBaseTrackingBorrowSpeed; emit SetBaseTrackingBorrowSpeed(cometProxy, oldBaseTrackingBorrowSpeed, newBaseTrackingBorrowSpeed); @@ -225,9 +275,7 @@ contract Configurator is ConfiguratorStorage { emit SetBaseMinForRewards(cometProxy, oldBaseMinForRewards, newBaseMinForRewards); } - function setBaseBorrowMin(address cometProxy, uint104 newBaseBorrowMin) external { - if (msg.sender != governor) revert Unauthorized(); - + function setBaseBorrowMin(address cometProxy, uint104 newBaseBorrowMin) external governorOrMarketAdmin { uint104 oldBaseBorrowMin = configuratorParams[cometProxy].baseBorrowMin; configuratorParams[cometProxy].baseBorrowMin = newBaseBorrowMin; emit SetBaseBorrowMin(cometProxy, oldBaseBorrowMin, newBaseBorrowMin); @@ -266,36 +314,28 @@ contract Configurator is ConfiguratorStorage { emit UpdateAssetPriceFeed(cometProxy, asset, oldPriceFeed, newPriceFeed); } - function updateAssetBorrowCollateralFactor(address cometProxy, address asset, uint64 newBorrowCF) external { - if (msg.sender != governor) revert Unauthorized(); - + function updateAssetBorrowCollateralFactor(address cometProxy, address asset, uint64 newBorrowCF) external governorOrMarketAdmin { uint assetIndex = getAssetIndex(cometProxy, asset); uint64 oldBorrowCF = configuratorParams[cometProxy].assetConfigs[assetIndex].borrowCollateralFactor; configuratorParams[cometProxy].assetConfigs[assetIndex].borrowCollateralFactor = newBorrowCF; emit UpdateAssetBorrowCollateralFactor(cometProxy, asset, oldBorrowCF, newBorrowCF); } - function updateAssetLiquidateCollateralFactor(address cometProxy, address asset, uint64 newLiquidateCF) external { - if (msg.sender != governor) revert Unauthorized(); - + function updateAssetLiquidateCollateralFactor(address cometProxy, address asset, uint64 newLiquidateCF) external governorOrMarketAdmin { uint assetIndex = getAssetIndex(cometProxy, asset); uint64 oldLiquidateCF = configuratorParams[cometProxy].assetConfigs[assetIndex].liquidateCollateralFactor; configuratorParams[cometProxy].assetConfigs[assetIndex].liquidateCollateralFactor = newLiquidateCF; emit UpdateAssetLiquidateCollateralFactor(cometProxy, asset, oldLiquidateCF, newLiquidateCF); } - function updateAssetLiquidationFactor(address cometProxy, address asset, uint64 newLiquidationFactor) external { - if (msg.sender != governor) revert Unauthorized(); - + function updateAssetLiquidationFactor(address cometProxy, address asset, uint64 newLiquidationFactor) external governorOrMarketAdmin { uint assetIndex = getAssetIndex(cometProxy, asset); uint64 oldLiquidationFactor = configuratorParams[cometProxy].assetConfigs[assetIndex].liquidationFactor; configuratorParams[cometProxy].assetConfigs[assetIndex].liquidationFactor = newLiquidationFactor; emit UpdateAssetLiquidationFactor(cometProxy, asset, oldLiquidationFactor, newLiquidationFactor); } - function updateAssetSupplyCap(address cometProxy, address asset, uint128 newSupplyCap) external { - if (msg.sender != governor) revert Unauthorized(); - + function updateAssetSupplyCap(address cometProxy, address asset, uint128 newSupplyCap) external governorOrMarketAdmin { uint assetIndex = getAssetIndex(cometProxy, asset); uint128 oldSupplyCap = configuratorParams[cometProxy].assetConfigs[assetIndex].supplyCap; configuratorParams[cometProxy].assetConfigs[assetIndex].supplyCap = newSupplyCap; diff --git a/contracts/ConfiguratorStorage.sol b/contracts/ConfiguratorStorage.sol index 38d55a3b..785202ef 100644 --- a/contracts/ConfiguratorStorage.sol +++ b/contracts/ConfiguratorStorage.sol @@ -24,4 +24,14 @@ contract ConfiguratorStorage is CometConfiguration { /// @notice Mapping of Comet proxy addresses to their Comet factory contracts mapping(address => address) public factory; -} \ No newline at end of file + + /// @notice The address of the market admin. This will be the address of a timelock contract. + address public marketAdmin; + + /// @notice Pause flag for the market admin + bool public marketAdminPaused = false; + + /// @notice address of the market admin pause guardian. We don't use `pauseGuardian` role because we have `setPauseGuardian` already which sets the pauseGuardian on comet. + address public marketAdminPauseGuardian; + +} diff --git a/contracts/marketupdates/CometProxyAdminOld.sol b/contracts/marketupdates/CometProxyAdminOld.sol new file mode 100644 index 00000000..772d015d --- /dev/null +++ b/contracts/marketupdates/CometProxyAdminOld.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "./../vendor/proxy/transparent/ProxyAdmin.sol"; + +interface Deployable { + function deploy(address cometProxy) external returns (address); +} + +/** + * @dev This contract is just to simulate the full deployment process of market updates. Should be deleted after the market updates are deployed. + */ +contract CometProxyAdminOld is ProxyAdmin { + /** + * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy + * Requirements: + * - This contract must be the admin of `CometProxy` + */ + function deployAndUpgradeTo(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy) public virtual onlyOwner { + address newCometImpl = configuratorProxy.deploy(address(cometProxy)); + upgrade(cometProxy, newCometImpl); + } + + /** + * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy, then call the function + * Requirements: + * - This contract must be the admin of `CometProxy` + */ + function deployUpgradeToAndCall(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy, bytes memory data) public virtual onlyOwner { + address newCometImpl = configuratorProxy.deploy(address(cometProxy)); + upgradeAndCall(cometProxy, newCometImpl, data); + } +} diff --git a/contracts/marketupdates/ConfiguratorOld.sol b/contracts/marketupdates/ConfiguratorOld.sol new file mode 100644 index 00000000..47060362 --- /dev/null +++ b/contracts/marketupdates/ConfiguratorOld.sol @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "./../CometFactory.sol"; +import "./../CometConfiguration.sol"; +import "./../ConfiguratorStorage.sol"; + +/** + * @title Compound's Configurator Contract + * @notice The contract that stores the configuration for Comet proxies + * @dev This contract is just to simulate the full deployment process of market updates. Should be deleted after the market updates are deployed. + */ +contract ConfiguratorOld is ConfiguratorStorage { + + /** Custom events **/ + + event AddAsset(address indexed cometProxy, AssetConfig assetConfig); + event CometDeployed(address indexed cometProxy, address indexed newComet); + event GovernorTransferred(address indexed oldGovernor, address indexed newGovernor); + event SetFactory(address indexed cometProxy, address indexed oldFactory, address indexed newFactory); + event SetGovernor(address indexed cometProxy, address indexed oldGovernor, address indexed newGovernor); + event SetConfiguration(address indexed cometProxy, Configuration oldConfiguration, Configuration newConfiguration); + event SetPauseGuardian(address indexed cometProxy, address indexed oldPauseGuardian, address indexed newPauseGuardian); + event SetBaseTokenPriceFeed(address indexed cometProxy, address indexed oldBaseTokenPriceFeed, address indexed newBaseTokenPriceFeed); + event SetExtensionDelegate(address indexed cometProxy, address indexed oldExt, address indexed newExt); + event SetSupplyKink(address indexed cometProxy,uint64 oldKink, uint64 newKink); + event SetSupplyPerYearInterestRateSlopeLow(address indexed cometProxy,uint64 oldIRSlopeLow, uint64 newIRSlopeLow); + event SetSupplyPerYearInterestRateSlopeHigh(address indexed cometProxy,uint64 oldIRSlopeHigh, uint64 newIRSlopeHigh); + event SetSupplyPerYearInterestRateBase(address indexed cometProxy,uint64 oldIRBase, uint64 newIRBase); + event SetBorrowKink(address indexed cometProxy,uint64 oldKink, uint64 newKink); + event SetBorrowPerYearInterestRateSlopeLow(address indexed cometProxy,uint64 oldIRSlopeLow, uint64 newIRSlopeLow); + event SetBorrowPerYearInterestRateSlopeHigh(address indexed cometProxy,uint64 oldIRSlopeHigh, uint64 newIRSlopeHigh); + event SetBorrowPerYearInterestRateBase(address indexed cometProxy,uint64 oldIRBase, uint64 newIRBase); + event SetStoreFrontPriceFactor(address indexed cometProxy, uint64 oldStoreFrontPriceFactor, uint64 newStoreFrontPriceFactor); + event SetBaseTrackingSupplySpeed(address indexed cometProxy, uint64 oldBaseTrackingSupplySpeed, uint64 newBaseTrackingSupplySpeed); + event SetBaseTrackingBorrowSpeed(address indexed cometProxy, uint64 oldBaseTrackingBorrowSpeed, uint64 newBaseTrackingBorrowSpeed); + event SetBaseMinForRewards(address indexed cometProxy, uint104 oldBaseMinForRewards, uint104 newBaseMinForRewards); + event SetBaseBorrowMin(address indexed cometProxy, uint104 oldBaseBorrowMin, uint104 newBaseBorrowMin); + event SetTargetReserves(address indexed cometProxy, uint104 oldTargetReserves, uint104 newTargetReserves); + event UpdateAsset(address indexed cometProxy, AssetConfig oldAssetConfig, AssetConfig newAssetConfig); + event UpdateAssetPriceFeed(address indexed cometProxy, address indexed asset, address oldPriceFeed, address newPriceFeed); + event UpdateAssetBorrowCollateralFactor(address indexed cometProxy, address indexed asset, uint64 oldBorrowCF, uint64 newBorrowCF); + event UpdateAssetLiquidateCollateralFactor(address indexed cometProxy, address indexed asset, uint64 oldLiquidateCF, uint64 newLiquidateCF); + event UpdateAssetLiquidationFactor(address indexed cometProxy, address indexed asset, uint64 oldLiquidationFactor, uint64 newLiquidationFactor); + event UpdateAssetSupplyCap(address indexed cometProxy, address indexed asset, uint128 oldSupplyCap, uint128 newSupplyCap); + + /** Custom errors **/ + + error AlreadyInitialized(); + error AssetDoesNotExist(); + error ConfigurationAlreadyExists(); + error InvalidAddress(); + error Unauthorized(); + + /** + * @notice Constructs a new Configurator instance + **/ + constructor() { + // Set a high version to prevent the implementation contract from being initialized + version = type(uint256).max; + } + + /** + * @notice Initializes the storage for Configurator + * @param governor_ The address of the governor + **/ + function initialize(address governor_) public { + if (version != 0) revert AlreadyInitialized(); + if (governor_ == address(0)) revert InvalidAddress(); + + governor = governor_; + version = 1; + } + + /** + * @notice Sets the factory for a Comet proxy + * @dev Note: Only callable by governor + **/ + function setFactory(address cometProxy, address newFactory) external { + if (msg.sender != governor) revert Unauthorized(); + + address oldFactory = factory[cometProxy]; + factory[cometProxy] = newFactory; + emit SetFactory(cometProxy, oldFactory, newFactory); + } + + /** + * @notice Sets the entire Configuration for a Comet proxy + * @dev Note: All params can later be updated by the governor except for `baseToken` and `trackingIndexScale` + **/ + function setConfiguration(address cometProxy, Configuration calldata newConfiguration) external { + if (msg.sender != governor) revert Unauthorized(); + Configuration memory oldConfiguration = configuratorParams[cometProxy]; + if (oldConfiguration.baseToken != address(0) && + (oldConfiguration.baseToken != newConfiguration.baseToken || + oldConfiguration.trackingIndexScale != newConfiguration.trackingIndexScale)) + revert ConfigurationAlreadyExists(); + + configuratorParams[cometProxy] = newConfiguration; + emit SetConfiguration(cometProxy, oldConfiguration, newConfiguration); + } + + /** Governance setters for Comet-related configuration **/ + + function setGovernor(address cometProxy, address newGovernor) external { + if (msg.sender != governor) revert Unauthorized(); + + address oldGovernor = configuratorParams[cometProxy].governor; + configuratorParams[cometProxy].governor = newGovernor; + emit SetGovernor(cometProxy, oldGovernor, newGovernor); + } + + function setPauseGuardian(address cometProxy, address newPauseGuardian) external { + if (msg.sender != governor) revert Unauthorized(); + + address oldPauseGuardian = configuratorParams[cometProxy].pauseGuardian; + configuratorParams[cometProxy].pauseGuardian = newPauseGuardian; + emit SetPauseGuardian(cometProxy, oldPauseGuardian, newPauseGuardian); + } + + function setBaseTokenPriceFeed(address cometProxy, address newBaseTokenPriceFeed) external { + if (msg.sender != governor) revert Unauthorized(); + + address oldBaseTokenPriceFeed = configuratorParams[cometProxy].baseTokenPriceFeed; + configuratorParams[cometProxy].baseTokenPriceFeed = newBaseTokenPriceFeed; + emit SetBaseTokenPriceFeed(cometProxy, oldBaseTokenPriceFeed, newBaseTokenPriceFeed); + } + + function setExtensionDelegate(address cometProxy, address newExtensionDelegate) external { + if (msg.sender != governor) revert Unauthorized(); + + address oldExtensionDelegate = configuratorParams[cometProxy].extensionDelegate; + configuratorParams[cometProxy].extensionDelegate = newExtensionDelegate; + emit SetExtensionDelegate(cometProxy, oldExtensionDelegate, newExtensionDelegate); + } + + function setSupplyKink(address cometProxy, uint64 newSupplyKink) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldSupplyKink = configuratorParams[cometProxy].supplyKink; + configuratorParams[cometProxy].supplyKink = newSupplyKink; + emit SetSupplyKink(cometProxy, oldSupplyKink, newSupplyKink); + } + + function setSupplyPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldSlope = configuratorParams[cometProxy].supplyPerYearInterestRateSlopeLow; + configuratorParams[cometProxy].supplyPerYearInterestRateSlopeLow = newSlope; + emit SetSupplyPerYearInterestRateSlopeLow(cometProxy, oldSlope, newSlope); + } + + function setSupplyPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldSlope = configuratorParams[cometProxy].supplyPerYearInterestRateSlopeHigh; + configuratorParams[cometProxy].supplyPerYearInterestRateSlopeHigh = newSlope; + emit SetSupplyPerYearInterestRateSlopeHigh(cometProxy, oldSlope, newSlope); + } + + function setSupplyPerYearInterestRateBase(address cometProxy, uint64 newBase) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldBase = configuratorParams[cometProxy].supplyPerYearInterestRateBase; + configuratorParams[cometProxy].supplyPerYearInterestRateBase = newBase; + emit SetSupplyPerYearInterestRateBase(cometProxy, oldBase, newBase); + } + + function setBorrowKink(address cometProxy, uint64 newBorrowKink) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldBorrowKink = configuratorParams[cometProxy].borrowKink; + configuratorParams[cometProxy].borrowKink = newBorrowKink; + emit SetBorrowKink(cometProxy, oldBorrowKink, newBorrowKink); + } + + function setBorrowPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldSlope = configuratorParams[cometProxy].borrowPerYearInterestRateSlopeLow; + configuratorParams[cometProxy].borrowPerYearInterestRateSlopeLow = newSlope; + emit SetBorrowPerYearInterestRateSlopeLow(cometProxy, oldSlope, newSlope); + } + + function setBorrowPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldSlope = configuratorParams[cometProxy].borrowPerYearInterestRateSlopeHigh; + configuratorParams[cometProxy].borrowPerYearInterestRateSlopeHigh = newSlope; + emit SetBorrowPerYearInterestRateSlopeHigh(cometProxy, oldSlope, newSlope); + } + + function setBorrowPerYearInterestRateBase(address cometProxy, uint64 newBase) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldBase = configuratorParams[cometProxy].borrowPerYearInterestRateBase; + configuratorParams[cometProxy].borrowPerYearInterestRateBase = newBase; + emit SetBorrowPerYearInterestRateBase(cometProxy, oldBase, newBase); + } + + function setStoreFrontPriceFactor(address cometProxy, uint64 newStoreFrontPriceFactor) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldStoreFrontPriceFactor = configuratorParams[cometProxy].storeFrontPriceFactor; + configuratorParams[cometProxy].storeFrontPriceFactor = newStoreFrontPriceFactor; + emit SetStoreFrontPriceFactor(cometProxy, oldStoreFrontPriceFactor, newStoreFrontPriceFactor); + } + + function setBaseTrackingSupplySpeed(address cometProxy, uint64 newBaseTrackingSupplySpeed) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldBaseTrackingSupplySpeed = configuratorParams[cometProxy].baseTrackingSupplySpeed; + configuratorParams[cometProxy].baseTrackingSupplySpeed = newBaseTrackingSupplySpeed; + emit SetBaseTrackingSupplySpeed(cometProxy, oldBaseTrackingSupplySpeed, newBaseTrackingSupplySpeed); + } + + function setBaseTrackingBorrowSpeed(address cometProxy, uint64 newBaseTrackingBorrowSpeed) external { + if (msg.sender != governor) revert Unauthorized(); + + uint64 oldBaseTrackingBorrowSpeed = configuratorParams[cometProxy].baseTrackingBorrowSpeed; + configuratorParams[cometProxy].baseTrackingBorrowSpeed = newBaseTrackingBorrowSpeed; + emit SetBaseTrackingBorrowSpeed(cometProxy, oldBaseTrackingBorrowSpeed, newBaseTrackingBorrowSpeed); + } + + function setBaseMinForRewards(address cometProxy, uint104 newBaseMinForRewards) external { + if (msg.sender != governor) revert Unauthorized(); + + uint104 oldBaseMinForRewards = configuratorParams[cometProxy].baseMinForRewards; + configuratorParams[cometProxy].baseMinForRewards = newBaseMinForRewards; + emit SetBaseMinForRewards(cometProxy, oldBaseMinForRewards, newBaseMinForRewards); + } + + function setBaseBorrowMin(address cometProxy, uint104 newBaseBorrowMin) external { + if (msg.sender != governor) revert Unauthorized(); + + uint104 oldBaseBorrowMin = configuratorParams[cometProxy].baseBorrowMin; + configuratorParams[cometProxy].baseBorrowMin = newBaseBorrowMin; + emit SetBaseBorrowMin(cometProxy, oldBaseBorrowMin, newBaseBorrowMin); + } + + function setTargetReserves(address cometProxy, uint104 newTargetReserves) external { + if (msg.sender != governor) revert Unauthorized(); + + uint104 oldTargetReserves = configuratorParams[cometProxy].targetReserves; + configuratorParams[cometProxy].targetReserves = newTargetReserves; + emit SetTargetReserves(cometProxy, oldTargetReserves, newTargetReserves); + } + + function addAsset(address cometProxy, AssetConfig calldata assetConfig) external { + if (msg.sender != governor) revert Unauthorized(); + + configuratorParams[cometProxy].assetConfigs.push(assetConfig); + emit AddAsset(cometProxy, assetConfig); + } + + function updateAsset(address cometProxy, AssetConfig calldata newAssetConfig) external { + if (msg.sender != governor) revert Unauthorized(); + + uint assetIndex = getAssetIndex(cometProxy, newAssetConfig.asset); + AssetConfig memory oldAssetConfig = configuratorParams[cometProxy].assetConfigs[assetIndex]; + configuratorParams[cometProxy].assetConfigs[assetIndex] = newAssetConfig; + emit UpdateAsset(cometProxy, oldAssetConfig, newAssetConfig); + } + + function updateAssetPriceFeed(address cometProxy, address asset, address newPriceFeed) external { + if (msg.sender != governor) revert Unauthorized(); + + uint assetIndex = getAssetIndex(cometProxy, asset); + address oldPriceFeed = configuratorParams[cometProxy].assetConfigs[assetIndex].priceFeed; + configuratorParams[cometProxy].assetConfigs[assetIndex].priceFeed = newPriceFeed; + emit UpdateAssetPriceFeed(cometProxy, asset, oldPriceFeed, newPriceFeed); + } + + function updateAssetBorrowCollateralFactor(address cometProxy, address asset, uint64 newBorrowCF) external { + if (msg.sender != governor) revert Unauthorized(); + + uint assetIndex = getAssetIndex(cometProxy, asset); + uint64 oldBorrowCF = configuratorParams[cometProxy].assetConfigs[assetIndex].borrowCollateralFactor; + configuratorParams[cometProxy].assetConfigs[assetIndex].borrowCollateralFactor = newBorrowCF; + emit UpdateAssetBorrowCollateralFactor(cometProxy, asset, oldBorrowCF, newBorrowCF); + } + + function updateAssetLiquidateCollateralFactor(address cometProxy, address asset, uint64 newLiquidateCF) external { + if (msg.sender != governor) revert Unauthorized(); + + uint assetIndex = getAssetIndex(cometProxy, asset); + uint64 oldLiquidateCF = configuratorParams[cometProxy].assetConfigs[assetIndex].liquidateCollateralFactor; + configuratorParams[cometProxy].assetConfigs[assetIndex].liquidateCollateralFactor = newLiquidateCF; + emit UpdateAssetLiquidateCollateralFactor(cometProxy, asset, oldLiquidateCF, newLiquidateCF); + } + + function updateAssetLiquidationFactor(address cometProxy, address asset, uint64 newLiquidationFactor) external { + if (msg.sender != governor) revert Unauthorized(); + + uint assetIndex = getAssetIndex(cometProxy, asset); + uint64 oldLiquidationFactor = configuratorParams[cometProxy].assetConfigs[assetIndex].liquidationFactor; + configuratorParams[cometProxy].assetConfigs[assetIndex].liquidationFactor = newLiquidationFactor; + emit UpdateAssetLiquidationFactor(cometProxy, asset, oldLiquidationFactor, newLiquidationFactor); + } + + function updateAssetSupplyCap(address cometProxy, address asset, uint128 newSupplyCap) external { + if (msg.sender != governor) revert Unauthorized(); + + uint assetIndex = getAssetIndex(cometProxy, asset); + uint128 oldSupplyCap = configuratorParams[cometProxy].assetConfigs[assetIndex].supplyCap; + configuratorParams[cometProxy].assetConfigs[assetIndex].supplyCap = newSupplyCap; + emit UpdateAssetSupplyCap(cometProxy, asset, oldSupplyCap, newSupplyCap); + } + + /** Other helpers **/ + + /** + * @dev Determine index of asset that matches given address + */ + function getAssetIndex(address cometProxy, address asset) public view returns (uint) { + AssetConfig[] memory assetConfigs = configuratorParams[cometProxy].assetConfigs; + uint numAssets = assetConfigs.length; + for (uint i = 0; i < numAssets; ) { + if (assetConfigs[i].asset == asset) { + return i; + } + unchecked { i++; } + } + revert AssetDoesNotExist(); + } + + /** + * @return The currently configured params for a Comet proxy + **/ + function getConfiguration(address cometProxy) external view returns (Configuration memory) { + return configuratorParams[cometProxy]; + } + + /** + * @notice Deploy a new Comet implementation using the factory and Configuration for that Comet proxy + * @dev Note: Callable by anyone + */ + function deploy(address cometProxy) external returns (address) { + address newComet = CometFactory(factory[cometProxy]).clone(configuratorParams[cometProxy]); + emit CometDeployed(cometProxy, newComet); + return newComet; + } + + /** + * @notice Transfers the governor rights to a new address + */ + function transferGovernor(address newGovernor) external { + if (msg.sender != governor) revert Unauthorized(); + address oldGovernor = governor; + governor = newGovernor; + emit GovernorTransferred(oldGovernor, newGovernor); + } +} diff --git a/contracts/marketupdates/MarketUpdateProposer.sol b/contracts/marketupdates/MarketUpdateProposer.sol new file mode 100644 index 00000000..6a3a7442 --- /dev/null +++ b/contracts/marketupdates/MarketUpdateProposer.sol @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "./../ITimelock.sol"; +import "./../vendor/access/Ownable.sol"; + +/** +* @title MarketUpdateProposer +* @notice This contract allows for the creation of proposals that can be executed by the timelock +* @dev This contract is used to propose market updates +* Here owner will be the market update multi-sig. The owner can set the new owner by calling `transferOwnership`. +* If multi-sig is compromised, the new owner will only be able to call timelock. marketUpdatePauseGuardian in +* Configurator or CometProxyAdmin can pause these updated. +* +* Other logic can be that only main-governor-timelock can update the owner of this contract, but that logic can be an +* overkill +* +*/ +contract MarketUpdateProposer is Ownable { + struct MarketUpdateProposal { + /// @notice Unique id for looking up a proposal + uint id; + + /// @notice Creator of the proposal + address proposer; + + /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds + uint eta; + + /// @notice the ordered list of target addresses for calls to be made + address[] targets; + + /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made + uint[] values; + + /// @notice The ordered list of function signatures to be called + string[] signatures; + + /// @notice The ordered list of calldata to be passed to each call + bytes[] calldatas; + + string description; + + /// @notice Flag marking whether the proposal has been canceled + bool canceled; + + /// @notice Flag marking whether the proposal has been executed + bool executed; + } + + enum ProposalState { + Canceled, + Queued, + Executed, + Expired + } + + ITimelock public timelock; + + /// @notice The official record of all proposals ever proposed + mapping(uint => MarketUpdateProposal) public proposals; + /// @notice The total number of proposals + uint public proposalCount; + + /// @notice Initial proposal id set at become + uint public initialProposalId = 0; + + /// @notice An event emitted when a new proposal is created + event MarketUpdateProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, string description); + event MarketUpdateProposalExecuted(uint id); + event MarketUpdateProposalCancelled(uint id); + + error AlreadyInitialized(); + error InvalidAddress(); + + + function initialize(ITimelock timelock_) public onlyOwner { + if (address(timelock_) == address(0)) revert InvalidAddress(); + if (address(timelock) != address(0)) revert AlreadyInitialized(); + + timelock = timelock_; + } + + function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) public onlyOwner returns (uint) { + require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, "MarketUpdateProposer::propose: proposal function information arity mismatch"); + require(targets.length != 0, "MarketUpdateProposer::propose: must provide actions"); + + proposalCount++; + uint newProposalID = proposalCount; + MarketUpdateProposal storage newProposal = proposals[newProposalID]; + + require(newProposal.id == 0, "MarketUpdateProposer::propose: ProposalID collision"); + uint eta = add256(block.timestamp, timelock.delay()); + newProposal.id = newProposalID; + newProposal.proposer = msg.sender; + newProposal.eta = eta; + newProposal.targets = targets; + newProposal.values = values; + newProposal.signatures = signatures; + newProposal.calldatas = calldatas; + newProposal.description = description; + newProposal.canceled = false; + newProposal.executed = false; + + proposals[newProposal.id] = newProposal; + + emit MarketUpdateProposalCreated(newProposal.id, msg.sender, targets, values, signatures, calldatas, description); + + for (uint i = 0; i < newProposal.targets.length; i++) { + queueOrRevertInternal(newProposal.targets[i], newProposal.values[i], newProposal.signatures[i], newProposal.calldatas[i], eta); + } + + return newProposal.id; + + } + + function queueOrRevertInternal(address target, uint value, string memory signature, bytes memory data, uint eta) internal { + require(!timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), "MarketUpdateProposer::queueOrRevertInternal: identical proposal action already queued at eta"); + timelock.queueTransaction(target, value, signature, data, eta); + } + + /** + * @notice Executes a queued proposal if eta has passed + * @param proposalId The id of the proposal to execute + */ + function execute(uint proposalId) external payable onlyOwner { + require(state(proposalId) == ProposalState.Queued, "MarketUpdateProposer::execute: proposal can only be executed if it is queued"); + MarketUpdateProposal storage proposal = proposals[proposalId]; + proposal.executed = true; + for (uint i = 0; i < proposal.targets.length; i++) { + timelock.executeTransaction{value: proposal.values[i]}(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta); + } + emit MarketUpdateProposalExecuted(proposalId); + } + + /** + * @notice Cancels a proposal only if sender is the proposer, or proposer delegates dropped below proposal threshold + * @param proposalId The id of the proposal to cancel + */ + function cancel(uint proposalId) external onlyOwner { + require(state(proposalId) != ProposalState.Executed, "MarketUpdateProposer::cancel: cannot cancel executed proposal"); + + MarketUpdateProposal storage proposal = proposals[proposalId]; + + proposal.canceled = true; + for (uint i = 0; i < proposal.targets.length; i++) { + timelock.cancelTransaction(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta); + } + + emit MarketUpdateProposalCancelled(proposalId); + } + + function state(uint proposalId) public view returns (ProposalState) { + require(proposalCount >= proposalId && proposalId > initialProposalId, "MarketUpdateProposer::state: invalid proposal id"); + MarketUpdateProposal storage proposal = proposals[proposalId]; + if (proposal.canceled) { + return ProposalState.Canceled; + } else if (proposal.executed) { + return ProposalState.Executed; + } else if (block.timestamp >= add256(proposal.eta, timelock.GRACE_PERIOD())) { + return ProposalState.Expired; + } else { + return ProposalState.Queued; + } + } + + function add256(uint256 a, uint256 b) internal pure returns (uint) { + uint c = a + b; + require(c >= a, "addition overflow"); + return c; + } + + function getProposal(uint proposalId) public view + returns ( + uint id, + address proposer, + uint eta, + address[] memory targets, + uint[] memory values, + string[] memory signatures, + bytes[] memory calldatas, + string memory description, + bool canceled, + bool executed + ) + { + MarketUpdateProposal storage proposal = proposals[proposalId]; + return ( + proposal.id, + proposal.proposer, + proposal.eta, + proposal.targets, + proposal.values, + proposal.signatures, + proposal.calldatas, + proposal.description, + proposal.canceled, + proposal.executed + ); + } +} diff --git a/contracts/marketupdates/MarketUpdateTimelock.sol b/contracts/marketupdates/MarketUpdateTimelock.sol new file mode 100644 index 00000000..e9bdcc22 --- /dev/null +++ b/contracts/marketupdates/MarketUpdateTimelock.sol @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; + +import "./SafeMath.sol"; + +/* + +Right now admin and marketUpdateProposer can cancel one another's transactions, but +this is not a realistic scenario as admin is a main-governor-timelock which will not be +queuing, executing, or cancelling transactions. So we are not handling or testing it. +*/ +contract MarketUpdateTimelock { + using SafeMath for uint; + + event NewAdmin(address indexed oldAdmin, address indexed newAdmin); + event NewMarketUpdateProposer(address indexed oldMarketAdmin, address indexed newMarketAdmin); + event NewDelay(uint indexed newDelay); + event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); + event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); + event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); + + uint public constant GRACE_PERIOD = 14 days; + uint public constant MINIMUM_DELAY = 0 days; + uint public constant MAXIMUM_DELAY = 30 days; + + address public admin; + address public marketUpdateProposer; + uint public delay; + + mapping (bytes32 => bool) public queuedTransactions; + + modifier adminOrMarketUpdater { + require(msg.sender == admin || msg.sender == marketUpdateProposer, "MarketUpdateTimelock::Unauthorized: call must come from admin or marketAdmin"); + _; + } + + constructor(address admin_, uint delay_) public { + require(delay_ >= MINIMUM_DELAY, "MarketUpdateTimelock::constructor: Delay must exceed minimum delay."); + require(delay_ <= MAXIMUM_DELAY, "MarketUpdateTimelock::setDelay: Delay must not exceed maximum delay."); + + admin = admin_; + delay = delay_; + } + + fallback() external payable { } + + + function setDelay(uint delay_) public { + require(msg.sender == address(this), "MarketUpdateTimelock::setDelay: Call must come from Timelock."); + require(delay_ >= MINIMUM_DELAY, "MarketUpdateTimelock::setDelay: Delay must exceed minimum delay."); + require(delay_ <= MAXIMUM_DELAY, "MarketUpdateTimelock::setDelay: Delay must not exceed maximum delay."); + delay = delay_; + + emit NewDelay(delay); + } + + function setAdmin(address newAdmin) public { + require(msg.sender == admin, "MarketUpdateTimelock::setAdmin: Call must come from admin."); + address oldAdmin = admin; + admin = newAdmin; + emit NewAdmin(oldAdmin, newAdmin); + } + + function setMarketUpdateProposer(address newMarketUpdateProposer) external { + require(msg.sender == admin, "MarketUpdateTimelock::setMarketUpdateProposer: Call must come from admin."); + address oldMarketUpdateProposer = marketUpdateProposer; + marketUpdateProposer = newMarketUpdateProposer; + emit NewMarketUpdateProposer(oldMarketUpdateProposer, newMarketUpdateProposer); + } + + function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public adminOrMarketUpdater returns (bytes32) { + require(eta >= getBlockTimestamp().add(delay), "MarketUpdateTimelock::queueTransaction: Estimated execution block must satisfy delay."); + + bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); + queuedTransactions[txHash] = true; + + emit QueueTransaction(txHash, target, value, signature, data, eta); + return txHash; + } + + function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public adminOrMarketUpdater { + bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); + queuedTransactions[txHash] = false; + + emit CancelTransaction(txHash, target, value, signature, data, eta); + } + + function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable adminOrMarketUpdater returns (bytes memory) { + bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); + require(queuedTransactions[txHash], "MarketUpdateTimelock::executeTransaction: Transaction hasn't been queued."); + require(getBlockTimestamp() >= eta, "MarketUpdateTimelock::executeTransaction: Transaction hasn't surpassed time lock."); + require(getBlockTimestamp() <= eta.add(GRACE_PERIOD), "MarketUpdateTimelock::executeTransaction: Transaction is stale."); + + queuedTransactions[txHash] = false; + + bytes memory callData; + + if (bytes(signature).length == 0) { + callData = data; + } else { + callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data); + } + + // solium-disable-next-line security/no-call-value + (bool success, bytes memory returnData) = target.call{value: value}(callData); + require(success, "MarketUpdateTimelock::executeTransaction: Transaction execution reverted."); + + emit ExecuteTransaction(txHash, target, value, signature, data, eta); + + return returnData; + } + + function getBlockTimestamp() internal view returns (uint) { + // solium-disable-next-line security/no-block-members + return block.timestamp; + } +} diff --git a/contracts/marketupdates/SafeMath.sol b/contracts/marketupdates/SafeMath.sol new file mode 100644 index 00000000..f9a3ca1c --- /dev/null +++ b/contracts/marketupdates/SafeMath.sol @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; + +// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol +// Subject to the MIT license. + +/** + * @dev Wrappers over Solidity's arithmetic operations with added overflow + * checks. + * + * Arithmetic operations in Solidity wrap on overflow. This can easily result + * in bugs, because programmers usually assume that an overflow raises an + * error, which is the standard behavior in high level programming languages. + * `SafeMath` restores this intuition by reverting the transaction when an + * operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, reverting on overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c; + unchecked { c = a + b; } + require(c >= a, "SafeMath: addition overflow"); + + return c; + } + + /** + * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + uint256 c; + unchecked { c = a + b; } + require(c >= a, errorMessage); + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot underflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + return sub(a, b, "SafeMath: subtraction underflow"); + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot underflow. + */ + function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b <= a, errorMessage); + uint256 c = a - b; + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint256 c; + unchecked { c = a * b; } + require(c / a == b, "SafeMath: multiplication overflow"); + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint256 c; + unchecked { c = a * b; } + require(c / a == b, errorMessage); + + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers. + * Reverts on division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + return div(a, b, "SafeMath: division by zero"); + } + + /** + * @dev Returns the integer division of two unsigned integers. + * Reverts with custom message on division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + // Solidity only automatically asserts when dividing by 0 + require(b > 0, errorMessage); + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + + return c; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + return mod(a, b, "SafeMath: modulo by zero"); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts with custom message when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b != 0, errorMessage); + return a % b; + } +} \ No newline at end of file diff --git a/contracts/test/GovernorSimple.sol b/contracts/test/GovernorSimple.sol index ad17838a..4d640753 100644 --- a/contracts/test/GovernorSimple.sol +++ b/contracts/test/GovernorSimple.sol @@ -3,9 +3,9 @@ pragma solidity 0.8.15; interface TimelockInterface { function queuedTransactions(bytes32 hash) external view returns (bool); - function queueTransaction(address target, uint value, string calldata signature, bytes calldata data) external returns (bytes32); + function queueTransaction(address target, uint value, string calldata signature, bytes calldata data, uint eta) external returns (bytes32); function cancelTransaction(address target, uint value, string calldata signature, bytes calldata data) external; - function executeTransaction(address target, uint value, string calldata signature, bytes calldata data) external payable returns (bytes memory); + function executeTransaction(address target, uint value, string calldata signature, bytes calldata data, uint eta) external payable returns (bytes memory); function executeTransactions(address[] calldata targets, uint[] calldata values, string[] calldata signatures, bytes[] calldata data) external payable; } @@ -155,7 +155,7 @@ contract GovernorSimple { function queueOrRevertInternal(address target, uint value, string memory signature, bytes memory data) internal { require(!timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data))), "GovernorSimple::queueOrRevertInternal: identical proposal action already queued at eta"); - timelock.queueTransaction(target, value, signature, data); + timelock.queueTransaction(target, value, signature, data, 0); } /** @@ -170,7 +170,7 @@ contract GovernorSimple { proposal.queued = false; proposal.executed = true; for (uint i = 0; i < proposal.targets.length; i++) { - timelock.executeTransaction{ value:proposal.values[i] }(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i]); + timelock.executeTransaction{ value:proposal.values[i] }(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], 0); } emit ProposalExecuted(proposalId); } diff --git a/deployments/localhost/dai/configuration.json b/deployments/localhost/dai/configuration.json new file mode 100644 index 00000000..61cbcd5d --- /dev/null +++ b/deployments/localhost/dai/configuration.json @@ -0,0 +1,26 @@ +{ + "name": "Compound DAI", + "symbol": "cDAIv3", + "baseToken": "DAI", + "borrowMin": "1000e6", + "storeFrontPriceFactor": 0.5, + "targetReserves": "5000000e6", + "rates": { + "supplyKink": 0.8, + "supplySlopeLow": 0.0325, + "supplySlopeHigh": 0.4, + "supplyBase": 0, + "borrowKink": 0.8, + "borrowSlopeLow": 0.035, + "borrowSlopeHigh": 0.25, + "borrowBase": 0.015 + }, + "tracking": { + "indexScale": "1e15", + "baseSupplySpeed": "0.000011574074074074073e15", + "baseBorrowSpeed": "0.0011458333333333333e15", + "baseMinForRewards": "1000000e6" + }, + "rewardToken": "GOLD", + "assets": {} +} diff --git a/deployments/localhost/dai/deploy.ts b/deployments/localhost/dai/deploy.ts new file mode 100644 index 00000000..2b47f125 --- /dev/null +++ b/deployments/localhost/dai/deploy.ts @@ -0,0 +1,519 @@ +import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; +import {Comet, FaucetToken, SimplePriceFeed, MarketUpdateProposer, CometProxyAdmin, SimpleTimelock, CometProxyAdminOld, MarketUpdateTimelock, CometFactory, ConfiguratorProxy, Configurator__factory} from '../../../build/types'; +import { + DeploySpec, + exp, + wait, + getConfiguration, + sameAddress, + COMP_WHALES, + getConfigurationStruct +} from '../../../src/deploy'; +import '@nomiclabs/hardhat-ethers'; + +async function makeToken( + deploymentManager: DeploymentManager, + amount: number, + name: string, + decimals: number, + symbol: string +): Promise { + const mint = (BigInt(amount) * 10n ** BigInt(decimals)).toString(); + return deploymentManager.deploy(symbol, 'test/FaucetToken.sol', [mint, name, decimals, symbol]); +} + +async function makePriceFeed( + deploymentManager: DeploymentManager, + alias: string, + initialPrice: number, + decimals: number +): Promise { + return deploymentManager.deploy(alias, 'test/SimplePriceFeed.sol', [initialPrice * 1e8, decimals]); +} + +// TODO: Support configurable assets as well? +export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { + const trace = deploymentManager.tracer(); + const signer = await deploymentManager.getSigner(); + const ethers = deploymentManager.hre.ethers; + const admin = signer; + const voterAddress = COMP_WHALES.testnet[0]; + + // Deploy governance contracts + const clone = { + comp: '0xc00e94cb662c3520282e6f5717214004a7f26888', + governorBravoImpl: '0xef3b6e9e13706a8f01fe98fdcf66335dc5cfdeed', + governorBravo: '0xc0da02939e1441f497fd74f78ce7decb17b66529', + }; + + const fauceteer = await deploymentManager.deploy('fauceteer', 'test/Fauceteer.sol', []); + const timelock = await deploymentManager.deploy('timelock', 'test/SimpleTimelock.sol', [admin.address]) as SimpleTimelock; + + const COMP = await deploymentManager.clone('COMP', clone.comp, [admin.address]); + + + await deploymentManager.idempotent( + async () => (await COMP.balanceOf(admin.address)).gte((await COMP.totalSupply()).div(3)), + async () => { + trace(`Sending 1/4 of COMP to fauceteer, 1/4 to timelock`); + const amount = (await COMP.balanceOf(admin.address)).div(4); + trace(await wait(COMP.connect(admin).transfer(fauceteer.address, amount))); + trace(await wait(COMP.connect(admin).transfer(timelock.address, amount))); + trace(`COMP.balanceOf(${fauceteer.address}): ${await COMP.balanceOf(fauceteer.address)}`); + trace(`COMP.balanceOf(${timelock.address}): ${await COMP.balanceOf(timelock.address)}`); + } + ); + + await deploymentManager.idempotent( + async () => (await COMP.getCurrentVotes(voterAddress)).eq(0), + async () => { + trace(`Delegating COMP votes to ${voterAddress}`); + trace(await wait(COMP.connect(admin).delegate(voterAddress))); + trace(`COMP.getCurrentVotes(${voterAddress}): ${await COMP.getCurrentVotes(voterAddress)}`); + } + ); + + const DAI = await makeToken(deploymentManager, 10000000, 'DAI', 18, 'DAI'); + const GOLD = await makeToken(deploymentManager, 20000000, 'GOLD', 8, 'GOLD'); + const SILVER = await makeToken(deploymentManager, 30000000, 'SILVER', 10, 'SILVER'); + + const daiPriceFeed = await makePriceFeed(deploymentManager, 'DAI:priceFeed', 1, 8); + const goldPriceFeed = await makePriceFeed(deploymentManager, 'GOLD:priceFeed', 0.5, 8); + const silverPriceFeed = await makePriceFeed(deploymentManager, 'SILVER:priceFeed', 0.05, 8); + + const assetConfig0 = { + asset: GOLD.address, + priceFeed: goldPriceFeed.address, + decimals: (8).toString(), + borrowCollateralFactor: (0.9e18).toString(), + liquidateCollateralFactor: (0.91e18).toString(), + liquidationFactor: (0.95e18).toString(), + supplyCap: (1000000e8).toString(), + }; + + const assetConfig1 = { + asset: SILVER.address, + priceFeed: silverPriceFeed.address, + decimals: (10).toString(), + borrowCollateralFactor: (0.4e18).toString(), + liquidateCollateralFactor: (0.5e18).toString(), + liquidationFactor: (0.9e18).toString(), + supplyCap: (500000e10).toString(), + }; + + const configOverrides = { + baseTokenPriceFeed: daiPriceFeed.address, + assetConfigs: [assetConfig0, assetConfig1], + }; + + const rewards = await deploymentManager.deploy( + 'rewards', + 'CometRewards.sol', + [admin.address], + maybeForce(deploySpec.rewards) + ); + + await deploymentManager.idempotent( + async () => (await GOLD.balanceOf(rewards.address)).eq(0), + async () => { + trace(`Sending some GOLD to CometRewards`); + const amount = exp(2_000_000, 8); + trace(await wait(GOLD.connect(signer).transfer(rewards.address, amount))); + trace(`GOLD.balanceOf(${rewards.address}): ${await GOLD.balanceOf(rewards.address)}`); + } + ); + + function maybeForce(flag?: boolean): boolean { + return deploySpec.all || flag; + } + + + const { + name, + symbol, + governor, // NB: generally 'timelock' alias, not 'governor' + pauseGuardian, + baseToken, + baseTokenPriceFeed, + supplyKink, + supplyPerYearInterestRateSlopeLow, + supplyPerYearInterestRateSlopeHigh, + supplyPerYearInterestRateBase, + borrowKink, + borrowPerYearInterestRateSlopeLow, + borrowPerYearInterestRateSlopeHigh, + borrowPerYearInterestRateBase, + storeFrontPriceFactor, + trackingIndexScale, + baseTrackingSupplySpeed, + baseTrackingBorrowSpeed, + baseMinForRewards, + baseBorrowMin, + targetReserves, + assetConfigs, + } = await getConfiguration(deploymentManager, configOverrides); + + /* Deploy contracts */ + + const cometProxyAdminOld = await deploymentManager.deploy( + 'cometAdminOld', + 'marketupdates/CometProxyAdminOld.sol', + [], + maybeForce() + ) as CometProxyAdminOld; + + + + const extConfiguration = { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }; + const cometExt = await deploymentManager.deploy( + 'comet:implementation:implementation', + 'CometExt.sol', + [extConfiguration], + maybeForce(deploySpec.cometExt) + ); + + const cometFactory = await deploymentManager.deploy( + 'cometFactory', + 'CometFactory.sol', + [], + maybeForce(deploySpec.cometMain) + ) as CometFactory; + + const configuration = { + governor, + pauseGuardian, + baseToken, + baseTokenPriceFeed, + extensionDelegate: cometExt.address, + supplyKink, + supplyPerYearInterestRateSlopeLow, + supplyPerYearInterestRateSlopeHigh, + supplyPerYearInterestRateBase, + borrowKink, + borrowPerYearInterestRateSlopeLow, + borrowPerYearInterestRateSlopeHigh, + borrowPerYearInterestRateBase, + storeFrontPriceFactor, + trackingIndexScale, + baseTrackingSupplySpeed, + baseTrackingBorrowSpeed, + baseMinForRewards, + baseBorrowMin, + targetReserves, + assetConfigs, + }; + trace('Timelock address:', timelock.address); + trace('Governor address:', governor); + + const tmpCometImpl = await deploymentManager.deploy( + 'comet:implementation', + 'Comet.sol', + [configuration], + maybeForce(), + ) as Comet; + + trace('Checking tmpCometImpl:supplyKink'); + console.log('tmpCometImpl:supplyKink', await tmpCometImpl.supplyKink()); + const cometProxyContract = await deploymentManager.deploy( + 'comet', + 'vendor/proxy/transparent/TransparentUpgradeableProxy.sol', + [tmpCometImpl.address, cometProxyAdminOld.address, []], // NB: temporary implementation contract + maybeForce() + ); + const factory= await ethers.getContractFactory('Comet'); + const cometProxy= factory.attach(cometProxyContract.address) as Comet; + + trace('tmpCometImpl', tmpCometImpl.address); + + trace('Checking CometProxy:supplyKink'); + console.log('CometProxy:supplyKink', await cometProxy.supplyKink()); + + + const configuratorImpl = await deploymentManager.deploy( + 'configurator-old:implementation', + 'marketupdates/ConfiguratorOld.sol', + [], + maybeForce(deploySpec.cometMain) + ); + + // If we deploy a new proxy, we initialize it to the current/new impl + // If its an existing proxy, the impl we got for the alias must already be current + // In other words, we shan't have deployed an impl in the last step unless there was no proxy too + const configuratorProxyContract = await deploymentManager.deploy( + 'configurator', + 'ConfiguratorProxy.sol', + [configuratorImpl.address, signer.address, (await configuratorImpl.populateTransaction.initialize(admin.address)).data], + maybeForce() + ) as ConfiguratorProxy; + + const configuratorFactory = await ethers.getContractFactory('Configurator') as Configurator__factory; + const configuratorProxy = configuratorFactory.attach(configuratorProxyContract.address); + trace(`Setting factory in Configurator to ${cometFactory.address}`); + await configuratorProxy.connect(admin).setFactory(cometProxy.address, cometFactory.address); + + + const configurationStr = await getConfigurationStruct(deploymentManager); + trace(`Setting configuration in Configurator for ${cometProxy.address}`); + await configuratorProxy.connect(admin).setConfiguration(cometProxy.address, configurationStr); + // await txSetConfiguration.wait(); + + + trace(`Upgrading implementation of Comet...`); + + await configuratorProxyContract.changeAdmin(cometProxyAdminOld.address); + + await cometProxyAdminOld.deployAndUpgradeTo(configuratorProxy.address, cometProxy.address); + + await cometProxyAdminOld.transferOwnership(timelock.address); + + /* Wire things up */ + + // Now configure the configurator and actually deploy comet + // Note: the success of these calls is dependent on who the admin is and if/when its been transferred + // scenarios can pass in an impersonated signer, but real deploys may require proposals for some states + const configurator = configuratorImpl.attach(configuratorProxyContract.address); + + // Also get a handle for Comet, although it may not *actually* support the interface yet + const comet = await deploymentManager.cast(cometProxy.address, 'contracts/CometInterface.sol:CometInterface'); + + // Call initializeStorage if storage not initialized + // Note: we now rely on the fact that anyone may call, which helps separate the proposal + await deploymentManager.idempotent( + async () => (await comet.totalsBasic()).lastAccrualTime == 0, + async () => { + trace(`Initializing Comet at ${comet.address}`); + trace(await wait(comet.connect(admin).initializeStorage())); + } + ); + + // If we aren't admin, we'll need proposals to configure things + const amAdmin = sameAddress(await cometProxyAdminOld.owner(), admin.address); + trace(`Am I admin? ${amAdmin}`); + + // Get the current impl addresses for the proxies, and determine if we've configurated + const $cometImpl = await cometProxyAdminOld.getProxyImplementation(comet.address); + const isTmpImpl = sameAddress($cometImpl, tmpCometImpl.address); + trace(`isTmpImpl ${isTmpImpl} deploySpec.all ${deploySpec.all} deploySpec.cometMain ${deploySpec.cometMain} deploySpec.cometExt ${deploySpec.cometExt}`); + + + /* Transfer to Gov */ + + await deploymentManager.idempotent( + async () => !sameAddress(await configurator.governor(), governor), + async () => { + trace(`Transferring governor of Configurator to ${governor}`); + trace(await wait(configurator.connect(admin).transferGovernor(governor))); + } + ); + + await deploymentManager.idempotent( + async () => !sameAddress(await cometProxyAdminOld.owner(), governor), + async () => { + trace(`Transferring ownership of CometProxyAdmin to ${governor}`); + trace(await wait(cometProxyAdminOld.connect(admin).transferOwnership(governor))); + } + ); + + await deploymentManager.idempotent( + async () => !sameAddress(await rewards.governor(), governor), + async () => { + trace(`Transferring governor of CometRewards to ${governor}`); + trace(await wait(rewards.connect(admin).transferGovernor(governor))); + } + ); + + + // Mint some tokens + trace(`Attempting to mint as ${signer.address}...`); + + await Promise.all( + [[DAI, 1e8], [GOLD, 2e6], [SILVER, 1e7]].map(([faucetToken, unitOfToken]) => { + const asset = faucetToken as FaucetToken; + const units = unitOfToken as number; + + return deploymentManager.idempotent( + async () => (await asset.balanceOf(fauceteer.address)).eq(0), + async () => { + trace(`Minting ${units} ${await asset.symbol()} to fauceteer`); + const amount = exp(units, await asset.decimals()); + trace(await wait(asset.connect(signer).allocateTo(fauceteer.address, amount))); + trace(`asset.balanceOf(${signer.address}): ${await asset.balanceOf(signer.address)}`); + } + ); + }) + ); + + const supplyKinkOld = await comet.supplyKink(); + trace(`supplyKink:`, supplyKinkOld); + + const signers = await ethers.getSigners(); + + // 1) Deploy the address of MarketAdminMultiSig + const marketUpdateMultiSig = signers[3]; + + const marketUpdateProposer = await deploymentManager.deploy( + 'marketUpdateProposer', + 'marketupdates/MarketUpdateProposer.sol', + [], + maybeForce() + ) as MarketUpdateProposer; + + + + const marketUpdateTimelock = await deploymentManager.deploy( + 'marketUpdateTimelock', + 'marketupdates/MarketUpdateTimelock.sol', + [governor, 0], + maybeForce() + ) as MarketUpdateTimelock; + + await marketUpdateProposer.initialize(marketUpdateTimelock.address); + + await marketUpdateProposer.transferOwnership(marketUpdateMultiSig.address); + + const cometProxyAdminNew = await deploymentManager.deploy( + 'cometProxyAdminNew', + 'CometProxyAdmin.sol', + [], + maybeForce() + ) as CometProxyAdmin; + + await cometProxyAdminNew.transferOwnership(governor); + + const configuratorNew = await deploymentManager.deploy( + 'configuratorNew', + 'Configurator.sol', + [], + maybeForce() + ); + + trace('Updating Admin of Configurator to CometProxyAdminNew'); + await timelock.executeTransactions( + [cometProxyAdminOld.address], + [0], + ['changeProxyAdmin(address,address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, cometProxyAdminNew.address] + ) + ] + ); + + + + trace('Updating Admin of CometProxy to CometProxyAdminNew'); + await timelock.executeTransactions( + [cometProxyAdminOld.address], + [0], + ['changeProxyAdmin(address,address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [cometProxy.address, cometProxyAdminNew.address] + ) + ] + ); + + await timelock.executeTransactions( + [cometProxyAdminNew.address], + [0], + ['upgrade(address,address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, configuratorNew.address] + ) + ] + ); + + trace('Setting Market Update Admin in Configurator'); + await timelock.executeTransactions( + [configuratorProxyContract.address], + [0], + ['setMarketAdmin(address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketUpdateTimelock.address] + ) + ] + ); + + trace('Setting Market Update Admin in CometProxyAdmin'); + await timelock.executeTransactions( + [cometProxyAdminNew.address], + [0], + ['setMarketAdmin(address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketUpdateTimelock.address] + ) + ] + ); + + trace('Setting Market Update proposer in MarketUpdateTimelock'); + await timelock.executeTransactions( + [marketUpdateTimelock.address], + [0], + ['setMarketUpdateProposer(address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketUpdateProposer.address] + ) + ] + ); + + trace('Governor Timelock: Setting new supplyKink in Configurator and deploying Comet'); + const newSupplyKinkByGovernorTimelock = 300n; + await timelock.executeTransactions( + [configuratorProxyContract.address, cometProxyAdminNew.address], + [0, 0], + ['setSupplyKink(address,uint64)', 'deployAndUpgradeTo(address,address)'], + [ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, newSupplyKinkByGovernorTimelock] + ), + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, cometProxy.address] + ) + ], + ); + + const supplyKinkByGovernorTimelock = await (comet).supplyKink(); + trace(`supplyKinkByGovernorTimelock:`, supplyKinkByGovernorTimelock); + + trace('MarketAdmin: Setting new supplyKink in Configurator and deploying Comet'); + const newSupplyKinkByMarketAdmin = 100n; + await marketUpdateProposer.connect(marketUpdateMultiSig).propose( + [configuratorProxyContract.address, cometProxyAdminNew.address], + [0, 0], + ['setSupplyKink(address,uint64)', 'deployAndUpgradeTo(address,address)'], + [ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, newSupplyKinkByMarketAdmin] + ), + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, cometProxy.address] + ) + ], + 'Test market update' + ); + + trace('Executing market update proposal'); + + await marketUpdateProposer.connect(marketUpdateMultiSig).execute(1); + + trace('checking supplyKink after market update'); + const supplyKinkByMarketAdmin = await (cometProxy).supplyKink(); + trace(`supplyKinkByMarketAdmin:`, supplyKinkByMarketAdmin); + + return { comet, configurator, rewards, fauceteer }; +} diff --git a/hardhat.config.ts b/hardhat.config.ts index c532b5ef..0ea5fd7d 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -233,6 +233,16 @@ const config: HardhatUserConfig = { allowUnlimitedContractSize: true, hardfork: 'shanghai' }, + localhost: { + url: 'http://127.0.0.1:8545', + loggingEnabled: true, + gas: 120000000, + gasPrice: 'auto', + blockGasLimit: 120000000, + accounts: { mnemonic: MNEMONIC, accountsBalance: (10n ** 36n).toString() }, + // this should only be relied upon for test harnesses and coverage (which does not use viaIR flag) + allowUnlimitedContractSize: true, + }, }, // See https://hardhat.org/plugins/nomiclabs-hardhat-etherscan.html#multiple-api-keys-and-alternative-block-explorers @@ -598,4 +608,4 @@ const config: HardhatUserConfig = { setupDefaultNetworkProviders(config); -export default config; \ No newline at end of file +export default config; diff --git a/tasks/deployment_manager/task.ts b/tasks/deployment_manager/task.ts index f6828691..5277f6c9 100644 --- a/tasks/deployment_manager/task.ts +++ b/tasks/deployment_manager/task.ts @@ -93,7 +93,7 @@ task('deploy', 'Deploys market') const verify = noVerify ? false : !simulate; const desc = verify ? 'Verify' : 'Would verify'; - if (noVerify && simulate) { + if (noVerify || simulate) { // Don't even print if --no-verify is set with --simulate } else { await dm.verifyContracts(async (address, args) => { diff --git a/test/helpers.ts b/test/helpers.ts index 58acf19a..028b4a61 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -340,36 +340,19 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { }; } -// Only for testing configurator. Non-configurator tests need to deploy the CometHarness instead. -export async function makeConfigurator(opts: ProtocolOpts = {}): Promise { - const assets = opts.assets || defaultAssets(); - - const { - governor, - pauseGuardian, - extensionDelegate, - users, - base, - reward, - comet, - tokens, - unsupportedToken, - priceFeeds, - } = await makeProtocol(opts); - - // Deploy ProxyAdmin - const ProxyAdmin = (await ethers.getContractFactory('CometProxyAdmin')) as CometProxyAdmin__factory; - const proxyAdmin = await ProxyAdmin.connect(governor).deploy(); - await proxyAdmin.deployed(); +export async function getConfigurationForConfigurator( + opts: ProtocolOpts, + comet: CometHarnessInterface, + governor: SignerWithAddress, + pauseGuardian: SignerWithAddress, + extensionDelegate: CometExt, + tokens: { + [p: string]: FaucetToken | NonStandardFaucetFeeToken; + }, + base: string, + priceFeeds: { [p: string]: SimplePriceFeed }) { - // Deploy Comet proxy - const CometProxy = (await ethers.getContractFactory('TransparentUpgradeableProxy')) as TransparentUpgradeableProxy__factory; - const cometProxy = await CometProxy.deploy( - comet.address, - proxyAdmin.address, - (await comet.populateTransaction.initializeStorage()).data, - ); - await cometProxy.deployed(); + const assets = opts.assets || defaultAssets(); // Derive the rest of the Configurator configuration values const supplyKink = dfn(opts.supplyKink, exp(0.8, 18)); @@ -388,15 +371,6 @@ export async function makeConfigurator(opts: ProtocolOpts = {}): Promise { + + + const { + governor, + pauseGuardian, + extensionDelegate, + users, + base, + reward, + comet, + tokens, + unsupportedToken, + priceFeeds, + } = await makeProtocol(opts); + + // Deploy ProxyAdmin + const ProxyAdmin = (await ethers.getContractFactory('CometProxyAdmin')) as CometProxyAdmin__factory; + const proxyAdmin = await ProxyAdmin.connect(governor).deploy(); + await proxyAdmin.deployed(); + + // Deploy Comet proxy + const CometProxy = (await ethers.getContractFactory('TransparentUpgradeableProxy')) as TransparentUpgradeableProxy__factory; + const cometProxy = await CometProxy.deploy( + comet.address, + proxyAdmin.address, + (await comet.populateTransaction.initializeStorage()).data, + ); + await cometProxy.deployed(); + const configuration = await getConfigurationForConfigurator( + opts, + comet, + governor, + pauseGuardian, + extensionDelegate, + tokens, + base, + priceFeeds, + ); + + // Deploy CometFactory + const CometFactoryFactory = (await ethers.getContractFactory('CometFactory')) as CometFactory__factory; + const cometFactory = await CometFactoryFactory.deploy(); + await cometFactory.deployed(); + + // Deploy Configurator + const ConfiguratorFactory = (await ethers.getContractFactory('Configurator')) as Configurator__factory; + const configurator = await ConfiguratorFactory.deploy(); + await configurator.deployed(); // Deploy Configurator proxy const initializeCalldata = (await configurator.populateTransaction.initialize(governor.address)).data; @@ -443,12 +470,11 @@ export async function makeConfigurator(opts: ProtocolOpts = {}): Promise { + const { signer, timelock } = await initializeAndFundTimelock(); + + const { + configurator, + configuratorProxy, + cometProxy, + users: [alice] + } = await makeConfigurator({ + governor: signer + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + let setPauseGuardianCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [cometProxy.address, alice.address] + ); + + // This works fine as governor is set as timelock's admin + await timelock.executeTransactions( + [configuratorProxy.address], + [0], + ['setPauseGuardian(address,address)'], + [setPauseGuardianCalldata] + ); + expect( + (await configuratorAsProxy.getConfiguration(cometProxy.address)) + .pauseGuardian + ).to.be.equal(alice.address); + + // This will revert as alice is calling the timelock + await expect( + timelock.connect(alice).executeTransactions( + [configuratorProxy.address], + [0], // no Ether to be sent + ['setPauseGuardian(address,address)'], + [setPauseGuardianCalldata] + ) + ).to.be.revertedWithCustomError(timelock, 'Unauthorized'); + }); + + it("Ensure - Configurator's governor is set as timelock - Test for access", async () => { + const { signer, timelock } = await initializeAndFundTimelock(); + const { + configurator, + configuratorProxy, + cometProxy, + users: [alice] + } = await makeConfigurator({ governor: signer }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + let setPauseGuardianCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [cometProxy.address, alice.address] + ); + + // This works fine as configurator's governor is set as timelock + await timelock.executeTransactions( + [configuratorProxy.address], + [0], + ['setPauseGuardian(address,address)'], + [setPauseGuardianCalldata] + ); + + expect( + (await configuratorAsProxy.getConfiguration(cometProxy.address)) + .pauseGuardian + ).to.be.equal(alice.address); + }); + + it("Ensure - Configurator's governor is set as timelock - Test for not access", async () => { + const { signer, timelock } = await initializeAndFundTimelock(); + const { + governor, + configurator, + configuratorProxy, + cometProxy, + users: [alice] + } = await makeConfigurator({ governor: signer }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + await configuratorAsProxy.connect(governor).transferGovernor(alice.address); // set alice as governor of Configurator + + let setPauseGuardianCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [cometProxy.address, alice.address] + ); + + // This will revert as configurator's governor is set as Alice + await expect( + timelock.executeTransactions( + [configuratorProxy.address], + [0], // no Ether to be sent + ['setPauseGuardian(address,address)'], + [setPauseGuardianCalldata] + ) + ).to.be.revertedWith('failed to call'); + }); + + it("Ensure - CometProxyAdmin's owner is timelock - Test for access", async () => { + const { signer, timelock } = await initializeAndFundTimelock(); + const { + configuratorProxy, + proxyAdmin, + cometProxy + } = await makeConfigurator({ governor: signer }); + + let deployAndUpgradeToCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxy.address, cometProxy.address] + ); + + const txn = (await wait( + timelock.executeTransactions( + [proxyAdmin.address], + [0], + ['deployAndUpgradeTo(address,address)'], + [deployAndUpgradeToCalldata] + ) + )) as any; + + const abi = [ + 'event CometDeployed(address indexed cometProxy, address indexed newComet)', + 'event Upgraded(address indexed implementation)' + ]; + + // Initialize the contract interface + const iface = new ethers.utils.Interface(abi); + const events = []; + + txn.receipt.events.forEach(event => { + try { + const decodedEvent = iface.parseLog(event); + events.push(decodedEvent); + } catch (error) { + console.log('Failed to decode event:', error); + } + }); + + // verify the event names + expect(events[0].name).to.be.equal('CometDeployed'); + expect(events[1].name).to.be.equal('Upgraded'); + + const oldCometProxyAddress = cometProxy.address; + const oldCometProxyAddressFromEvent = events[0].args.cometProxy; + const newCometProxyAddress = events[0].args.newComet; + + expect(oldCometProxyAddress).to.be.equal(oldCometProxyAddressFromEvent); + expect(oldCometProxyAddress).to.be.not.equal(newCometProxyAddress); + }); + + it("Ensure - CometProxyAdmin's owner is timelock - Test for non-access", async () => { + const { signer, timelock } = await initializeAndFundTimelock(); + const { + configuratorProxy, + proxyAdmin, + cometProxy, + users: [alice] + } = await makeConfigurator({ governor: signer }); + + await proxyAdmin.transferOwnership(alice.address); // Transferred ownership to alice instead of timelock + + let deployAndUpgradeToCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxy.address, cometProxy.address] + ); + + expect( + timelock.executeTransactions( + [proxyAdmin.address], + [0], + ['deployAndUpgradeTo(address,address)'], + [deployAndUpgradeToCalldata] + ) + ).to.be.revertedWith('failed to call'); + }); + + it("Ensure - Comet's Proxy's admin is set as CometProxyAdmin - Test for access.", async () => { + const { + configurator, + configuratorProxy, + proxyAdmin, + comet, + cometProxy, + users: [alice] + } = await makeConfigurator(); + + const cometAsProxy = comet.attach(cometProxy.address); + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + expect( + (await configuratorAsProxy.getConfiguration(cometProxy.address)).governor + ).to.be.equal(await comet.governor()); + + const oldGovernor = await comet.governor(); + const newGovernor = alice.address; + const txn = await wait( + configuratorAsProxy.setGovernor(cometProxy.address, newGovernor) + ); + await wait( + proxyAdmin.deployAndUpgradeTo( + configuratorProxy.address, + cometProxy.address + ) + ); + + expect(event(txn, 0)).to.be.deep.equal({ + SetGovernor: { + cometProxy: cometProxy.address, + oldGovernor, + newGovernor + } + }); + expect(oldGovernor).to.be.not.equal(newGovernor); + expect( + (await configuratorAsProxy.getConfiguration(cometProxy.address)).governor + ).to.be.equal(newGovernor); + expect(await cometAsProxy.governor()).to.be.equal(newGovernor); + }); + + it("Ensure - Comet's Proxy's admin is set as CometProxyAdmin - Test for non-access.", async () => { + const { + configuratorProxy, + proxyAdmin, + comet, + users: [_alice, bob] + } = await makeConfigurator(); + + // Deploy ProxyAdmin + const ProxyAdmin = (await ethers.getContractFactory( + 'CometProxyAdmin' + )) as CometProxyAdmin__factory; + const proxyAdminTemp = await ProxyAdmin.connect(bob).deploy(); + await proxyAdminTemp.deployed(); + + // Deploy Comet proxy + const CometProxy = (await ethers.getContractFactory( + 'TransparentUpgradeableProxy' + )) as TransparentUpgradeableProxy__factory; + const cometProxy = await CometProxy.deploy( + comet.address, + proxyAdminTemp.address, + (await comet.populateTransaction.initializeStorage()).data + ); + await cometProxy.deployed(); + + await expect( + proxyAdmin.deployAndUpgradeTo( + configuratorProxy.address, + cometProxy.address + ) + ).to.be.reverted; + }); + + it("Add a test to create a proposal and execute it(This proposal changes the governor of configurator and the deploys the comet through ProxyAdmin). This proposal should update something simple on Comet's asset", async () => { + const { signer, timelock } = await initializeAndFundTimelock(); + const { + governor, + configuratorProxy, + proxyAdmin, + cometProxy, + comet, + users: [_alice] + } = await makeConfigurator({ governor: signer }); + const GovernorFactory = (await ethers.getContractFactory( + 'GovernorSimple' + )) as GovernorSimple__factory; + const governorBravo = await GovernorFactory.deploy(); + await governorBravo.deployed(); + governorBravo.initialize(timelock.address, [governor.address]); + + // Setting GovernorBravo as the admin of timelock + timelock.setAdmin(governorBravo.address); + + const cometAsProxy = comet.attach(cometProxy.address); + const ASSET_ADDRESS = (await cometAsProxy.getAssetInfo(1)).asset; + const NEW_ASSET_SUPPLY_CAP = ethers.BigNumber.from('500000000000000000000'); + + expect((await cometAsProxy.getAssetInfo(1)).supplyCap).to.be.not.equal( + NEW_ASSET_SUPPLY_CAP + ); + + let updateAssetSupplyCapCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'address', 'uint128'], + [cometProxy.address, ASSET_ADDRESS, NEW_ASSET_SUPPLY_CAP] + ); + let deployAndUpgradeToCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxy.address, cometProxy.address] + ); + + const proposeTx = (await wait( + governorBravo + .connect(governor) + .propose( + [configuratorProxy.address, proxyAdmin.address], + [0, 0], + [ + 'updateAssetSupplyCap(address,address,uint128)', + 'deployAndUpgradeTo(address,address)' + ], + [updateAssetSupplyCapCalldata, deployAndUpgradeToCalldata], + "Proposal to update Comet's governor" + ) + )) as any; + + const proposalId = proposeTx.receipt.events[0].args.id.toNumber(); + + await wait(governorBravo.connect(governor).queue(proposalId)); + + await wait(governorBravo.connect(governor).execute(proposalId)); + + expect( + (await cometAsProxy.getAssetInfoByAddress(ASSET_ADDRESS)).supplyCap + ).to.be.equal(NEW_ASSET_SUPPLY_CAP); + }); +}); +async function initializeAndFundTimelock() { + const signers = await ethers.getSigners(); + const gov = signers[0]; + const TimelockFactory = (await ethers.getContractFactory( + 'SimpleTimelock' + )) as SimpleTimelock__factory; + const timelock = await TimelockFactory.deploy(gov.address); + const timelockAddress = await timelock.deployed(); + + // Impersonate the account + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [timelockAddress.address] + }); + + // Fund the impersonated account + await gov.sendTransaction({ + to: timelock.address, + value: ethers.utils.parseEther('1.0') // Sending 1 Ether to cover gas fees + }); + + // Get the signer from the impersonated account + const signer = await ethers.getSigner(timelockAddress.address); + return { signer, timelock }; +} diff --git a/test/marketupdates/market-update-comet-proxy-admin-test.ts b/test/marketupdates/market-update-comet-proxy-admin-test.ts new file mode 100644 index 00000000..459d96be --- /dev/null +++ b/test/marketupdates/market-update-comet-proxy-admin-test.ts @@ -0,0 +1,506 @@ +import { expect, makeConfigurator, event, wait } from './../helpers'; +import { makeMarketAdmin } from './market-updates-helper'; +import { ethers } from 'hardhat'; + +describe('CometProxyAdmin', function() { + it('only main-governor-timelock can transferOwnership of CometProxyAdmin as it is the owner', async () => { + const { governorTimelockSigner } = await makeMarketAdmin(); + + const { + proxyAdmin, + users: [alice, bob], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const oldOwner = await proxyAdmin.owner(); + const txn = await wait( + proxyAdmin + .connect(governorTimelockSigner) + .transferOwnership(alice.address) + ); + + expect(event(txn, 0)).to.be.deep.equal({ + OwnershipTransferred: { + previousOwner: oldOwner, + newOwner: alice.address, + }, + }); + expect(await proxyAdmin.owner()).to.be.equal(alice.address); + + await expect( + proxyAdmin.connect(bob).transferOwnership(alice.address) + ).to.be.revertedWith('Ownable: caller is not the owner'); + }); + + it('market admin cannot transferOwnership of CometProxyAdmin', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + proxyAdmin, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + await proxyAdmin + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address); + + expect(await proxyAdmin.marketAdmin()).to.be.equal( + marketUpdateTimelock.address + ); + + await expect( + proxyAdmin + .connect(marketUpdateTimelockSigner) + .transferOwnership(alice.address) + ).to.be.revertedWith('Ownable: caller is not the owner'); + }); + + it('only main-governor-timelock can set or update marketAdminPauseGuardian', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateMultiSig, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + proxyAdmin, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const oldMarketAdminPauseGuardian = await proxyAdmin.marketAdminPauseGuardian(); + expect(oldMarketAdminPauseGuardian).to.be.equal( + ethers.constants.AddressZero + ); + + const txn = await wait( + proxyAdmin + .connect(governorTimelockSigner) + .setMarketAdminPauseGuardian(alice.address) + ); + expect(event(txn, 0)).to.be.deep.equal({ + SetMarketAdminPauseGuardian: { + oldPauseGuardian: oldMarketAdminPauseGuardian, + newPauseGuardian: alice.address, + }, + }); + const newMarketAdminPauseGuardian = await proxyAdmin.marketAdminPauseGuardian(); + expect(newMarketAdminPauseGuardian).to.be.equal(alice.address); + expect(newMarketAdminPauseGuardian).to.be.not.equal( + oldMarketAdminPauseGuardian + ); + await expect( + proxyAdmin + .connect(marketUpdateMultiSig) + .setMarketAdminPauseGuardian(marketUpdateTimelock.address) + ).to.be.revertedWithCustomError(proxyAdmin, 'Unauthorized'); + + await expect( + proxyAdmin + .connect(marketUpdateTimelockSigner) + .setMarketAdminPauseGuardian(marketUpdateTimelock.address) + ).to.be.revertedWithCustomError(proxyAdmin, 'Unauthorized'); + }); + + it('main-governor-timelock can pause and unpause market admin', async () => { + const { governorTimelockSigner } = await makeMarketAdmin(); + const { proxyAdmin } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + expect(await proxyAdmin.marketAdminPaused()).to.be.false; + + const txnOfPause = await wait( + proxyAdmin.connect(governorTimelockSigner).pauseMarketAdmin() + ); + + expect(event(txnOfPause, 0)).to.be.deep.equal({ + MarketAdminPaused: { + isMarketAdminPaused: true, + }, + }); + expect(await proxyAdmin.marketAdminPaused()).to.be.true; + + const txnOfUnpause = await wait( + proxyAdmin.connect(governorTimelockSigner).unpauseMarketAdmin() + ); + + expect(event(txnOfUnpause, 0)).to.be.deep.equal({ + MarketAdminPaused: { + isMarketAdminPaused: false, + }, + }); + expect(await proxyAdmin.marketAdminPaused()).to.be.false; + }); + + it('marketAdminPauseGuardian can pause market admin', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateMultiSig, + marketUpdateProposer, + } = await makeMarketAdmin(); + + const { + configuratorProxy, + cometProxy, + proxyAdmin, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + expect(await proxyAdmin.marketAdminPaused()).to.be.false; + + await proxyAdmin + .connect(governorTimelockSigner) + .setMarketAdminPauseGuardian(alice.address); + + expect(await proxyAdmin.marketAdminPauseGuardian()).to.be.equal( + alice.address + ); + + const txn = await wait(proxyAdmin.connect(alice).pauseMarketAdmin()); + + expect(event(txn, 0)).to.be.deep.equal({ + MarketAdminPaused: { + isMarketAdminPaused: true, + }, + }); + expect(await proxyAdmin.marketAdminPaused()).to.be.true; + + await proxyAdmin + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address); + + expect(await proxyAdmin.marketAdmin()).to.be.equal( + marketUpdateTimelock.address + ); + + const proposalId = 1n; + + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [proxyAdmin.address], + [0], + ['deployAndUpgradeTo(address,address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxy.address, cometProxy.address] + ), + ], + 'Upgrading comet proxy admin implementation' + ); + + await expect( + marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId) + ).to.be.rejectedWith( + 'MarketUpdateTimelock::executeTransaction: Transaction execution reverted.' + ); + }); + + it('marketAdminPauseGuardian cannot unpause market admin', async () => { + const { governorTimelockSigner } = await makeMarketAdmin(); + + const { + proxyAdmin, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + expect(await proxyAdmin.marketAdminPaused()).to.be.false; + + await proxyAdmin + .connect(governorTimelockSigner) + .setMarketAdminPauseGuardian(alice.address); + + expect(await proxyAdmin.marketAdminPauseGuardian()).to.be.equal( + alice.address + ); + + await expect( + proxyAdmin.connect(alice).unpauseMarketAdmin() + ).to.be.revertedWithCustomError(proxyAdmin, 'Unauthorized'); + }); + + it('deployAndUpgradeTo can be called by main-governor-timelock or market-admin', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + configuratorProxy, + cometProxy, + proxyAdmin, + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const abi = [ + 'event CometDeployed(address indexed cometProxy, address indexed newComet)', + 'event Upgraded(address indexed implementation)', + ]; + + // Initialize the contract interface + const iface = new ethers.utils.Interface(abi); + + const txnForGovernorTimelock = (await wait( + proxyAdmin + .connect(governorTimelockSigner) + .deployAndUpgradeTo(configuratorProxy.address, cometProxy.address) + )) as any; + + const eventsForGovernorTimelock = []; + + txnForGovernorTimelock.receipt.events.forEach((event) => { + try { + const decodedEvent = iface.parseLog(event); + eventsForGovernorTimelock.push(decodedEvent); + } catch (error) { + console.log('Failed to decode event:', error); + } + }); + + // verify the event names + expect(eventsForGovernorTimelock[0].name).to.be.equal('CometDeployed'); + expect(eventsForGovernorTimelock[1].name).to.be.equal('Upgraded'); + + await proxyAdmin + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address); + + expect(await proxyAdmin.marketAdmin()).to.be.equal( + marketUpdateTimelock.address + ); + + const txnForMarketAdmin = (await wait( + proxyAdmin + .connect(marketUpdateTimelockSigner) + .deployAndUpgradeTo(configuratorProxy.address, cometProxy.address) + )) as any; + + const eventsForMarketAdmin = []; + + txnForMarketAdmin.receipt.events.forEach((event) => { + try { + const decodedEvent = iface.parseLog(event); + eventsForMarketAdmin.push(decodedEvent); + } catch (error) { + console.log('Failed to decode event:', error); + } + }); + + // verify the event names + expect(eventsForMarketAdmin[0].name).to.be.equal('CometDeployed'); + expect(eventsForMarketAdmin[1].name).to.be.equal('Upgraded'); + }); + + it('deployUpgradeToAndCall can be called by main-governor-timelock or market-admin', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + configuratorProxy, + cometProxy, + proxyAdmin, + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const functionAbi = new ethers.utils.Interface(['function getReserves()']); + const calldata = functionAbi.encodeFunctionData('getReserves', []); + + const abiToCheck = [ + 'event CometDeployed(address indexed cometProxy, address indexed newComet)', + 'event Upgraded(address indexed implementation)', + ]; + + // Initialize the contract interface + const iface = new ethers.utils.Interface(abiToCheck); + + const txnForGovernorTimelock = (await wait( + proxyAdmin + .connect(governorTimelockSigner) + .deployUpgradeToAndCall( + configuratorProxy.address, + cometProxy.address, + calldata + ) + )) as any; + + const eventsForGovernorTimelock = []; + + txnForGovernorTimelock.receipt.events.forEach((event) => { + try { + const decodedEvent = iface.parseLog(event); + eventsForGovernorTimelock.push(decodedEvent); + } catch (error) { + console.log('Failed to decode event:', error); + } + }); + + // verify the event names + expect(eventsForGovernorTimelock[0].name).to.be.equal('CometDeployed'); + expect(eventsForGovernorTimelock[1].name).to.be.equal('Upgraded'); + + await proxyAdmin + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address); + + expect(await proxyAdmin.marketAdmin()).to.be.equal( + marketUpdateTimelock.address + ); + + const txnForMarketAdmin = (await wait( + proxyAdmin + .connect(marketUpdateTimelockSigner) + .deployUpgradeToAndCall( + configuratorProxy.address, + cometProxy.address, + calldata + ) + )) as any; + + const eventsForMarketAdmin = []; + + txnForMarketAdmin.receipt.events.forEach((event) => { + try { + const decodedEvent = iface.parseLog(event); + eventsForMarketAdmin.push(decodedEvent); + } catch (error) { + console.log('Failed to decode event:', error); + } + }); + + // verify the event names + expect(eventsForMarketAdmin[0].name).to.be.equal('CometDeployed'); + expect(eventsForMarketAdmin[1].name).to.be.equal('Upgraded'); + }); + + it('no other address can call deployAndUpgradeTo', async () => { + const { governorTimelockSigner } = await makeMarketAdmin(); + + const { + configuratorProxy, + cometProxy, + proxyAdmin, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + await expect( + proxyAdmin + .connect(alice) + .deployAndUpgradeTo(configuratorProxy.address, cometProxy.address) + ).to.be.revertedWith( + 'Unauthorized: caller is not owner or market update admin' + ); + }); + + it('no other address can call deployUpgradeToAndCall', async () => { + const { governorTimelockSigner } = await makeMarketAdmin(); + + const { + configuratorProxy, + cometProxy, + proxyAdmin, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const callData = '0x'; + + await expect( + proxyAdmin + .connect(alice) + .deployUpgradeToAndCall( + configuratorProxy.address, + cometProxy.address, + callData + ) + ).to.be.revertedWith( + 'Unauthorized: caller is not owner or market update admin' + ); + }); + + it('a new comet implementation gets deployed when main-governor-timelock calls deployAndUpgradeTo', async () => { + const { governorTimelockSigner } = await makeMarketAdmin(); + + const { + configuratorProxy, + cometProxy, + proxyAdmin, + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const oldCometImplementation = await proxyAdmin.getProxyImplementation( + cometProxy.address + ); + + await proxyAdmin + .connect(governorTimelockSigner) + .deployAndUpgradeTo(configuratorProxy.address, cometProxy.address); + + const newCometImplementation = await proxyAdmin.getProxyImplementation( + cometProxy.address + ); + expect(newCometImplementation).to.be.not.equal(oldCometImplementation); + }); + + it('a new comet implementation gets deployed when market admin calls deployAndUpgradeTo', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + configuratorProxy, + cometProxy, + proxyAdmin, + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + await proxyAdmin + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address); + + expect(await proxyAdmin.marketAdmin()).to.be.equal( + marketUpdateTimelock.address + ); + + const oldCometImplementation = await proxyAdmin.getProxyImplementation( + cometProxy.address + ); + + await proxyAdmin + .connect(marketUpdateTimelockSigner) + .deployAndUpgradeTo(configuratorProxy.address, cometProxy.address); + + const newCometImplementation = await proxyAdmin.getProxyImplementation( + cometProxy.address + ); + expect(newCometImplementation).to.be.not.equal(oldCometImplementation); + }); +}); diff --git a/test/marketupdates/market-update-configurator-test.ts b/test/marketupdates/market-update-configurator-test.ts new file mode 100644 index 00000000..8508006a --- /dev/null +++ b/test/marketupdates/market-update-configurator-test.ts @@ -0,0 +1,470 @@ +import { expect, makeConfigurator, event, wait } from './../helpers'; +import { makeMarketAdmin } from './market-updates-helper'; +import { ethers } from 'hardhat'; + +describe('Configurator', function() { + it('already initialized and is not able to initialize again with main-governor-timelock as admin', async () => { + const { + governorTimelockSigner, + governorTimelock, + } = await makeMarketAdmin(); + + const { configurator, configuratorProxy } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + // check already initialized properly + expect(await configuratorAsProxy.version()).to.be.equal(1); + expect(await configuratorAsProxy.governor()).to.be.equal( + governorTimelock.address + ); + expect(await configuratorAsProxy.governor()).to.be.equal( + governorTimelock.address + ); + + // check is not able to initialize again + await expect( + configuratorAsProxy.initialize(governorTimelock.address) + ).to.be.revertedWith("custom error 'AlreadyInitialized()'"); + }); + + it('only main-governor-timelock can set market admin', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateTimelockSigner, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { configurator, configuratorProxy } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + const oldMarketAdmin = await configuratorAsProxy.marketAdmin(); + + // Add a check to make sure its set as address(0) initially. So here oldMarketAdmin should be (0) + expect(oldMarketAdmin).to.be.equal(ethers.constants.AddressZero); + const txn = await wait( + configuratorAsProxy + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address) + ); + expect(event(txn, 0)).to.be.deep.equal({ + SetMarketAdmin: { + oldAdmin: oldMarketAdmin, + newAdmin: marketUpdateTimelock.address, + }, + }); + const newMarketAdmin = await configuratorAsProxy.marketAdmin(); + expect(newMarketAdmin).to.be.equal(marketUpdateTimelock.address); + expect(newMarketAdmin).to.be.not.equal(oldMarketAdmin); + + await expect( + configuratorAsProxy + .connect(marketUpdateMultiSig) + .setMarketAdmin(marketUpdateTimelock.address) + ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); + + await expect( + configuratorAsProxy + .connect(marketUpdateTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address) + ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); + }); + + it('only main-governor-timelock can set or update marketAdminPauseGuardian', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateMultiSig, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + configurator, + configuratorProxy, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + const oldMarketAdminPauseGuardian = await configuratorAsProxy.marketAdminPauseGuardian(); + expect(oldMarketAdminPauseGuardian).to.be.equal( + ethers.constants.AddressZero + ); + + const txn = await wait( + configuratorAsProxy + .connect(governorTimelockSigner) + .setMarketAdminPauseGuardian(alice.address) + ); + expect(event(txn, 0)).to.be.deep.equal({ + SetMarketAdminPauseGuardian: { + oldPauseGuardian: oldMarketAdminPauseGuardian, + newPauseGuardian: alice.address, + }, + }); + const newMarketAdminPauseGuardian = await configuratorAsProxy.marketAdminPauseGuardian(); + expect(newMarketAdminPauseGuardian).to.be.equal(alice.address); + expect(newMarketAdminPauseGuardian).to.be.not.equal( + oldMarketAdminPauseGuardian + ); + await expect( + configuratorAsProxy + .connect(marketUpdateMultiSig) + .setMarketAdminPauseGuardian(marketUpdateTimelock.address) + ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); + + await expect( + configuratorAsProxy + .connect(marketUpdateTimelockSigner) + .setMarketAdminPauseGuardian(marketUpdateTimelock.address) + ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); + }); + + it('main-governor-timelock can pause and unpause market admin', async () => { + const { governorTimelockSigner } = await makeMarketAdmin(); + const { configurator, configuratorProxy } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + expect(await configuratorAsProxy.marketAdminPaused()).to.be.false; + + const txnOfPause = await wait( + configuratorAsProxy.connect(governorTimelockSigner).pauseMarketAdmin() + ); + + expect(event(txnOfPause, 0)).to.be.deep.equal({ + MarketAdminPaused: { + isMarketAdminPaused: true, + }, + }); + expect(await configuratorAsProxy.marketAdminPaused()).to.be.true; + + const txnOfUnpause = await wait( + configuratorAsProxy.connect(governorTimelockSigner).unpauseMarketAdmin() + ); + + expect(event(txnOfUnpause, 0)).to.be.deep.equal({ + MarketAdminPaused: { + isMarketAdminPaused: false, + }, + }); + expect(await configuratorAsProxy.marketAdminPaused()).to.be.false; + }); + + it('marketAdminPauseGuardian can pause market admin', async () => { + const { + governorTimelockSigner, + marketUpdateMultiSig, + marketUpdateProposer, + marketUpdateTimelock, + } = await makeMarketAdmin(); + + const { + configurator, + configuratorProxy, + cometProxy, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + expect(await configuratorAsProxy.marketAdminPaused()).to.be.false; + + await configuratorAsProxy + .connect(governorTimelockSigner) + .setMarketAdminPauseGuardian(alice.address); + + expect(await configuratorAsProxy.marketAdminPauseGuardian()).to.be.equal( + alice.address + ); + + const txn = await wait( + configuratorAsProxy.connect(alice).pauseMarketAdmin() + ); + + expect(event(txn, 0)).to.be.deep.equal({ + MarketAdminPaused: { + isMarketAdminPaused: true, + }, + }); + expect(await configuratorAsProxy.marketAdminPaused()).to.be.true; + + await configuratorAsProxy + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address); + + expect(await configuratorAsProxy.marketAdmin()).to.be.equal( + marketUpdateTimelock.address + ); + + const proposalId = 1n; + + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + ], + 'Setting supply kink to 100' + ); + + await expect( + marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId) + ).to.be.rejectedWith( + 'MarketUpdateTimelock::executeTransaction: Transaction execution reverted.' + ); + }); + it('marketAdminPauseGuardian cannot unpause market admin', async () => { + const { governorTimelockSigner } = await makeMarketAdmin(); + + const { + configurator, + configuratorProxy, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + expect(await configuratorAsProxy.marketAdminPaused()).to.be.false; + + await configuratorAsProxy + .connect(governorTimelockSigner) + .setMarketAdminPauseGuardian(alice.address); + + expect(await configuratorAsProxy.marketAdminPauseGuardian()).to.be.equal( + alice.address + ); + + await expect( + configuratorAsProxy.connect(alice).unpauseMarketAdmin() + ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); + }); + + it('only main-governor-timelock or market admin can call market update functions', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + configurator, + configuratorProxy, + cometProxy, + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + const oldSupplyKink = ( + await configuratorAsProxy.getConfiguration(cometProxy.address) + ).supplyKink; + const newSupplyKink = 100n; + + const txnOfGovernorTimelock = await wait( + configuratorAsProxy + .connect(governorTimelockSigner) + .setSupplyKink(cometProxy.address, newSupplyKink) + ); + + expect(event(txnOfGovernorTimelock, 0)).to.be.deep.equal({ + SetSupplyKink: { + cometProxy: cometProxy.address, + oldKink: oldSupplyKink, + newKink: newSupplyKink, + }, + }); + expect( + (await configuratorAsProxy.getConfiguration(cometProxy.address)) + .supplyKink + ).to.be.equal(newSupplyKink); + + await configuratorAsProxy + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address); + + expect(await configuratorAsProxy.marketAdmin()).to.be.equal( + marketUpdateTimelock.address + ); + + const oldBorrowKink = ( + await configuratorAsProxy.getConfiguration(cometProxy.address) + ).borrowKink; + + const newBorrowKink = 100n; + + const txnOfMarketAdmin = await wait( + configuratorAsProxy + .connect(marketUpdateTimelockSigner) + .setBorrowKink(cometProxy.address, newBorrowKink) + ); + + expect(event(txnOfMarketAdmin, 0)).to.be.deep.equal({ + SetBorrowKink: { + cometProxy: cometProxy.address, + oldKink: oldBorrowKink, + newKink: newBorrowKink, + }, + }); + expect( + (await configuratorAsProxy.getConfiguration(cometProxy.address)) + .borrowKink + ).to.be.equal(newBorrowKink); + }); + + it('market admin cannot call NON market update functions', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + configurator, + configuratorProxy, + cometProxy, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + await configuratorAsProxy + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address); + + await expect( + configuratorAsProxy + .connect(marketUpdateTimelockSigner) + .setPauseGuardian(cometProxy.address, alice.address) + ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); + }); + + it('market admin cannot call market update functions when marketAdminPaused', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + configurator, + configuratorProxy, + cometProxy, + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + await configuratorAsProxy + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address); + + expect(await configuratorAsProxy.marketAdmin()).to.be.equal( + marketUpdateTimelock.address + ); + + await configuratorAsProxy + .connect(governorTimelockSigner) + .pauseMarketAdmin(); + expect(await configuratorAsProxy.marketAdminPaused()).to.be.true; + + const newBorrowKink = 100n; + await expect( + configuratorAsProxy + .connect(marketUpdateTimelockSigner) + .setBorrowKink(cometProxy.address, newBorrowKink) + ).to.be.revertedWith('Market admin is paused'); + }); + + it('main-governor-timelock can call market update functions when marketAdminPause', async () => { + const { governorTimelockSigner } = await makeMarketAdmin(); + + const { + configurator, + configuratorProxy, + cometProxy, + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + await configuratorAsProxy + .connect(governorTimelockSigner) + .pauseMarketAdmin(); + expect(await configuratorAsProxy.marketAdminPaused()).to.be.true; + + const oldSupplyKink = ( + await configuratorAsProxy.getConfiguration(cometProxy.address) + ).supplyKink; + const newSupplyKink = 100n; + + const txnOfGovernorTimelock = await wait( + configuratorAsProxy + .connect(governorTimelockSigner) + .setSupplyKink(cometProxy.address, newSupplyKink) + ); + + expect(event(txnOfGovernorTimelock, 0)).to.be.deep.equal({ + SetSupplyKink: { + cometProxy: cometProxy.address, + oldKink: oldSupplyKink, + newKink: newSupplyKink, + }, + }); + expect( + (await configuratorAsProxy.getConfiguration(cometProxy.address)) + .supplyKink + ).to.be.equal(newSupplyKink); + }); + + it('governor cannot be updated by market admin', async () => { + const { + governorTimelockSigner, + marketUpdateTimelock, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + configurator, + configuratorProxy, + cometProxy, + users: [alice], + } = await makeConfigurator({ + governor: governorTimelockSigner, + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + await configuratorAsProxy + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelock.address); + + await expect( + configuratorAsProxy + .connect(marketUpdateTimelockSigner) + .setGovernor(cometProxy.address, alice.address) + ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); + }); +}); diff --git a/test/marketupdates/market-update-deployment-test.ts b/test/marketupdates/market-update-deployment-test.ts new file mode 100644 index 00000000..111c34cb --- /dev/null +++ b/test/marketupdates/market-update-deployment-test.ts @@ -0,0 +1,377 @@ +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; +import { event, expect, wait } from './../helpers'; +import { initializeAndFundGovernorTimelock } from './market-updates-helper'; +import { + CometFactory__factory, + CometProxyAdmin__factory, + CometProxyAdminOld__factory, + Configurator__factory, + ConfiguratorOld__factory, + ConfiguratorProxy__factory, + SimpleTimelock, + TransparentUpgradeableProxy__factory, +} from './../../build/types'; +import { makeProtocol, getConfigurationForConfigurator } from './../helpers'; +import { ethers } from 'hardhat'; + +describe('MarketUpdateDeployment', function() { + /* + + Mainner Timelock - https://etherscan.io/address/0x6d903f6003cca6255D85CcA4D3B5E5146dC33925 + + Existing Setup Steps: + 1) Deploy CometProxyAdmin with Governor Timelock. The owner of the CometProxyAdmin should be the Governor Timelock + See the owner here on mainnet -https://etherscan.io/address/0x1ec63b5883c3481134fd50d5daebc83ecd2e8779#readContract + The owner should be the Governor Timelock + 2) Deploy the Configurator with Admin as CometProxyAdmin + See the admin of the Proxy contact https://etherscan.io/address/0x316f9708bb98af7da9c68c1c3b5e79039cd336e3 + The admin should be the CometProxyAdmin + 3) Deploy the Comet's Proxy with Admin as CometProxyAdmin + See the admin of the Proxy contact https://etherscan.io/address/0x3Afdc9BCA9213A35503b077a6072F3D0d5AB0840 + The admin should be the CometProxyAdmin + + New Setup Steps: + ------- Deploy New Contracts ----------- + 1) Deploy the address of MarketAdminMultiSig + + 2) Deploy MarketUpdateProposer with MarketAdminMultiSig as the owner + + 3) Deploy MarketUpdateTimelock with Governor Timelock as the owner + + 4) Initialize the MarketUpdateProposer with MarketUpdateTimelock + + 5) Deploy the new CometProxyAdmin + + 6) Set MainGovernorTimelock as the owner of new CometProxyAdmin by calling transferOwnership + + 7) Deploy the new Configurator's Implementation + + 8) Initialize the new Configurator with Governor Timelock + + ------- Update Existing Contracts ----------- + + All actions to be done by timelock proposals + -- Update Admins --- + 1) Call Old CometProxyAdmin via timelock and call `changeProxyAdmin` function to set Comet Proxy's admin as the new CometProxyAdmin // This will allow the new CometProxyAdmin to upgrade the Comet's implementation + + 2) Call Old CometProxyAdmin and call `changeProxyAdmin` function to set Configurator's Proxy's admin as the new CometProxyAdmin // This will allow the new CometProxyAdmin to upgrade the Configurator's implementation if needed in future + + -- Set new configurator as implementation --- + + 3) Set marketUpdateAdmin on Configurator + + 4) Set marketUpdateAdmin on CometProxyAdmin + + 5) Set marketAdminPauseGuardian on Configurator + + 6) Set marketAdminPauseGuardian on CometProxyAdmin + + 7) Deploy market update // This will make sure existing functionality is working fine + - setSupplyCap + - deployAndUpgrade + */ + + /* + Market Updates + + 1) propose a new market update on MarketUpdateProposer using MarketAdminMultiSig + + 2) Call the execute function on MarketUpdateProposer to execute the proposal + */ + + it('should be able to deploy MarketUpdates in the proper sequence', async () => { + const { + governorTimelockSigner: governorTimelockSigner, + governorTimelock: governorTimelock, + originalSigner, + } = await initializeAndFundGovernorTimelock(); + + const { + configuratorProxyContract, + configuratorBehindProxy, + cometBehindProxy, + oldCometProxyAdmin, + proxyOfComet, + comet, + } = await deployExistingContracts({ + governorTimelock, + governorTimelockSigner, + originalSigner, + }); + + const cometAsProxy = comet.attach(cometBehindProxy.address); + + expect(await configuratorBehindProxy.governor()).to.be.equal( + governorTimelock.address + ); + // ------- Deploy New Contracts ----------- + + const signers = await ethers.getSigners(); + + // 1) Deploy the address of MarketAdminMultiSig + const marketUpdateMultiSig = signers[3]; + + const marketUpdaterProposerFactory = await ethers.getContractFactory( + 'MarketUpdateProposer' + ); + + // Fund the impersonated account + await signers[0].sendTransaction({ + to: marketUpdateMultiSig.address, + value: ethers.utils.parseEther('1.0'), // Sending 1 Ether to cover gas fees + }); + + // 2) Deploy MarketUpdateProposer with MarketAdminMultiSig as the owner + const marketUpdateProposer = await marketUpdaterProposerFactory + .connect(marketUpdateMultiSig) + .deploy(); + + expect(await marketUpdateProposer.owner()).to.be.equal( + marketUpdateMultiSig.address + ); + + const marketAdminTimelockFactory = await ethers.getContractFactory( + 'MarketUpdateTimelock' + ); + + // 3) Deploy MarketUpdateTimelock with Governor Timelock as the owner + const marketUpdateTimelock = await marketAdminTimelockFactory.deploy( + governorTimelock.address, + 0 + ); + + // Fund the impersonated account + await signers[0].sendTransaction({ + to: marketUpdateTimelock.address, + value: ethers.utils.parseEther('1.0'), // Sending 1 Ether to cover gas fees + }); + + // 4) Initialize the MarketUpdateProposer with MarketUpdateTimelock + marketUpdateProposer + .connect(marketUpdateMultiSig) + .initialize(marketUpdateTimelock.address); + + + const ProxyAdmin = (await ethers.getContractFactory('CometProxyAdmin')) as CometProxyAdmin__factory; + const proxyAdminNew = await ProxyAdmin.connect(marketUpdateMultiSig).deploy(); + + // 6) Set MainGovernorTimelock as the owner of new CometProxyAdmin by calling transferOwnership + await proxyAdminNew.connect(marketUpdateMultiSig).transferOwnership(governorTimelock.address); + + // 7) Deploy the new Configurator's Implementation + const ConfiguratorFactory = (await ethers.getContractFactory('Configurator')) as Configurator__factory; + const configuratorNew = await ConfiguratorFactory.connect(marketUpdateMultiSig).deploy(); + await configuratorNew.deployed(); + + // ------- Update Existing Contracts ----------- + console.log('Updating the existing contracts'); + + // Call Old CometProxyAdmin via timelock and call `changeProxyAdmin` function to set Comet Proxy's admin as the new CometProxyAdmin // This will allow the new CometProxyAdmin to upgrade the Comet's implementation + await governorTimelock.executeTransactions( + [oldCometProxyAdmin.address], + [0], + ['changeProxyAdmin(address,address)'], + [ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [proxyOfComet.address, proxyAdminNew.address] + )] + ); + + // Call Old CometProxyAdmin and call `changeProxyAdmin` function to set Configurator's Proxy's admin as the new CometProxyAdmin // This will allow the new CometProxyAdmin to upgrade the Configurator's implementation if needed in future + await governorTimelock.executeTransactions( + [oldCometProxyAdmin.address], + [0], + ['changeProxyAdmin(address,address)'], + [ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, proxyAdminNew.address] + )] + ); + + // + + await governorTimelock.executeTransactions( + [proxyAdminNew.address], + [0], + ['upgrade(address,address)'], + [ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, configuratorNew.address] + )] + ); + + // Setting Market Update Admin in Configurator + await governorTimelock.executeTransactions( + [configuratorProxyContract.address], + [0], + ['setMarketAdmin(address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketUpdateTimelock.address] + ), + ] + ); + + // Setting Market Update Admin in CometProxyAdmin + await governorTimelock.executeTransactions( + [proxyAdminNew.address], + [0], + ['setMarketAdmin(address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketUpdateTimelock.address] + ), + ] + ); + + // Setting Market Update proposer in MarketUpdateTimelock + await governorTimelock.executeTransactions( + [marketUpdateTimelock.address], + [0], + ['setMarketUpdateProposer(address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketUpdateProposer.address] + ), + ] + ); + + // Governor Timelock: Setting new supplyKink in Configurator and deploying Comet + const newSupplyKinkByGovernorTimelock = 300n; + const oldSupplyKink = await cometAsProxy.supplyKink(); + expect(oldSupplyKink).to.be.equal(800000000000000000n); + await governorTimelock.executeTransactions( + [configuratorProxyContract.address, proxyAdminNew.address], + [0, 0], + ['setSupplyKink(address,uint64)', 'deployAndUpgradeTo(address,address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometBehindProxy.address, newSupplyKinkByGovernorTimelock] + ), + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, cometBehindProxy.address] + ), + ] + ); + + const newSupplyKink = await cometAsProxy.supplyKink(); + expect(newSupplyKink).to.be.equal(newSupplyKinkByGovernorTimelock); + + // MarketAdmin: Setting new supplyKink in Configurator and deploying Comet + const newConfiguratorViaProxy = configuratorNew.attach( + configuratorProxyContract.address + ); + const supplyKinkOld = ( + await newConfiguratorViaProxy.getConfiguration(cometBehindProxy.address) + ).supplyKink; + expect(supplyKinkOld).to.be.equal(300n); + + const newSupplyKinkByMarketAdmin = 100n; + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxyContract.address, proxyAdminNew.address], + [0, 0], + [ + 'setSupplyKink(address,uint64)', + 'deployAndUpgradeTo(address,address)', + ], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometBehindProxy.address, newSupplyKinkByMarketAdmin] + ), + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, cometBehindProxy.address] + ), + ], + 'Test market update' + ); + + await marketUpdateProposer.connect(marketUpdateMultiSig).execute(1); + + expect( + (await newConfiguratorViaProxy.getConfiguration(cometBehindProxy.address)) + .supplyKink + ).to.be.equal(newSupplyKinkByMarketAdmin); + }); + + async function deployExistingContracts(input: { + governorTimelock: SimpleTimelock; + governorTimelockSigner: SignerWithAddress; + originalSigner: SignerWithAddress; + }) { + const { governorTimelock, governorTimelockSigner } = input; + const opts: any = {}; + + const { + governor, + pauseGuardian, + extensionDelegate, + base, + comet, + tokens, + priceFeeds, + } = await makeProtocol({ + governor: governorTimelockSigner, + }); + + const configuration = await getConfigurationForConfigurator( + opts, + comet, + governor, + pauseGuardian, + extensionDelegate, + tokens, + base, + priceFeeds + ); + + // Deploy ProxyAdmin + const ProxyAdmin = (await ethers.getContractFactory('CometProxyAdminOld')) as CometProxyAdminOld__factory; + const proxyAdmin = await ProxyAdmin.connect(governorTimelockSigner).deploy(); + + // Deploy Comet proxy + const CometProxy = (await ethers.getContractFactory('TransparentUpgradeableProxy')) as TransparentUpgradeableProxy__factory; + const cometBehindProxy = await CometProxy.connect(governorTimelockSigner).deploy(comet.address, proxyAdmin.address, (await comet.populateTransaction.initializeStorage()).data); + await cometBehindProxy.deployed(); + + // Derive the rest of the Configurator configuration values + + // Deploy CometFactory + const CometFactoryFactory = (await ethers.getContractFactory('CometFactory')) as CometFactory__factory; + const cometFactory = await CometFactoryFactory.deploy(); + await cometFactory.deployed(); + + // Deploy Configurator + const ConfiguratorFactory = (await ethers.getContractFactory('ConfiguratorOld')) as ConfiguratorOld__factory; + const configurator = await ConfiguratorFactory.deploy(); + await configurator.deployed(); + + // Deploy Configurator proxy + const initializeCalldata = (await configurator.populateTransaction.initialize(governor.address)).data; + const ConfiguratorProxyContract = (await ethers.getContractFactory('ConfiguratorProxy')) as ConfiguratorProxy__factory; + const configuratorProxyContract = await ConfiguratorProxyContract.deploy(configurator.address, proxyAdmin.address, initializeCalldata); + await configuratorProxyContract.deployed(); + + // Set the initial factory and configuration for Comet in Configurator + const configuratorBehindProxy = configurator.attach(configuratorProxyContract.address); + await configuratorBehindProxy.connect(governorTimelockSigner).setConfiguration(cometBehindProxy.address, configuration); + await configuratorBehindProxy.connect(governorTimelockSigner).setFactory(cometBehindProxy.address, cometFactory.address); + + return { + configuratorProxyContract, + configuratorBehindProxy, + cometBehindProxy, + proxyOfComet: cometBehindProxy, + oldCometProxyAdmin: proxyAdmin, + comet, + }; + } +}); diff --git a/test/marketupdates/market-update-proposer-test.ts b/test/marketupdates/market-update-proposer-test.ts new file mode 100644 index 00000000..1123eae0 --- /dev/null +++ b/test/marketupdates/market-update-proposer-test.ts @@ -0,0 +1,247 @@ +import { makeMarketAdmin } from './market-updates-helper'; +import { expect, makeConfigurator, ethers, wait, event } from '../helpers'; + +describe('MarketUpdateProposer', function() { + // We are not checking market updates here. we are just checking interaction + // between MarketUpdateMultisig and MarketUpdateProposer or checking interactions + // on MarketUpdateProposer + it('is initialized properly with timelock', async () => { + const { + marketUpdateProposer, + marketUpdateTimelock, + } = await makeMarketAdmin(); + + expect(await marketUpdateProposer.timelock()).to.equal( + marketUpdateTimelock.address + ); + }); + + it('throw error if MarketUpdateProposer is initialized twice', async () => { + const { + marketUpdateProposer, + marketUpdateTimelock, + } = await makeMarketAdmin(); + + await expect( + marketUpdateProposer.initialize(marketUpdateTimelock.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'AlreadyInitialized'); + }); + + it('MarketUpdateMultisig is set as the owner of MarketUpdateProposer', async () => { + const { + marketUpdateProposer, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + expect(await marketUpdateProposer.owner()).to.equal( + marketUpdateMultiSig.address + ); + }); + + it('MarketUpdateMultisig can set a new owner for MarketUpdateProposer', async () => { + const { + marketUpdateProposer, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { + users: [alice], + } = await makeConfigurator(); + + expect(await marketUpdateProposer.owner()).to.equal( + marketUpdateMultiSig.address + ); + + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .transferOwnership(alice.address); + + expect(await marketUpdateProposer.owner()).to.equal(alice.address); + }); + + it('only allows MarketUpdateMultisig to create proposal', async () => { + const { + marketUpdateProposer, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { + configuratorProxy, + cometProxy, + users: [alice], + } = await makeConfigurator(); + + let setSupplyKinkCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ); + + const proposalId = 1n; + const proposalDescription = 'Test Proposal'; + + // Creates a proposal successfully as the signer is the multisig + const txn = await wait( + marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + 'Test Proposal' + ) + ); + + // Checks the emitter event properly + expect(event(txn, 0)).to.be.deep.equal({ + MarketUpdateProposalCreated: { + id: proposalId, + proposer: marketUpdateMultiSig.address, + targets: [configuratorProxy.address], + signatures: ['setSupplyKink(address,uint64)'], + calldatas: [setSupplyKinkCalldata], + description: proposalDescription, + }, + }); + + // this will fail because the signer is not the multisig + await expect( + marketUpdateProposer + .connect(alice) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + proposalDescription + ) + ).to.be.revertedWith('Ownable: caller is not the owner'); + }); + + it('keeps track of all the proposals', async () => { + const { + marketUpdateProposer, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { configuratorProxy, cometProxy } = await makeConfigurator(); + + let setSupplyKinkCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ); + + const proposalId = 1n; + const proposalDescription = 'Test Proposal'; + + // Creates a proposal successfully as the signer is the multisig + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + proposalDescription + ); + + // Checks the proposal + const proposal = await marketUpdateProposer.getProposal(proposalId); + + expect(proposal.id).to.equal(proposalId); + expect(proposal.proposer).to.equal(marketUpdateMultiSig.address); + expect(proposal.targets[0]).to.equal(configuratorProxy.address); + expect(proposal.signatures[0]).to.equal('setSupplyKink(address,uint64)'); + expect(proposal.calldatas[0]).to.equal(setSupplyKinkCalldata); + expect(proposal.description).to.equal(proposalDescription); + }); + + it('can cancel the proposal', async () => { + // Create a proposal + // Cancel the proposal + // Check if the proposal is cancelled + const { + marketUpdateProposer, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { configuratorProxy, cometProxy } = await makeConfigurator(); + + let setSupplyKinkCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ); + + const proposalId = 1n; + const proposalDescription = 'Test Proposal'; + + // Creates a proposal successfully as the signer is the multisig + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + proposalDescription + ); + + expect( + (await marketUpdateProposer.proposals(proposalId)).canceled + ).to.be.equal(false); + + // Cancel the proposal + await marketUpdateProposer.connect(marketUpdateMultiSig).cancel(proposalId); + + expect( + (await marketUpdateProposer.proposals(proposalId)).canceled + ).to.be.equal(true); + + await expect( + marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId) + ).to.be.revertedWith( + 'MarketUpdateProposer::execute: proposal can only be executed if it is queued' + ); + }); + + it('marks the proposal as expired after grace period', async () => { + const { + marketUpdateProposer, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { configuratorProxy, cometProxy } = await makeConfigurator(); + + let setSupplyKinkCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ); + + const proposalId = 1n; + const proposalDescription = 'Test Proposal'; + + // Creates a proposal successfully as the signer is the multisig + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + proposalDescription + ); + + // Fast forward time by more than the GRACE_PERIOD + const GRACE_PERIOD = 14 * 24 * 60 * 60; // 14 days in seconds + await ethers.provider.send('evm_increaseTime', [GRACE_PERIOD + 1]); // Increase by 14 days + 1 second + await ethers.provider.send('evm_mine', []); // Mine the next block to apply the time increase + + expect(await marketUpdateProposer.state(proposalId)).to.equal(3); // Proposal should be expired + + await expect( + marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId) + ).to.be.revertedWith( + 'MarketUpdateProposer::execute: proposal can only be executed if it is queued' + ); + }); +}); diff --git a/test/marketupdates/market-update-timelock-test.ts b/test/marketupdates/market-update-timelock-test.ts new file mode 100644 index 00000000..73f1bc03 --- /dev/null +++ b/test/marketupdates/market-update-timelock-test.ts @@ -0,0 +1,414 @@ +import { makeMarketAdmin } from './market-updates-helper'; +import { expect, makeConfigurator, ethers } from '../helpers'; + +describe('MarketUpdateTimelock', function() { + it('is created properly with main-governor-timelock as admin', async () => { + const { marketUpdateTimelock, governorTimelock } = await makeMarketAdmin(); + + expect(await marketUpdateTimelock.admin()).to.equal( + governorTimelock.address + ); + }); + + it('only allows main-governor-timelock to set MarketUpdateProposer', async () => { + const { + marketUpdateTimelock, + governorTimelockSigner, + } = await makeMarketAdmin(); + + const { + users: [alice, bob], + } = await makeConfigurator(); + + await marketUpdateTimelock + .connect(governorTimelockSigner) + .setMarketUpdateProposer(alice.address); + + expect(await marketUpdateTimelock.marketUpdateProposer()).to.equal( + alice.address + ); + + await expect( + marketUpdateTimelock.connect(bob).setMarketUpdateProposer(bob.address) + ).to.be.revertedWith( + 'MarketUpdateTimelock::setMarketUpdateProposer: Call must come from admin.' + ); + }); + + it('only MarketUpdateProposer or main-governor-timelock can queue transactions', async () => { + const { + marketUpdateTimelock, + governorTimelockSigner, + marketUpdateProposer, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { + configuratorProxy, + cometProxy, + users: [bob], + } = await makeConfigurator(); + + const latestBlock = await ethers.provider.getBlock('latest'); + const currentTimestamp = latestBlock.timestamp; + + const eta = currentTimestamp + 5; // Ensure eta is in the future + + // ensuring that main gover-timelock can queue transactions + await marketUpdateTimelock + .connect(governorTimelockSigner) + .queueTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address, uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + eta + ); + + // ensuring that market update proposer can queue transactions + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address, uint64)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + ], + 'Setting supply kink to 100' + ); + + // ensuring that none other than the main-governor-timelock or MarketUpdateProposer can queue transactions + await expect( + marketUpdateTimelock + .connect(bob) + .queueTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address, uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + eta + ) + ).to.be.revertedWith( + 'MarketUpdateTimelock::Unauthorized: call must come from admin or marketAdmin' + ); + }); + + it('only MarketUpdateProposer or main-governor-timelock can execute transactions', async () => { + const { + marketUpdateTimelock, + governorTimelockSigner, + marketUpdateProposer, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { + configuratorProxy, + configurator, + cometProxy, + users: [bob], + } = await makeConfigurator(); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + configuratorAsProxy.transferGovernor(marketUpdateTimelock.address); + const proposalId = 1n; + + let latestBlock = await ethers.provider.getBlock('latest'); + let currentTimestamp = latestBlock.timestamp; + + let eta = currentTimestamp + 5; // Ensure eta is in the future + + // ensuring that main gover-timelock can execute transactions + await marketUpdateTimelock + .connect(governorTimelockSigner) + .queueTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address,uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100000] + ), + eta + ); + + // Fast-forward time by 5 seconds to surpass the eta + await ethers.provider.send('evm_increaseTime', [5]); + await ethers.provider.send('evm_mine', []); // Mine a new block to apply the time increase + + await marketUpdateTimelock + .connect(governorTimelockSigner) + .executeTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address,uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100000] + ), + eta + ); + + // ensuring that market update proposer can queue transactions + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + ], + 'Setting supply kink to 100' + ); + + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .execute(proposalId); + + // ensuring that none other than the main-governor-timelock or MarketUpdateProposer can execute transactions + + // first queuing a transaction + latestBlock = await ethers.provider.getBlock('latest'); + currentTimestamp = latestBlock.timestamp; + + eta = currentTimestamp + 5; // Ensure eta is in the future + + // ensuring that MarketUpdateProposer can execute transactions + await marketUpdateTimelock + .connect(governorTimelockSigner) + .queueTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address,uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100000] + ), + eta + ); + + // Fast-forward time by 5 seconds to surpass the eta + await ethers.provider.send('evm_increaseTime', [5]); + await ethers.provider.send('evm_mine', []); // Mine a new block to apply the time increase + + await expect( + marketUpdateTimelock + .connect(bob) + .executeTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address,uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100000] + ), + eta + ) + ).to.be.revertedWith( + 'MarketUpdateTimelock::Unauthorized: call must come from admin or marketAdmin' + ); + }); + + it('only MarketUpdateProposer or main-governor-timelock can cancel transactions', async () => { + const { + marketUpdateTimelock, + governorTimelockSigner, + marketUpdateProposer, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { + configuratorProxy, + configurator, + cometProxy, + users: [bob], + } = await makeConfigurator(); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + await configuratorAsProxy.transferGovernor(marketUpdateTimelock.address); + + const proposalId = 1n; + + let latestBlock = await ethers.provider.getBlock('latest'); + let currentTimestamp = latestBlock.timestamp; + + let eta = currentTimestamp + 5; // Ensure eta is in the future + + // ensuring that main gover-timelock can cancel transactions + await marketUpdateTimelock + .connect(governorTimelockSigner) + .queueTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address,uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100000] + ), + eta + ); + + await marketUpdateTimelock + .connect(governorTimelockSigner) + .cancelTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address,uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100000] + ), + eta + ); + + // ensuring that MarketUpdateProposer can cacnel transactions + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + ], + 'Setting supply kink to 100' + ); + + await marketUpdateProposer.connect(marketUpdateMultiSig).cancel(proposalId); + + // Checking the state of the transaction using the txHash + const txHash = ethers.utils.keccak256( + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint', 'string', 'bytes', 'uint'], + [ + configuratorProxy.address, + 0, + 'setSupplyKink(address,uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100000] + ), + eta, + ] + ) + ); + + expect(await marketUpdateTimelock.queuedTransactions(txHash)).to.equal( + false + ); + + // ensuring that none other than the main-governor-timelock or MarketUpdateProposer can execute transactions + + // first queuing a transaction + latestBlock = await ethers.provider.getBlock('latest'); + currentTimestamp = latestBlock.timestamp; + + eta = currentTimestamp + 5; // Ensure eta is in the future + + // ensuring that MarketUpdateProposer can execute transactions + await marketUpdateTimelock + .connect(governorTimelockSigner) + .queueTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address,uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100000] + ), + eta + ); + + await expect( + marketUpdateTimelock + .connect(bob) + .cancelTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address,uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100000] + ), + eta + ) + ).to.be.revertedWith( + 'MarketUpdateTimelock::Unauthorized: call must come from admin or marketAdmin' + ); + }); + + it('only main-governor-timelock can set new admin', async () => { + const { + marketUpdateTimelock, + governorTimelockSigner, + } = await makeMarketAdmin(); + + const { + users: [alice, bob], + } = await makeConfigurator(); + + await marketUpdateTimelock + .connect(governorTimelockSigner) + .setAdmin(alice.address); + + expect(await marketUpdateTimelock.admin()).to.equal(alice.address); + + await expect( + marketUpdateTimelock.connect(bob).setAdmin(bob.address) + ).to.be.revertedWith( + 'MarketUpdateTimelock::setAdmin: Call must come from admin.' + ); + }); + + it('MarketUpdateProposer cannot set or update MarketUpdateProposer', async () => { + const { + marketUpdateTimelock, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { + users: [bob], + } = await makeConfigurator(); + + await expect( + marketUpdateTimelock + .connect(marketUpdateMultiSig) + .setMarketUpdateProposer(bob.address) + ).to.be.revertedWith( + 'MarketUpdateTimelock::setMarketUpdateProposer: Call must come from admin.' + ); + }); + + it('MarketUpdateProposer cannot set or update main-governor-timelock', async () => { + const { + marketUpdateTimelock, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { + users: [bob], + } = await makeConfigurator(); + + await expect( + marketUpdateTimelock.connect(marketUpdateMultiSig).setAdmin(bob.address) + ).to.be.revertedWith( + 'MarketUpdateTimelock::setAdmin: Call must come from admin.' + ); + }); +}); diff --git a/test/marketupdates/market-updates-helper.ts b/test/marketupdates/market-updates-helper.ts new file mode 100644 index 00000000..1fef50a3 --- /dev/null +++ b/test/marketupdates/market-updates-helper.ts @@ -0,0 +1,107 @@ +import { + SimpleTimelock__factory, + MarketUpdateTimelock__factory, + MarketUpdateProposer__factory, +} from './../../build/types'; +import hre from 'hardhat'; +import { ethers, expect } from './../helpers'; + +export async function makeMarketAdmin() { + const { + governorTimelockSigner: governorTimelockSigner, + governorTimelock: governorTimelock, + } = await initializeAndFundGovernorTimelock(); + + const signers = await ethers.getSigners(); + + const marketUpdateMultiSig = signers[3]; + + const marketUpdaterProposerFactory = (await ethers.getContractFactory( + 'MarketUpdateProposer' + )) as MarketUpdateProposer__factory; + + // Fund the impersonated account + await signers[0].sendTransaction({ + to: marketUpdateMultiSig.address, + value: ethers.utils.parseEther('1.0'), // Sending 1 Ether to cover gas fees + }); + + // This sets the owner of the MarketUpdateProposer to the marketUpdateMultiSig + const marketUpdateProposer = await marketUpdaterProposerFactory + .connect(marketUpdateMultiSig) + .deploy(); + + expect(await marketUpdateProposer.owner()).to.be.equal( + marketUpdateMultiSig.address + ); + + const marketAdminTimelockFactory = (await ethers.getContractFactory( + 'MarketUpdateTimelock' + )) as MarketUpdateTimelock__factory; + + const marketUpdateTimelock = await marketAdminTimelockFactory.deploy( + governorTimelock.address, + 0 + ); + const marketUpdateTimelockAddress = await marketUpdateTimelock.deployed(); + + // Impersonate the account + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [marketUpdateTimelockAddress.address], + }); + + // Fund the impersonated account + await signers[0].sendTransaction({ + to: marketUpdateTimelock.address, + value: ethers.utils.parseEther('1.0'), // Sending 1 Ether to cover gas fees + }); + + // Get the signer from the impersonated account + const marketUpdateTimelockSigner = await ethers.getSigner( + marketUpdateTimelockAddress.address + ); + + marketUpdateProposer + .connect(marketUpdateMultiSig) + .initialize(marketUpdateTimelock.address); + + await marketUpdateTimelock + .connect(governorTimelockSigner) + .setMarketUpdateProposer(marketUpdateProposer.address); + + return { + governorTimelockSigner, + governorTimelock, + marketUpdateMultiSig, + marketUpdateTimelock, + marketUpdateTimelockSigner, + marketUpdateProposer, + }; +} + +export async function initializeAndFundGovernorTimelock() { + const signers = await ethers.getSigners(); + const gov = signers[0]; + const TimelockFactory = (await ethers.getContractFactory( + 'SimpleTimelock' + )) as SimpleTimelock__factory; + const governorTimelock = await TimelockFactory.deploy(gov.address); + await governorTimelock.deployed(); + + // Impersonate the account + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [governorTimelock.address], + }); + + // Fund the impersonated account + await gov.sendTransaction({ + to: governorTimelock.address, + value: ethers.utils.parseEther('100.0'), // Sending 1 Ether to cover gas fees + }); + + // Get the signer from the impersonated account + const governorTimelockSigner = await ethers.getSigner(governorTimelock.address); + return { originalSigner: gov, governorTimelockSigner, governorTimelock }; +} From 1b6ad0dfcf58bc394f463a9626a7ec36462460ad Mon Sep 17 00:00:00 2001 From: robin Date: Fri, 6 Sep 2024 19:16:46 -0400 Subject: [PATCH 03/28] Cleanups --- contracts/CometProxyAdmin.sol | 4 +- contracts/ConfiguratorStorage.sol | 1 - .../marketupdates/MarketUpdateTimelock.sol | 9 +- contracts/marketupdates/SafeMath.sol | 191 ------------- deployments/localhost/dai/deploy.ts | 259 +++++++++++------- .../market-update-deployment-test.ts | 13 +- .../market-update-proposer-test.ts | 17 +- .../market-update-timelock-test.ts | 41 ++- test/marketupdates/market-updates-helper.ts | 7 +- 9 files changed, 217 insertions(+), 325 deletions(-) delete mode 100644 contracts/marketupdates/SafeMath.sol diff --git a/contracts/CometProxyAdmin.sol b/contracts/CometProxyAdmin.sol index bdd6f22e..3bf5bf3e 100644 --- a/contracts/CometProxyAdmin.sol +++ b/contracts/CometProxyAdmin.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.15; import "./vendor/proxy/transparent/ProxyAdmin.sol"; interface Deployable { - function deploy(address cometProxy) external returns (address); + function deploy(address cometProxy) external returns (address); } contract CometProxyAdmin is ProxyAdmin { @@ -118,7 +118,7 @@ contract CometProxyAdmin is ProxyAdmin { } /** - * @dev Custom upgrade function that allows owner and marketUpdateAdmin to call it + * @dev Custom upgrade function that allows owner and marketUpdateAdmin to call it */ function _upgrade(TransparentUpgradeableProxy proxy, address implementation) private ownerOrMarketAdmin { proxy.upgradeTo(implementation); diff --git a/contracts/ConfiguratorStorage.sol b/contracts/ConfiguratorStorage.sol index 785202ef..82000fce 100644 --- a/contracts/ConfiguratorStorage.sol +++ b/contracts/ConfiguratorStorage.sol @@ -33,5 +33,4 @@ contract ConfiguratorStorage is CometConfiguration { /// @notice address of the market admin pause guardian. We don't use `pauseGuardian` role because we have `setPauseGuardian` already which sets the pauseGuardian on comet. address public marketAdminPauseGuardian; - } diff --git a/contracts/marketupdates/MarketUpdateTimelock.sol b/contracts/marketupdates/MarketUpdateTimelock.sol index e9bdcc22..ecbb5bea 100644 --- a/contracts/marketupdates/MarketUpdateTimelock.sol +++ b/contracts/marketupdates/MarketUpdateTimelock.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: BSD-3-Clause pragma solidity ^0.8.10; -import "./SafeMath.sol"; - /* Right now admin and marketUpdateProposer can cancel one another's transactions, but @@ -10,7 +8,6 @@ this is not a realistic scenario as admin is a main-governor-timelock which will queuing, executing, or cancelling transactions. So we are not handling or testing it. */ contract MarketUpdateTimelock { - using SafeMath for uint; event NewAdmin(address indexed oldAdmin, address indexed newAdmin); event NewMarketUpdateProposer(address indexed oldMarketAdmin, address indexed newMarketAdmin); @@ -20,7 +17,7 @@ contract MarketUpdateTimelock { event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); uint public constant GRACE_PERIOD = 14 days; - uint public constant MINIMUM_DELAY = 0 days; + uint public constant MINIMUM_DELAY = 2 days; uint public constant MAXIMUM_DELAY = 30 days; address public admin; @@ -69,7 +66,7 @@ contract MarketUpdateTimelock { } function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public adminOrMarketUpdater returns (bytes32) { - require(eta >= getBlockTimestamp().add(delay), "MarketUpdateTimelock::queueTransaction: Estimated execution block must satisfy delay."); + require(eta >= getBlockTimestamp() + delay, "MarketUpdateTimelock::queueTransaction: Estimated execution block must satisfy delay."); bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); queuedTransactions[txHash] = true; @@ -89,7 +86,7 @@ contract MarketUpdateTimelock { bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); require(queuedTransactions[txHash], "MarketUpdateTimelock::executeTransaction: Transaction hasn't been queued."); require(getBlockTimestamp() >= eta, "MarketUpdateTimelock::executeTransaction: Transaction hasn't surpassed time lock."); - require(getBlockTimestamp() <= eta.add(GRACE_PERIOD), "MarketUpdateTimelock::executeTransaction: Transaction is stale."); + require(getBlockTimestamp() <= eta + GRACE_PERIOD, "MarketUpdateTimelock::executeTransaction: Transaction is stale."); queuedTransactions[txHash] = false; diff --git a/contracts/marketupdates/SafeMath.sol b/contracts/marketupdates/SafeMath.sol deleted file mode 100644 index f9a3ca1c..00000000 --- a/contracts/marketupdates/SafeMath.sol +++ /dev/null @@ -1,191 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -pragma solidity ^0.8.10; - -// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol -// Subject to the MIT license. - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c; - unchecked { c = a + b; } - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - uint256 c; - unchecked { c = a + b; } - require(c >= a, errorMessage); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot underflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction underflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot underflow. - */ - function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c; - unchecked { c = a * b; } - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c; - unchecked { c = a * b; } - require(c / a == b, errorMessage); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. - * Reverts on division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. - * Reverts with custom message on division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} \ No newline at end of file diff --git a/deployments/localhost/dai/deploy.ts b/deployments/localhost/dai/deploy.ts index 2b47f125..42b09d3c 100644 --- a/deployments/localhost/dai/deploy.ts +++ b/deployments/localhost/dai/deploy.ts @@ -10,6 +10,7 @@ import { getConfigurationStruct } from '../../../src/deploy'; import '@nomiclabs/hardhat-ethers'; +import { ethers } from 'hardhat'; async function makeToken( deploymentManager: DeploymentManager, @@ -31,6 +32,11 @@ async function makePriceFeed( return deploymentManager.deploy(alias, 'test/SimplePriceFeed.sol', [initialPrice * 1e8, decimals]); } +async function advanceTimeAndMineBlock(delay: number) { + await ethers.provider.send('evm_increaseTime', [delay + 10]); + await ethers.provider.send('evm_mine', []); // Mine a new block to apply the time increase +} + // TODO: Support configurable assets as well? export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { const trace = deploymentManager.tracer(); @@ -48,9 +54,35 @@ export default async function deploy(deploymentManager: DeploymentManager, deplo const fauceteer = await deploymentManager.deploy('fauceteer', 'test/Fauceteer.sol', []); const timelock = await deploymentManager.deploy('timelock', 'test/SimpleTimelock.sol', [admin.address]) as SimpleTimelock; - const COMP = await deploymentManager.clone('COMP', clone.comp, [admin.address]); - + + const governorImpl = await deploymentManager.clone( + 'governor:implementation', + clone.governorBravoImpl, + [] + ); + const governorProxy = await deploymentManager.clone( + 'governor', + clone.governorBravo, + [ + timelock.address, + COMP.address, + admin.address, + governorImpl.address, + await governorImpl.MIN_VOTING_PERIOD(), + await governorImpl.MIN_VOTING_DELAY(), + await governorImpl.MIN_PROPOSAL_THRESHOLD(), + ] + ); + const governorBravo = governorImpl.attach(governorProxy.address); + await deploymentManager.idempotent( + async () => (await governorBravo.proposalCount()).eq(0), + async () => { + trace(`Initiating Governor using patched Timelock`); + trace(await wait(governorBravo.connect(admin)._initiate(timelock.address))); + } + ); + await timelock.connect(admin).setAdmin(governorBravo.address); await deploymentManager.idempotent( async () => (await COMP.balanceOf(admin.address)).gte((await COMP.totalSupply()).div(3)), @@ -65,11 +97,11 @@ export default async function deploy(deploymentManager: DeploymentManager, deplo ); await deploymentManager.idempotent( - async () => (await COMP.getCurrentVotes(voterAddress)).eq(0), + async () => (await COMP.getCurrentVotes(admin.address)).eq(0), async () => { - trace(`Delegating COMP votes to ${voterAddress}`); - trace(await wait(COMP.connect(admin).delegate(voterAddress))); - trace(`COMP.getCurrentVotes(${voterAddress}): ${await COMP.getCurrentVotes(voterAddress)}`); + trace(`Delegating COMP votes to ${admin.address}`); + trace(await wait(COMP.connect(admin).delegate(admin.address))); + trace(`COMP.getCurrentVotes(${admin.address}): ${await COMP.getCurrentVotes(admin.address)}`); } ); @@ -366,7 +398,7 @@ export default async function deploy(deploymentManager: DeploymentManager, deplo const marketUpdateTimelock = await deploymentManager.deploy( 'marketUpdateTimelock', 'marketupdates/MarketUpdateTimelock.sol', - [governor, 0], + [governor, 2 * 24 * 60 * 60], maybeForce() ) as MarketUpdateTimelock; @@ -390,123 +422,146 @@ export default async function deploy(deploymentManager: DeploymentManager, deplo maybeForce() ); - trace('Updating Admin of Configurator to CometProxyAdminNew'); - await timelock.executeTransactions( - [cometProxyAdminOld.address], - [0], - ['changeProxyAdmin(address,address)'], - [ - ethers.utils.defaultAbiCoder.encode( - ['address', 'address'], - [configuratorProxyContract.address, cometProxyAdminNew.address] - ) - ] - ); - - + const newSupplyKinkByGovernorTimelock = 300n; - trace('Updating Admin of CometProxy to CometProxyAdminNew'); - await timelock.executeTransactions( - [cometProxyAdminOld.address], - [0], - ['changeProxyAdmin(address,address)'], + trace('Trigger updates to enable market admin'); + const firstProposalTxn = await governorBravo.connect(admin).propose( [ - ethers.utils.defaultAbiCoder.encode( - ['address', 'address'], - [cometProxy.address, cometProxyAdminNew.address] - ) - ] - ); - - await timelock.executeTransactions( - [cometProxyAdminNew.address], - [0], - ['upgrade(address,address)'], + cometProxyAdminOld.address, + cometProxyAdminOld.address, + cometProxyAdminNew.address, + configuratorProxyContract.address, + cometProxyAdminNew.address, + marketUpdateTimelock.address + ], + [0, 0, 0, 0, 0, 0], [ - ethers.utils.defaultAbiCoder.encode( - ['address', 'address'], - [configuratorProxyContract.address, configuratorNew.address] - ) - ] - ); - - trace('Setting Market Update Admin in Configurator'); - await timelock.executeTransactions( - [configuratorProxyContract.address], - [0], - ['setMarketAdmin(address)'], + 'changeProxyAdmin(address,address)', + 'changeProxyAdmin(address,address)', + 'upgrade(address,address)', + 'setMarketAdmin(address)', + 'setMarketAdmin(address)', + 'setMarketUpdateProposer(address)', + ], [ - ethers.utils.defaultAbiCoder.encode( - ['address'], - [marketUpdateTimelock.address] - ) - ] + ethers.utils.defaultAbiCoder.encode(['address', 'address'], [configuratorProxyContract.address, cometProxyAdminNew.address]), + ethers.utils.defaultAbiCoder.encode(['address', 'address'], [cometProxy.address, cometProxyAdminNew.address]), + ethers.utils.defaultAbiCoder.encode(['address', 'address'], [configuratorProxyContract.address, configuratorNew.address]), + ethers.utils.defaultAbiCoder.encode(['address'], [marketUpdateTimelock.address]), + ethers.utils.defaultAbiCoder.encode(['address'], [marketUpdateTimelock.address]), + ethers.utils.defaultAbiCoder.encode(['address'], [marketUpdateProposer.address]) + ], + 'Proposal to trigger updates for market admin' ); + const firstProposalReceipt = await firstProposalTxn.wait(); - trace('Setting Market Update Admin in CometProxyAdmin'); - await timelock.executeTransactions( - [cometProxyAdminNew.address], - [0], - ['setMarketAdmin(address)'], + const firstProposalID = firstProposalReceipt.events.find( + (event) => event.event === 'ProposalCreated' + ).args.id; + console.log('first proposal id: ', firstProposalID); + + const stateBeforeStart = await governorBravo.state(firstProposalID); + console.log('Proposal State before start block forwarding:', stateBeforeStart); + + const votingDelay = await governorBravo.votingDelay(); + // Fast-forward by votingDelay blocks to reach the start of the voting period + for (let i = 0; i < votingDelay.toNumber(); i++) { + await ethers.provider.send('evm_mine', []); + } + const stateAfterStart = await governorBravo.state(firstProposalID); + console.log('Proposal State after start block forwarding:', stateAfterStart); + + await governorBravo.connect(admin).castVote(firstProposalID, 1); + + const votingPeriod = await governorBravo.votingPeriod(); + // Fast-forward to the end of the voting period + for (let i = 0; i <= votingPeriod.toNumber(); i++) { + await ethers.provider.send('evm_mine', []); // fast-forward remaining blocks + } + + const stateAfter = await governorBravo.state(firstProposalID); + console.log('Proposal State after fast-forward:', stateAfter); + + trace('Queue from Governor Bravo'); + await governorBravo.connect(admin).queue(firstProposalID); + trace('Execute from Governor Bravo'); + await governorBravo.connect(admin).execute(firstProposalID); + + trace('Update supply kink through GovernorBravo'); + const secondProposalTxn = await governorBravo.connect(admin).propose( [ - ethers.utils.defaultAbiCoder.encode( - ['address'], - [marketUpdateTimelock.address] - ) - ] - ); - - trace('Setting Market Update proposer in MarketUpdateTimelock'); - await timelock.executeTransactions( - [marketUpdateTimelock.address], - [0], - ['setMarketUpdateProposer(address)'], + configuratorProxyContract.address, + cometProxyAdminNew.address + ], + [0,0], [ - ethers.utils.defaultAbiCoder.encode( - ['address'], - [marketUpdateProposer.address] - ) - ] - ); - - trace('Governor Timelock: Setting new supplyKink in Configurator and deploying Comet'); - const newSupplyKinkByGovernorTimelock = 300n; - await timelock.executeTransactions( - [configuratorProxyContract.address, cometProxyAdminNew.address], - [0, 0], - ['setSupplyKink(address,uint64)', 'deployAndUpgradeTo(address,address)'], - [ethers.utils.defaultAbiCoder.encode( - ['address', 'uint64'], - [cometProxy.address, newSupplyKinkByGovernorTimelock] - ), - ethers.utils.defaultAbiCoder.encode( - ['address', 'address'], - [configuratorProxyContract.address, cometProxy.address] - ) + 'setSupplyKink(address,uint64)', + 'deployAndUpgradeTo(address,address)' + ], + [ + ethers.utils.defaultAbiCoder.encode(['address', 'uint64'], [cometProxy.address, newSupplyKinkByGovernorTimelock]), + ethers.utils.defaultAbiCoder.encode(['address', 'address'], [configuratorProxyContract.address, cometProxy.address]) ], + 'Proposal to update supply kink' ); + const secondProposalReceipt = await secondProposalTxn.wait(); + const secondProposalID = secondProposalReceipt.events.find( + (event) => event.event === 'ProposalCreated' + ).args.id; + console.log('second proposal id: ', secondProposalID); + + const stateBeforeStart2 = await governorBravo.state(secondProposalID); + console.log('Proposal State before start block forwarding #2:', stateBeforeStart2); + + const votingDelay2 = await governorBravo.votingDelay(); + // Fast-forward by votingDelay blocks to reach the start of the voting period + for (let i = 0; i < votingDelay2.toNumber(); i++) { + await ethers.provider.send('evm_mine', []); + } + const stateAfterStart2 = await governorBravo.state(secondProposalID); + console.log('Proposal State after start block forwarding #2:', stateAfterStart2); + + await governorBravo.connect(admin).castVote(secondProposalID, 1); + + const votingPeriod2 = await governorBravo.votingPeriod(); + // Fast-forward to the end of the voting period + for (let i = 0; i <= votingPeriod2.toNumber(); i++) { + await ethers.provider.send('evm_mine', []); // fast-forward remaining blocks + } + + const stateAfter2 = await governorBravo.state(secondProposalID); + console.log('Proposal State after fast-forward #2:', stateAfter2); + + trace('Queue from Governor Bravo #2'); + await governorBravo.connect(admin).queue(secondProposalID); + trace('Execute from Governor Bravo #2'); + await governorBravo.connect(admin).execute(secondProposalID); + const supplyKinkByGovernorTimelock = await (comet).supplyKink(); trace(`supplyKinkByGovernorTimelock:`, supplyKinkByGovernorTimelock); trace('MarketAdmin: Setting new supplyKink in Configurator and deploying Comet'); const newSupplyKinkByMarketAdmin = 100n; await marketUpdateProposer.connect(marketUpdateMultiSig).propose( - [configuratorProxyContract.address, cometProxyAdminNew.address], + [ + configuratorProxyContract.address, + cometProxyAdminNew.address + ], [0, 0], - ['setSupplyKink(address,uint64)', 'deployAndUpgradeTo(address,address)'], - [ethers.utils.defaultAbiCoder.encode( - ['address', 'uint64'], - [cometProxy.address, newSupplyKinkByMarketAdmin] - ), - ethers.utils.defaultAbiCoder.encode( - ['address', 'address'], - [configuratorProxyContract.address, cometProxy.address] - ) + [ + 'setSupplyKink(address,uint64)', + 'deployAndUpgradeTo(address,address)' + ], + [ + ethers.utils.defaultAbiCoder.encode(['address', 'uint64'], [cometProxy.address, newSupplyKinkByMarketAdmin]), + ethers.utils.defaultAbiCoder.encode(['address', 'address'], [configuratorProxyContract.address, cometProxy.address]) ], 'Test market update' ); + await advanceTimeAndMineBlock(2 * 24 * 60 * 60 + 10); // Fast forwarding by 2 days and a few seconds + trace('Executing market update proposal'); await marketUpdateProposer.connect(marketUpdateMultiSig).execute(1); diff --git a/test/marketupdates/market-update-deployment-test.ts b/test/marketupdates/market-update-deployment-test.ts index 111c34cb..e30d97d0 100644 --- a/test/marketupdates/market-update-deployment-test.ts +++ b/test/marketupdates/market-update-deployment-test.ts @@ -1,6 +1,9 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; -import { event, expect, wait } from './../helpers'; -import { initializeAndFundGovernorTimelock } from './market-updates-helper'; +import { expect } from './../helpers'; +import { + initializeAndFundGovernorTimelock, + advanceTimeAndMineBlock, +} from './market-updates-helper'; import { CometFactory__factory, CometProxyAdmin__factory, @@ -137,7 +140,7 @@ describe('MarketUpdateDeployment', function() { // 3) Deploy MarketUpdateTimelock with Governor Timelock as the owner const marketUpdateTimelock = await marketAdminTimelockFactory.deploy( governorTimelock.address, - 0 + 2 * 24 * 60 * 60 // This is 2 days in seconds ); // Fund the impersonated account @@ -294,6 +297,8 @@ describe('MarketUpdateDeployment', function() { 'Test market update' ); + await advanceTimeAndMineBlock(2 * 24 * 60 * 60 + 10); // Fast forward by 2 days + a few seconds to surpass the eta + await marketUpdateProposer.connect(marketUpdateMultiSig).execute(1); expect( @@ -307,7 +312,7 @@ describe('MarketUpdateDeployment', function() { governorTimelockSigner: SignerWithAddress; originalSigner: SignerWithAddress; }) { - const { governorTimelock, governorTimelockSigner } = input; + const { governorTimelockSigner } = input; const opts: any = {}; const { diff --git a/test/marketupdates/market-update-proposer-test.ts b/test/marketupdates/market-update-proposer-test.ts index 1123eae0..bd206178 100644 --- a/test/marketupdates/market-update-proposer-test.ts +++ b/test/marketupdates/market-update-proposer-test.ts @@ -1,4 +1,4 @@ -import { makeMarketAdmin } from './market-updates-helper'; +import { makeMarketAdmin, advanceTimeAndMineBlock } from './market-updates-helper'; import { expect, makeConfigurator, ethers, wait, event } from '../helpers'; describe('MarketUpdateProposer', function() { @@ -231,10 +231,21 @@ describe('MarketUpdateProposer', function() { proposalDescription ); + // Get the timelock address from the MarketUpdateProposer contract + const timelockAddress = await marketUpdateProposer.timelock(); + + // Create a contract instance for the timelock using its interface + const timelockContract = await ethers.getContractAt( + 'ITimelock', + timelockAddress + ); + + // Now call the delay function from the timelock contract + const delay = (await timelockContract.delay()).toNumber(); + // Fast forward time by more than the GRACE_PERIOD const GRACE_PERIOD = 14 * 24 * 60 * 60; // 14 days in seconds - await ethers.provider.send('evm_increaseTime', [GRACE_PERIOD + 1]); // Increase by 14 days + 1 second - await ethers.provider.send('evm_mine', []); // Mine the next block to apply the time increase + await advanceTimeAndMineBlock(GRACE_PERIOD + delay + 1);// Increase by 14 days(GRACE_PERIOD) + timelock delay + 1 second expect(await marketUpdateProposer.state(proposalId)).to.equal(3); // Proposal should be expired diff --git a/test/marketupdates/market-update-timelock-test.ts b/test/marketupdates/market-update-timelock-test.ts index 73f1bc03..d88e8061 100644 --- a/test/marketupdates/market-update-timelock-test.ts +++ b/test/marketupdates/market-update-timelock-test.ts @@ -1,4 +1,4 @@ -import { makeMarketAdmin } from './market-updates-helper'; +import { makeMarketAdmin, advanceTimeAndMineBlock } from './market-updates-helper'; import { expect, makeConfigurator, ethers } from '../helpers'; describe('MarketUpdateTimelock', function() { @@ -49,10 +49,14 @@ describe('MarketUpdateTimelock', function() { users: [bob], } = await makeConfigurator(); + // Get the delay from the contract + const delay = (await marketUpdateTimelock.delay()).toNumber(); // Example: 172800 for 2 days + const latestBlock = await ethers.provider.getBlock('latest'); const currentTimestamp = latestBlock.timestamp; - const eta = currentTimestamp + 5; // Ensure eta is in the future + // Ensure eta is sufficiently in the future + const eta = currentTimestamp + delay + 5; // eta is current timestamp + delay + a few seconds // ensuring that main gover-timelock can queue transactions await marketUpdateTimelock @@ -122,10 +126,13 @@ describe('MarketUpdateTimelock', function() { configuratorAsProxy.transferGovernor(marketUpdateTimelock.address); const proposalId = 1n; + // Get the delay from the contract + const delay = (await marketUpdateTimelock.delay()).toNumber(); // Example: 172800 for 2 days + let latestBlock = await ethers.provider.getBlock('latest'); let currentTimestamp = latestBlock.timestamp; - let eta = currentTimestamp + 5; // Ensure eta is in the future + let eta = currentTimestamp + delay + 5; // Ensure eta is in the future // ensuring that main gover-timelock can execute transactions await marketUpdateTimelock @@ -141,9 +148,8 @@ describe('MarketUpdateTimelock', function() { eta ); - // Fast-forward time by 5 seconds to surpass the eta - await ethers.provider.send('evm_increaseTime', [5]); - await ethers.provider.send('evm_mine', []); // Mine a new block to apply the time increase + // Fast-forward time by delay + few seconds to surpass the eta + await advanceTimeAndMineBlock(delay); await marketUpdateTimelock .connect(governorTimelockSigner) @@ -174,6 +180,9 @@ describe('MarketUpdateTimelock', function() { 'Setting supply kink to 100' ); + // Fast-forward time by delay + seconds to surpass the eta + await advanceTimeAndMineBlock(delay); + await marketUpdateProposer .connect(marketUpdateMultiSig) .execute(proposalId); @@ -184,7 +193,7 @@ describe('MarketUpdateTimelock', function() { latestBlock = await ethers.provider.getBlock('latest'); currentTimestamp = latestBlock.timestamp; - eta = currentTimestamp + 5; // Ensure eta is in the future + eta = currentTimestamp + delay + 5; // Ensure eta is in the future // ensuring that MarketUpdateProposer can execute transactions await marketUpdateTimelock @@ -200,9 +209,8 @@ describe('MarketUpdateTimelock', function() { eta ); - // Fast-forward time by 5 seconds to surpass the eta - await ethers.provider.send('evm_increaseTime', [5]); - await ethers.provider.send('evm_mine', []); // Mine a new block to apply the time increase + // Fast-forward time by delay + few seconds to surpass the eta + await advanceTimeAndMineBlock(delay); await expect( marketUpdateTimelock @@ -242,12 +250,15 @@ describe('MarketUpdateTimelock', function() { const proposalId = 1n; + // Get the delay from the contract + const delay = (await marketUpdateTimelock.delay()).toNumber(); // Example: 172800 for 2 days + let latestBlock = await ethers.provider.getBlock('latest'); let currentTimestamp = latestBlock.timestamp; - let eta = currentTimestamp + 5; // Ensure eta is in the future + let eta = currentTimestamp + delay + 5; // Ensure eta is in the future - // ensuring that main gover-timelock can cancel transactions + // ensuring that main governor-timelock can cancel transactions await marketUpdateTimelock .connect(governorTimelockSigner) .queueTransaction( @@ -274,7 +285,7 @@ describe('MarketUpdateTimelock', function() { eta ); - // ensuring that MarketUpdateProposer can cacnel transactions + // ensuring that MarketUpdateProposer can cancel transactions await marketUpdateProposer .connect(marketUpdateMultiSig) .propose( @@ -319,7 +330,7 @@ describe('MarketUpdateTimelock', function() { latestBlock = await ethers.provider.getBlock('latest'); currentTimestamp = latestBlock.timestamp; - eta = currentTimestamp + 5; // Ensure eta is in the future + eta = currentTimestamp + delay + 5; // Ensure eta is in the future // ensuring that MarketUpdateProposer can execute transactions await marketUpdateTimelock @@ -411,4 +422,4 @@ describe('MarketUpdateTimelock', function() { 'MarketUpdateTimelock::setAdmin: Call must come from admin.' ); }); -}); +}); \ No newline at end of file diff --git a/test/marketupdates/market-updates-helper.ts b/test/marketupdates/market-updates-helper.ts index 1fef50a3..85fa0515 100644 --- a/test/marketupdates/market-updates-helper.ts +++ b/test/marketupdates/market-updates-helper.ts @@ -41,7 +41,7 @@ export async function makeMarketAdmin() { const marketUpdateTimelock = await marketAdminTimelockFactory.deploy( governorTimelock.address, - 0 + 2 * 24 * 60 * 60 // This is 2 days in seconds ); const marketUpdateTimelockAddress = await marketUpdateTimelock.deployed(); @@ -105,3 +105,8 @@ export async function initializeAndFundGovernorTimelock() { const governorTimelockSigner = await ethers.getSigner(governorTimelock.address); return { originalSigner: gov, governorTimelockSigner, governorTimelock }; } + +export async function advanceTimeAndMineBlock(delay: number) { + await ethers.provider.send('evm_increaseTime', [delay + 10]); + await ethers.provider.send('evm_mine', []); // Mine a new block to apply the time increase +} From 00d941c1ab7d70540bdcaf3282be76bb229364cd Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 10 Sep 2024 19:34:02 -0400 Subject: [PATCH 04/28] Update solidity version --- contracts/marketupdates/MarketUpdateTimelock.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/marketupdates/MarketUpdateTimelock.sol b/contracts/marketupdates/MarketUpdateTimelock.sol index ecbb5bea..8bf4188c 100644 --- a/contracts/marketupdates/MarketUpdateTimelock.sol +++ b/contracts/marketupdates/MarketUpdateTimelock.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -pragma solidity ^0.8.10; +pragma solidity 0.8.15; /* From bb32bfba18e477a435812524030e549bdcdd5d28 Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 16 Sep 2024 11:43:50 -0400 Subject: [PATCH 05/28] Add pauseGuardian to MaketUpdateProposer so that it can cancel the proposals if needed --- contracts/CometProxyAdmin.sol | 11 +- contracts/ConfiguratorStorage.sol | 2 +- .../marketupdates/MarketUpdateProposer.sol | 77 +++- .../marketupdates/MarketUpdateTimelock.sol | 42 +- .../market-update-proposer-test.ts | 401 +++++++++++++++++- .../market-update-timelock-test.ts | 32 +- test/marketupdates/market-updates-helper.ts | 49 +-- 7 files changed, 511 insertions(+), 103 deletions(-) diff --git a/contracts/CometProxyAdmin.sol b/contracts/CometProxyAdmin.sol index 3bf5bf3e..37f21ed0 100644 --- a/contracts/CometProxyAdmin.sol +++ b/contracts/CometProxyAdmin.sol @@ -9,7 +9,7 @@ interface Deployable { contract CometProxyAdmin is ProxyAdmin { /// @notice Pause flag for the market update admin - bool public marketAdminPaused = false; + bool public marketAdminPaused; /// @notice The address of the market update admin. This will be the address of a timelock contract. address public marketAdmin; @@ -33,11 +33,9 @@ contract CometProxyAdmin is ProxyAdmin { */ modifier ownerOrMarketAdmin() { // using revert instead of require to keep it consistent with other calls - if (owner() != _msgSender() && marketAdmin != _msgSender()) - revert Unauthorized(); + if (owner() != _msgSender() && marketAdmin != _msgSender()) revert Unauthorized(); // If the sender is the marketAdmin, check that the marketAdmin is not paused - if (_msgSender() == marketAdmin && marketAdminPaused) - revert MarketAdminIsPaused(); + if (_msgSender() == marketAdmin && marketAdminPaused) revert MarketAdminIsPaused(); _; } @@ -64,8 +62,7 @@ contract CometProxyAdmin is ProxyAdmin { */ function pauseMarketAdmin() external { if (marketAdminPaused) revert AlreadyPaused(); - if (msg.sender != owner() && msg.sender != marketAdminPauseGuardian) - revert Unauthorized(); + if (msg.sender != owner() && msg.sender != marketAdminPauseGuardian) revert Unauthorized(); marketAdminPaused = true; emit MarketAdminPaused(msg.sender, true); } diff --git a/contracts/ConfiguratorStorage.sol b/contracts/ConfiguratorStorage.sol index 82000fce..37ff6ae3 100644 --- a/contracts/ConfiguratorStorage.sol +++ b/contracts/ConfiguratorStorage.sol @@ -29,7 +29,7 @@ contract ConfiguratorStorage is CometConfiguration { address public marketAdmin; /// @notice Pause flag for the market admin - bool public marketAdminPaused = false; + bool public marketAdminPaused; /// @notice address of the market admin pause guardian. We don't use `pauseGuardian` role because we have `setPauseGuardian` already which sets the pauseGuardian on comet. address public marketAdminPauseGuardian; diff --git a/contracts/marketupdates/MarketUpdateProposer.sol b/contracts/marketupdates/MarketUpdateProposer.sol index 6a3a7442..9ff643c4 100644 --- a/contracts/marketupdates/MarketUpdateProposer.sol +++ b/contracts/marketupdates/MarketUpdateProposer.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.15; import "./../ITimelock.sol"; -import "./../vendor/access/Ownable.sol"; /** * @title MarketUpdateProposer @@ -16,7 +15,7 @@ import "./../vendor/access/Ownable.sol"; * overkill * */ -contract MarketUpdateProposer is Ownable { +contract MarketUpdateProposer { struct MarketUpdateProposal { /// @notice Unique id for looking up a proposal uint id; @@ -55,6 +54,9 @@ contract MarketUpdateProposer is Ownable { Expired } + address public governor; + address public pauseGuardian; + address public marketAdmin; ITimelock public timelock; /// @notice The official record of all proposals ever proposed @@ -69,19 +71,70 @@ contract MarketUpdateProposer is Ownable { event MarketUpdateProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, string description); event MarketUpdateProposalExecuted(uint id); event MarketUpdateProposalCancelled(uint id); + event SetPauseGuardian(address indexed oldPauseGuardian, address indexed newPauseGuardian); + event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); + event SetGovernor(address indexed oldGovernor, address indexed newGovernor); - error AlreadyInitialized(); + error Unauthorized(); error InvalidAddress(); - - function initialize(ITimelock timelock_) public onlyOwner { - if (address(timelock_) == address(0)) revert InvalidAddress(); - if (address(timelock) != address(0)) revert AlreadyInitialized(); - + constructor(address governor_, address marketAdmin_, address pauseGuardian_, ITimelock timelock_) public { + if (address(governor_) == address(0) || address(marketAdmin_) == address(0) || address(timelock_) == address(0)) revert InvalidAddress(); + governor = governor_; + marketAdmin = marketAdmin_; + pauseGuardian = pauseGuardian_; timelock = timelock_; } + + /** + * @notice Transfers the governor rights to a new address + * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the owner. + * Emits an event with the old and new governor addresses. + * @param newGovernor The address of the new governor. + */ + function setGovernor(address newGovernor) external { + if (msg.sender != governor) revert Unauthorized(); + if (address(newGovernor) == address(0)) revert InvalidAddress(); + + address oldGovernor = governor; + governor = newGovernor; + emit SetGovernor(oldGovernor, newGovernor); + } + + /** + * @notice Sets a new pause guardian. + * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the owner. + * Emits an event with the old and new pause guardian addresses. + * Note that there is no enforced zero address check on `newPauseGuadian` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the pause guadian. + * @param newPauseGuardian The address of the new market admin pause guardian. + */ + function setPauseGuardian(address newPauseGuardian) external { + if (msg.sender != governor) revert Unauthorized(); + address oldPauseGuardian = pauseGuardian; + pauseGuardian = newPauseGuardian; + emit SetPauseGuardian(oldPauseGuardian, newPauseGuardian); + } - function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) public onlyOwner returns (uint) { + /** + * @notice Sets a new market admin. + * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the governor. + * Emits an event with the old and new market admin addresses. + * Note that there is no enforced zero address check on `newMarketAdmin` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the market admin role. + * @param newMarketAdmin The address of the new market admin. + */ + function setMarketAdmin(address newMarketAdmin) external { + if (msg.sender != governor) revert Unauthorized(); + address oldMarketAdmin = marketAdmin; + marketAdmin = newMarketAdmin; + emit SetMarketAdmin(oldMarketAdmin, newMarketAdmin); + } + + function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) public returns (uint) { + if (msg.sender != marketAdmin) revert Unauthorized(); require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, "MarketUpdateProposer::propose: proposal function information arity mismatch"); require(targets.length != 0, "MarketUpdateProposer::propose: must provide actions"); @@ -123,7 +176,8 @@ contract MarketUpdateProposer is Ownable { * @notice Executes a queued proposal if eta has passed * @param proposalId The id of the proposal to execute */ - function execute(uint proposalId) external payable onlyOwner { + function execute(uint proposalId) external payable { + if (msg.sender != marketAdmin) revert Unauthorized(); require(state(proposalId) == ProposalState.Queued, "MarketUpdateProposer::execute: proposal can only be executed if it is queued"); MarketUpdateProposal storage proposal = proposals[proposalId]; proposal.executed = true; @@ -137,7 +191,8 @@ contract MarketUpdateProposer is Ownable { * @notice Cancels a proposal only if sender is the proposer, or proposer delegates dropped below proposal threshold * @param proposalId The id of the proposal to cancel */ - function cancel(uint proposalId) external onlyOwner { + function cancel(uint proposalId) external { + if (msg.sender != governor && msg.sender != pauseGuardian && msg.sender != marketAdmin) revert Unauthorized(); require(state(proposalId) != ProposalState.Executed, "MarketUpdateProposer::cancel: cannot cancel executed proposal"); MarketUpdateProposal storage proposal = proposals[proposalId]; diff --git a/contracts/marketupdates/MarketUpdateTimelock.sol b/contracts/marketupdates/MarketUpdateTimelock.sol index 8bf4188c..e0487889 100644 --- a/contracts/marketupdates/MarketUpdateTimelock.sol +++ b/contracts/marketupdates/MarketUpdateTimelock.sol @@ -3,15 +3,15 @@ pragma solidity 0.8.15; /* -Right now admin and marketUpdateProposer can cancel one another's transactions, but -this is not a realistic scenario as admin is a main-governor-timelock which will not be +Right now governor and marketUpdateProposer can cancel one another's transactions, but +this is not a realistic scenario as governor is the main-governor-timelock which will not be queuing, executing, or cancelling transactions. So we are not handling or testing it. */ contract MarketUpdateTimelock { - event NewAdmin(address indexed oldAdmin, address indexed newAdmin); - event NewMarketUpdateProposer(address indexed oldMarketAdmin, address indexed newMarketAdmin); - event NewDelay(uint indexed newDelay); + event SetGovernor(address indexed oldGovernor, address indexed newGovernor); + event SetMarketUpdateProposer(address indexed oldMarketAdmin, address indexed newMarketAdmin); + event SetDelay(uint indexed newDelay); event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); @@ -20,22 +20,22 @@ contract MarketUpdateTimelock { uint public constant MINIMUM_DELAY = 2 days; uint public constant MAXIMUM_DELAY = 30 days; - address public admin; + address public governor; address public marketUpdateProposer; uint public delay; mapping (bytes32 => bool) public queuedTransactions; - modifier adminOrMarketUpdater { - require(msg.sender == admin || msg.sender == marketUpdateProposer, "MarketUpdateTimelock::Unauthorized: call must come from admin or marketAdmin"); + modifier governorOrMarketUpdater { + require(msg.sender == governor || msg.sender == marketUpdateProposer, "MarketUpdateTimelock::Unauthorized: call must come from governor or marketAdmin"); _; } - constructor(address admin_, uint delay_) public { + constructor(address governor_, uint delay_) public { require(delay_ >= MINIMUM_DELAY, "MarketUpdateTimelock::constructor: Delay must exceed minimum delay."); require(delay_ <= MAXIMUM_DELAY, "MarketUpdateTimelock::setDelay: Delay must not exceed maximum delay."); - admin = admin_; + governor = governor_; delay = delay_; } @@ -48,24 +48,24 @@ contract MarketUpdateTimelock { require(delay_ <= MAXIMUM_DELAY, "MarketUpdateTimelock::setDelay: Delay must not exceed maximum delay."); delay = delay_; - emit NewDelay(delay); + emit SetDelay(delay); } - function setAdmin(address newAdmin) public { - require(msg.sender == admin, "MarketUpdateTimelock::setAdmin: Call must come from admin."); - address oldAdmin = admin; - admin = newAdmin; - emit NewAdmin(oldAdmin, newAdmin); + function setGovernor(address newGovernor) public { + require(msg.sender == governor, "MarketUpdateTimelock::setGovernor: Call must come from governor."); + address oldGovernor = governor; + governor = newGovernor; + emit SetGovernor(oldGovernor, newGovernor); } function setMarketUpdateProposer(address newMarketUpdateProposer) external { - require(msg.sender == admin, "MarketUpdateTimelock::setMarketUpdateProposer: Call must come from admin."); + require(msg.sender == governor, "MarketUpdateTimelock::setMarketUpdateProposer: Call must come from governor."); address oldMarketUpdateProposer = marketUpdateProposer; marketUpdateProposer = newMarketUpdateProposer; - emit NewMarketUpdateProposer(oldMarketUpdateProposer, newMarketUpdateProposer); + emit SetMarketUpdateProposer(oldMarketUpdateProposer, newMarketUpdateProposer); } - function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public adminOrMarketUpdater returns (bytes32) { + function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public governorOrMarketUpdater returns (bytes32) { require(eta >= getBlockTimestamp() + delay, "MarketUpdateTimelock::queueTransaction: Estimated execution block must satisfy delay."); bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); @@ -75,14 +75,14 @@ contract MarketUpdateTimelock { return txHash; } - function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public adminOrMarketUpdater { + function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public governorOrMarketUpdater { bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); queuedTransactions[txHash] = false; emit CancelTransaction(txHash, target, value, signature, data, eta); } - function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable adminOrMarketUpdater returns (bytes memory) { + function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable governorOrMarketUpdater returns (bytes memory) { bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); require(queuedTransactions[txHash], "MarketUpdateTimelock::executeTransaction: Transaction hasn't been queued."); require(getBlockTimestamp() >= eta, "MarketUpdateTimelock::executeTransaction: Transaction hasn't surpassed time lock."); diff --git a/test/marketupdates/market-update-proposer-test.ts b/test/marketupdates/market-update-proposer-test.ts index bd206178..537b8c57 100644 --- a/test/marketupdates/market-update-proposer-test.ts +++ b/test/marketupdates/market-update-proposer-test.ts @@ -1,5 +1,6 @@ import { makeMarketAdmin, advanceTimeAndMineBlock } from './market-updates-helper'; import { expect, makeConfigurator, ethers, wait, event } from '../helpers'; +import { MarketUpdateProposer__factory } from '../../build/types'; describe('MarketUpdateProposer', function() { // We are not checking market updates here. we are just checking interaction @@ -16,49 +17,67 @@ describe('MarketUpdateProposer', function() { ); }); - it('throw error if MarketUpdateProposer is initialized twice', async () => { + it('MarketUpdateMultisig is set as the marketAdmin of MarketUpdateProposer', async () => { const { marketUpdateProposer, - marketUpdateTimelock, + marketUpdateMultiSig, } = await makeMarketAdmin(); - await expect( - marketUpdateProposer.initialize(marketUpdateTimelock.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'AlreadyInitialized'); + expect(await marketUpdateProposer.marketAdmin()).to.equal( + marketUpdateMultiSig.address + ); }); - it('MarketUpdateMultisig is set as the owner of MarketUpdateProposer', async () => { + it('only GovernorTimelock can set a new governor for MarketUpdateProposer', async () => { const { + governorTimelockSigner, marketUpdateProposer, - marketUpdateMultiSig, } = await makeMarketAdmin(); - expect(await marketUpdateProposer.owner()).to.equal( - marketUpdateMultiSig.address + const { + users: [alice, bob], + } = await makeConfigurator(); + + expect(await marketUpdateProposer.governor()).to.equal( + governorTimelockSigner.address ); - }); - it('MarketUpdateMultisig can set a new owner for MarketUpdateProposer', async () => { + await marketUpdateProposer + .connect(governorTimelockSigner) + .setGovernor(alice.address); + + expect(await marketUpdateProposer.governor()).to.equal(alice.address); + + await expect( + marketUpdateProposer.connect(bob).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + }); + + it('only GovernorTimelock can set a new pause guardian for MarketUpdateProposer', async () => { const { + governorTimelockSigner, marketUpdateProposer, - marketUpdateMultiSig, } = await makeMarketAdmin(); const { - users: [alice], + users: [alice, bob], } = await makeConfigurator(); - expect(await marketUpdateProposer.owner()).to.equal( - marketUpdateMultiSig.address + expect(await marketUpdateProposer.governor()).to.equal( + governorTimelockSigner.address ); await marketUpdateProposer - .connect(marketUpdateMultiSig) - .transferOwnership(alice.address); + .connect(governorTimelockSigner) + .setPauseGuardian(alice.address); - expect(await marketUpdateProposer.owner()).to.equal(alice.address); + expect(await marketUpdateProposer.pauseGuardian()).to.equal(alice.address); + + await expect( + marketUpdateProposer.connect(bob).setPauseGuardian(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); }); - + it('only allows MarketUpdateMultisig to create proposal', async () => { const { marketUpdateProposer, @@ -115,7 +134,7 @@ describe('MarketUpdateProposer', function() { [setSupplyKinkCalldata], proposalDescription ) - ).to.be.revertedWith('Ownable: caller is not the owner'); + ).to.be.revertedWithCustomError(marketUpdateProposer,'Unauthorized'); }); it('keeps track of all the proposals', async () => { @@ -255,4 +274,346 @@ describe('MarketUpdateProposer', function() { 'MarketUpdateProposer::execute: proposal can only be executed if it is queued' ); }); + + describe('MarketUpdateProposer::permissions', function () { + it('should ensure the addresses are not zero while creating the contract(constructor validation)', async () => { + const { + governorTimelockSigner, + marketUpdateMultiSig, + pauseGuardianSigner, + marketUpdateTimelock + } = await makeMarketAdmin(); + + const marketUpdaterProposerFactory = (await ethers.getContractFactory( + 'MarketUpdateProposer' + )) as MarketUpdateProposer__factory; + + // Governor as zero address + await expect(marketUpdaterProposerFactory + .deploy(ethers.constants.AddressZero, marketUpdateMultiSig.address, pauseGuardianSigner.address, marketUpdateTimelock.address)) + .to.be.revertedWithCustomError(marketUpdaterProposerFactory, 'InvalidAddress'); + + // Market admin as zero address + await expect(marketUpdaterProposerFactory + .deploy(governorTimelockSigner.address, ethers.constants.AddressZero, pauseGuardianSigner.address, marketUpdateTimelock.address)) + .to.be.revertedWithCustomError(marketUpdaterProposerFactory, 'InvalidAddress'); + + await expect(marketUpdaterProposerFactory + .deploy(governorTimelockSigner.address, marketUpdateMultiSig.address, pauseGuardianSigner.address, ethers.constants.AddressZero)) + .to.be.revertedWithCustomError(marketUpdaterProposerFactory, 'InvalidAddress'); + + const marketUpdateProposer = await marketUpdaterProposerFactory + .deploy(governorTimelockSigner.address, marketUpdateMultiSig.address, pauseGuardianSigner.address, marketUpdateTimelock.address); + + expect(await marketUpdateProposer.governor()).to.be.equal(governorTimelockSigner.address); + expect(await marketUpdateProposer.marketAdmin()).to.be.equal(marketUpdateMultiSig.address); + expect(await marketUpdateProposer.pauseGuardian()).to.be.equal(pauseGuardianSigner.address); + expect(await marketUpdateProposer.timelock()).to.be.equal(marketUpdateTimelock.address); + + }); + + it('only governor can update a governor', async () => { + // include checks for pauseGuardian, marketAdmin, and nonGovernor for failure scenario + const { + governorTimelockSigner, + marketUpdateProposer, + marketUpdateMultiSig, + pauseGuardianSigner, + } = await makeMarketAdmin(); + + const { + users: [alice, bob], + } = await makeConfigurator(); + + expect(await marketUpdateProposer.governor()).to.be.equal(governorTimelockSigner.address); + + // Ensure only the governor can set a new governor + await marketUpdateProposer + .connect(governorTimelockSigner) + .setGovernor(alice.address); + + expect(await marketUpdateProposer.governor()).to.equal(alice.address); + + // failure case: market admin cannot update the governor + await expect( + marketUpdateProposer.connect(marketUpdateMultiSig).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // failure case: pause guardian cannot update the governor + await expect( + marketUpdateProposer.connect(pauseGuardianSigner).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // failure case: Non-governor cannot update the governor + await expect( + marketUpdateProposer.connect(bob).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + }); + it('only governor can update a marketAdmin', async () => { + // include checks for pauseGuardian, marketAdmin, and nonGovernor for failure scenario + const { + governorTimelockSigner, + marketUpdateProposer, + marketUpdateMultiSig, + pauseGuardianSigner, + } = await makeMarketAdmin(); + + const { + users: [alice, bob], + } = await makeConfigurator(); + + expect(await marketUpdateProposer.governor()).to.be.equal(governorTimelockSigner.address); + + // Ensure only the governor can set a new market admin + await marketUpdateProposer + .connect(governorTimelockSigner) + .setMarketAdmin(alice.address); + + expect(await marketUpdateProposer.marketAdmin()).to.equal(alice.address); + + // failure case: market admin cannot update the market admin + await expect( + marketUpdateProposer.connect(marketUpdateMultiSig).setMarketAdmin(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // failure case: pause guardian cannot update the market admin + await expect( + marketUpdateProposer.connect(pauseGuardianSigner).setMarketAdmin(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // failure case: Non-governor cannot update the market admin + await expect( + marketUpdateProposer.connect(bob).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + }); + it('only governor can update a pauseGuardian', async () => { + // include checks for pauseGuardian, marketAdmin, and nonGovernor for failure scenario + const { + governorTimelockSigner, + marketUpdateProposer, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + const { + users: [alice, bob, john], + } = await makeConfigurator(); + + expect(await marketUpdateProposer.governor()).to.be.equal(governorTimelockSigner.address); + + // Ensure only the governor can set a new pause guardian + await marketUpdateProposer + .connect(governorTimelockSigner) + .setPauseGuardian(alice.address); + + expect(await marketUpdateProposer.pauseGuardian()).to.equal(alice.address); + + // failure case: market admin cannot update the pause guardian + await expect( + marketUpdateProposer.connect(marketUpdateMultiSig).setPauseGuardian(bob.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // failure case: pause guardian cannot update the pause guardian + // alice is the pause guardian by the above governor call + await expect( + marketUpdateProposer.connect(alice).setPauseGuardian(bob.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // failure case: Non-governor cannot update the pause guardian + await expect( + marketUpdateProposer.connect(john).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + }); + + it('only marketAdmin can create a proposal', async () => { + // include checks for pauseGuardian, and governor, and anonymous address + const { + governorTimelockSigner, + marketUpdateProposer, + marketUpdateMultiSig, + pauseGuardianSigner + } = await makeMarketAdmin(); + + const { configuratorProxy, cometProxy, users: [alice] } = await makeConfigurator(); + + expect(await marketUpdateProposer.marketAdmin()).to.be.equal( + marketUpdateMultiSig.address + ); + + let setSupplyKinkCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ); + + const proposalDescription = 'Test Proposal'; + + // only MarketAdmin can create a proposal + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + proposalDescription + ); + + // Failure case: Governor cannot create a proposal + await expect( + marketUpdateProposer + .connect(governorTimelockSigner) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + proposalDescription + ) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // Failure case: Pause guardian cannot create a proposal + await expect( + marketUpdateProposer + .connect(pauseGuardianSigner) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + proposalDescription + ) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // Failure case: anonymous cannot create a proposal + await expect( + marketUpdateProposer + .connect(alice) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + proposalDescription + ) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + }); + + it('only marketAdmin can execute a proposal', async () => { + // include checks for pauseGuardian, marketAdmin, and governor, and anonymous address + const { + governorTimelockSigner, + marketUpdateProposer, + marketUpdateMultiSig, + marketUpdateTimelock, + pauseGuardianSigner + } = await makeMarketAdmin(); + + const { + configuratorProxy, + configurator, + cometProxy, + users: [bob], + } = await makeConfigurator( + {governor: governorTimelockSigner} + ); + + expect(await marketUpdateProposer.marketAdmin()).to.be.equal( + marketUpdateMultiSig.address + ); + + let setSupplyKinkCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ); + + const proposalDescription = 'Test Proposal'; + + // only MarketAdmin can create a proposal + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + proposalDescription + ); + + const delay = (await marketUpdateTimelock.delay()).toNumber(); // Example: 172800 for 2 days + // Fast-forward time by delay + few seconds to surpass the eta + await advanceTimeAndMineBlock(delay); + + const proposalId = 1n; + + // Failure case: Governor cannot execute the proposal + await expect( + marketUpdateProposer.connect(governorTimelockSigner).execute(proposalId) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // Failure case: Pause guardian cannot execute the proposal + await expect( + marketUpdateProposer.connect(pauseGuardianSigner).execute(proposalId) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // Failure case: anonymous cannot execute the proposal + await expect( + marketUpdateProposer.connect(bob).execute(proposalId) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + // Success case: only MarketAdmin can execute the proposal + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + await configuratorAsProxy.connect(governorTimelockSigner).setMarketAdmin(marketUpdateTimelock.address); + expect (await configuratorAsProxy.marketAdmin()).to.be.equal(marketUpdateTimelock.address); + await marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId); + }); + + it('only marketAdmin, pauseGuardian, or governor can cancel a proposal', async () => { + // include checks for pauseGuardian, marketAdmin, and governor, and anonymous address + const { + governorTimelockSigner, + marketUpdateProposer, + marketUpdateMultiSig, + pauseGuardianSigner + } = await makeMarketAdmin(); + + const { configuratorProxy, cometProxy, users: [bob] } = await makeConfigurator(); + + expect(await marketUpdateProposer.marketAdmin()).to.be.equal( + marketUpdateMultiSig.address + ); + + let setSupplyKinkCalldata = ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ); + + const proposalDescription = 'Test Proposal'; + + // only MarketAdmin can create a proposal + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [setSupplyKinkCalldata], + proposalDescription + ); + const proposalId = 1n; + + // Success case: Governor can cancel the proposal + expect(await marketUpdateProposer.connect(governorTimelockSigner).cancel(proposalId)); + + // Success case: MarketAdmin can cancel the proposal + await marketUpdateProposer.connect(marketUpdateMultiSig).cancel(proposalId); + + // Success case: Pause guardian can cancel the proposal + expect(await marketUpdateProposer.connect(pauseGuardianSigner).cancel(proposalId)); + + // Failure case: anonymous cannot cancel the proposal + await expect( + marketUpdateProposer.connect(bob).cancel(proposalId) + ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + + }); + }); }); diff --git a/test/marketupdates/market-update-timelock-test.ts b/test/marketupdates/market-update-timelock-test.ts index d88e8061..b3b913c7 100644 --- a/test/marketupdates/market-update-timelock-test.ts +++ b/test/marketupdates/market-update-timelock-test.ts @@ -2,11 +2,11 @@ import { makeMarketAdmin, advanceTimeAndMineBlock } from './market-updates-helpe import { expect, makeConfigurator, ethers } from '../helpers'; describe('MarketUpdateTimelock', function() { - it('is created properly with main-governor-timelock as admin', async () => { - const { marketUpdateTimelock, governorTimelock } = await makeMarketAdmin(); + it('is created properly with main-governor-timelock as governor', async () => { + const { marketUpdateTimelock, governorTimelockSigner } = await makeMarketAdmin(); - expect(await marketUpdateTimelock.admin()).to.equal( - governorTimelock.address + expect(await marketUpdateTimelock.governor()).to.equal( + governorTimelockSigner.address ); }); @@ -31,7 +31,7 @@ describe('MarketUpdateTimelock', function() { await expect( marketUpdateTimelock.connect(bob).setMarketUpdateProposer(bob.address) ).to.be.revertedWith( - 'MarketUpdateTimelock::setMarketUpdateProposer: Call must come from admin.' + 'MarketUpdateTimelock::setMarketUpdateProposer: Call must come from governor.' ); }); @@ -103,7 +103,7 @@ describe('MarketUpdateTimelock', function() { eta ) ).to.be.revertedWith( - 'MarketUpdateTimelock::Unauthorized: call must come from admin or marketAdmin' + 'MarketUpdateTimelock::Unauthorized: call must come from governor or marketAdmin' ); }); @@ -226,7 +226,7 @@ describe('MarketUpdateTimelock', function() { eta ) ).to.be.revertedWith( - 'MarketUpdateTimelock::Unauthorized: call must come from admin or marketAdmin' + 'MarketUpdateTimelock::Unauthorized: call must come from governor or marketAdmin' ); }); @@ -360,11 +360,11 @@ describe('MarketUpdateTimelock', function() { eta ) ).to.be.revertedWith( - 'MarketUpdateTimelock::Unauthorized: call must come from admin or marketAdmin' + 'MarketUpdateTimelock::Unauthorized: call must come from governor or marketAdmin' ); }); - it('only main-governor-timelock can set new admin', async () => { + it('only main-governor-timelock can set new governor', async () => { const { marketUpdateTimelock, governorTimelockSigner, @@ -376,14 +376,14 @@ describe('MarketUpdateTimelock', function() { await marketUpdateTimelock .connect(governorTimelockSigner) - .setAdmin(alice.address); + .setGovernor(alice.address); - expect(await marketUpdateTimelock.admin()).to.equal(alice.address); + expect(await marketUpdateTimelock.governor()).to.equal(alice.address); await expect( - marketUpdateTimelock.connect(bob).setAdmin(bob.address) + marketUpdateTimelock.connect(bob).setGovernor(bob.address) ).to.be.revertedWith( - 'MarketUpdateTimelock::setAdmin: Call must come from admin.' + 'MarketUpdateTimelock::setGovernor: Call must come from governor.' ); }); @@ -402,7 +402,7 @@ describe('MarketUpdateTimelock', function() { .connect(marketUpdateMultiSig) .setMarketUpdateProposer(bob.address) ).to.be.revertedWith( - 'MarketUpdateTimelock::setMarketUpdateProposer: Call must come from admin.' + 'MarketUpdateTimelock::setMarketUpdateProposer: Call must come from governor.' ); }); @@ -417,9 +417,9 @@ describe('MarketUpdateTimelock', function() { } = await makeConfigurator(); await expect( - marketUpdateTimelock.connect(marketUpdateMultiSig).setAdmin(bob.address) + marketUpdateTimelock.connect(marketUpdateMultiSig).setGovernor(bob.address) ).to.be.revertedWith( - 'MarketUpdateTimelock::setAdmin: Call must come from admin.' + 'MarketUpdateTimelock::setGovernor: Call must come from governor.' ); }); }); \ No newline at end of file diff --git a/test/marketupdates/market-updates-helper.ts b/test/marketupdates/market-updates-helper.ts index 85fa0515..46d9c74d 100644 --- a/test/marketupdates/market-updates-helper.ts +++ b/test/marketupdates/market-updates-helper.ts @@ -9,38 +9,19 @@ import { ethers, expect } from './../helpers'; export async function makeMarketAdmin() { const { governorTimelockSigner: governorTimelockSigner, - governorTimelock: governorTimelock, } = await initializeAndFundGovernorTimelock(); const signers = await ethers.getSigners(); - const marketUpdateMultiSig = signers[3]; - - const marketUpdaterProposerFactory = (await ethers.getContractFactory( - 'MarketUpdateProposer' - )) as MarketUpdateProposer__factory; - - // Fund the impersonated account - await signers[0].sendTransaction({ - to: marketUpdateMultiSig.address, - value: ethers.utils.parseEther('1.0'), // Sending 1 Ether to cover gas fees - }); - - // This sets the owner of the MarketUpdateProposer to the marketUpdateMultiSig - const marketUpdateProposer = await marketUpdaterProposerFactory - .connect(marketUpdateMultiSig) - .deploy(); - - expect(await marketUpdateProposer.owner()).to.be.equal( - marketUpdateMultiSig.address - ); - + const marketUpdateMultiSig = signers[10]; + const pauseGuardianSigner = signers[11]; + const marketAdminTimelockFactory = (await ethers.getContractFactory( 'MarketUpdateTimelock' )) as MarketUpdateTimelock__factory; const marketUpdateTimelock = await marketAdminTimelockFactory.deploy( - governorTimelock.address, + governorTimelockSigner.address, 2 * 24 * 60 * 60 // This is 2 days in seconds ); const marketUpdateTimelockAddress = await marketUpdateTimelock.deployed(); @@ -62,9 +43,23 @@ export async function makeMarketAdmin() { marketUpdateTimelockAddress.address ); - marketUpdateProposer - .connect(marketUpdateMultiSig) - .initialize(marketUpdateTimelock.address); + const marketUpdaterProposerFactory = (await ethers.getContractFactory( + 'MarketUpdateProposer' + )) as MarketUpdateProposer__factory; + + // Fund the impersonated account + await signers[0].sendTransaction({ + to: marketUpdateMultiSig.address, + value: ethers.utils.parseEther('1.0'), // Sending 1 Ether to cover gas fees + }); + + // This sets the owner of the MarketUpdateProposer to the marketUpdateMultiSig + const marketUpdateProposer = await marketUpdaterProposerFactory + .deploy(governorTimelockSigner.address, marketUpdateMultiSig.address, pauseGuardianSigner.address, marketUpdateTimelock.address); + + expect(await marketUpdateProposer.governor()).to.be.equal( + governorTimelockSigner.address + ); await marketUpdateTimelock .connect(governorTimelockSigner) @@ -72,8 +67,8 @@ export async function makeMarketAdmin() { return { governorTimelockSigner, - governorTimelock, marketUpdateMultiSig, + pauseGuardianSigner, marketUpdateTimelock, marketUpdateTimelockSigner, marketUpdateProposer, From 66a69c7d58be6aa75c7a57227c72f3ebc19b922f Mon Sep 17 00:00:00 2001 From: Muhammad Sami Tariq <68412933+MSamiTariq@users.noreply.github.com> Date: Thu, 19 Sep 2024 20:15:32 +0500 Subject: [PATCH 06/28] Changed pause guardian to proposal guardian (#34) --- contracts/CometProxyAdmin.sol | 32 +-- contracts/Configurator.sol | 117 +++++----- .../marketupdates/MarketUpdateProposer.sol | 101 +++++---- .../marketupdates/MarketUpdateTimelock.sol | 45 ++-- .../market-update-proposer-test.ts | 140 +++++++----- .../market-update-timelock-test.ts | 209 ++++++++++-------- test/marketupdates/market-updates-helper.ts | 12 +- 7 files changed, 360 insertions(+), 296 deletions(-) diff --git a/contracts/CometProxyAdmin.sol b/contracts/CometProxyAdmin.sol index 37f21ed0..8ea158e6 100644 --- a/contracts/CometProxyAdmin.sol +++ b/contracts/CometProxyAdmin.sol @@ -17,8 +17,8 @@ contract CometProxyAdmin is ProxyAdmin { /// @notice address of the market admin pause guardian. We don't use `pauseGuardian` because we have `setPauseGuardian` which sets the pauseGuardian on comet. address public marketAdminPauseGuardian; - event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); event MarketAdminPaused(address indexed caller, bool isMarketAdminPaused); + event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); event SetMarketAdminPauseGuardian( address indexed oldPauseGuardian, address indexed newPauseGuardian @@ -55,6 +55,21 @@ contract CometProxyAdmin is ProxyAdmin { emit SetMarketAdmin(oldAdmin, newAdmin); } + /** + * @notice Sets a new market admin pause guardian. + * @dev Can only be called by the owner. Reverts with Unauthorized if the caller is not the owner. + * @param newPauseGuardian The address of the new market admin pause guardian. + * Note that there is no enforced zero address check on `newPauseGuadian` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the pause guadian. + */ + function setMarketAdminPauseGuardian(address newPauseGuardian) external { + if (msg.sender != owner()) revert Unauthorized(); + address oldPauseGuardian = marketAdminPauseGuardian; + marketAdminPauseGuardian = newPauseGuardian; + emit SetMarketAdminPauseGuardian(oldPauseGuardian, newPauseGuardian); + } + /** * @notice Pauses the market admin role. * @dev Can only be called by the owner or the market admin pause guardian. @@ -79,21 +94,6 @@ contract CometProxyAdmin is ProxyAdmin { emit MarketAdminPaused(msg.sender, false); } - /** - * @notice Sets a new market admin pause guardian. - * @dev Can only be called by the owner. Reverts with Unauthorized if the caller is not the owner. - * @param newPauseGuardian The address of the new market admin pause guardian. - * Note that there is no enforced zero address check on `newPauseGuadian` as it may be a deliberate choice - * to assign the zero address in certain scenarios. This design allows flexibility if the zero address - * is intended to represent a specific state, such as temporarily disabling the pause guadian. - */ - function setMarketAdminPauseGuardian(address newPauseGuardian) external { - if (msg.sender != owner()) revert Unauthorized(); - address oldPauseGuardian = marketAdminPauseGuardian; - marketAdminPauseGuardian = newPauseGuardian; - emit SetMarketAdminPauseGuardian(oldPauseGuardian, newPauseGuardian); - } - /** * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy * Requirements: diff --git a/contracts/Configurator.sol b/contracts/Configurator.sol index dd177cc4..231c854a 100644 --- a/contracts/Configurator.sol +++ b/contracts/Configurator.sol @@ -11,6 +11,7 @@ contract Configurator is ConfiguratorStorage { event AddAsset(address indexed cometProxy, AssetConfig assetConfig); event CometDeployed(address indexed cometProxy, address indexed newComet); event GovernorTransferred(address indexed oldGovernor, address indexed newGovernor); + event MarketAdminPaused(address indexed caller, bool isMarketAdminPaused); event SetFactory(address indexed cometProxy, address indexed oldFactory, address indexed newFactory); event SetGovernor(address indexed cometProxy, address indexed oldGovernor, address indexed newGovernor); event SetConfiguration(address indexed cometProxy, Configuration oldConfiguration, Configuration newConfiguration); @@ -31,6 +32,8 @@ contract Configurator is ConfiguratorStorage { event SetBaseMinForRewards(address indexed cometProxy, uint104 oldBaseMinForRewards, uint104 newBaseMinForRewards); event SetBaseBorrowMin(address indexed cometProxy, uint104 oldBaseBorrowMin, uint104 newBaseBorrowMin); event SetTargetReserves(address indexed cometProxy, uint104 oldTargetReserves, uint104 newTargetReserves); + event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); + event SetMarketAdminPauseGuardian(address indexed oldPauseGuardian, address indexed newPauseGuardian); event UpdateAsset(address indexed cometProxy, AssetConfig oldAssetConfig, AssetConfig newAssetConfig); event UpdateAssetPriceFeed(address indexed cometProxy, address indexed asset, address oldPriceFeed, address newPriceFeed); event UpdateAssetBorrowCollateralFactor(address indexed cometProxy, address indexed asset, uint64 oldBorrowCF, uint64 newBorrowCF); @@ -38,10 +41,6 @@ contract Configurator is ConfiguratorStorage { event UpdateAssetLiquidationFactor(address indexed cometProxy, address indexed asset, uint64 oldLiquidationFactor, uint64 newLiquidationFactor); event UpdateAssetSupplyCap(address indexed cometProxy, address indexed asset, uint128 oldSupplyCap, uint128 newSupplyCap); - event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); - event MarketAdminPaused(address indexed caller, bool isMarketAdminPaused); - event SetMarketAdminPauseGuardian(address indexed oldPauseGuardian, address indexed newPauseGuardian); - /** Custom errors **/ error AlreadyInitialized(); error AssetDoesNotExist(); @@ -83,61 +82,6 @@ contract Configurator is ConfiguratorStorage { version = 1; } - /** - * @notice Sets a new market admin. - * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the governor. - * Emits an event with the old and new market admin addresses. - * Note that there is no enforced zero address check on `newMarketAdmin` as it may be a deliberate choice - * to assign the zero address in certain scenarios. This design allows flexibility if the zero address - * is intended to represent a specific state, such as temporarily disabling the market admin role. - * @param newMarketAdmin The address of the new market admin. - */ - function setMarketAdmin(address newMarketAdmin) external { - if (msg.sender != governor) revert Unauthorized(); - address oldMarketAdmin = marketAdmin; - marketAdmin = newMarketAdmin; - emit SetMarketAdmin(oldMarketAdmin, newMarketAdmin); - } - - /** - * @notice Pauses the market admin role. - * @dev Can only be called by the governor or the market admin pause guardian. - * Reverts with Unauthorized if the caller is neither. - */ - function pauseMarketAdmin() external { - if (marketAdminPaused) revert AlreadyPaused(); - if (msg.sender != governor && msg.sender != marketAdminPauseGuardian) revert Unauthorized(); - marketAdminPaused = true; - emit MarketAdminPaused(msg.sender, true); - } - - /** - * @notice Unpauses the market admin role. - * @dev Can only be called by the governor. - * Reverts with Unauthorized if the caller is not the governor. - */ - function unpauseMarketAdmin() external { - if (!marketAdminPaused) revert AlreadyUnPaused(); - if (msg.sender != governor) revert Unauthorized(); - marketAdminPaused = false; - emit MarketAdminPaused(msg.sender, false); - } - - /** - * @notice Sets a new market admin pause guardian. - * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the owner. - * @param newPauseGuardian The address of the new market admin pause guardian. - * Note that there is no enforced zero address check on `newPauseGuadian` as it may be a deliberate choice - * to assign the zero address in certain scenarios. This design allows flexibility if the zero address - * is intended to represent a specific state, such as temporarily disabling the pause guadian. - */ - function setMarketAdminPauseGuardian(address newPauseGuardian) external { - if (msg.sender != governor) revert Unauthorized(); - address oldPauseGuardian = marketAdminPauseGuardian; - marketAdminPauseGuardian = newPauseGuardian; - emit SetMarketAdminPauseGuardian(oldPauseGuardian, newPauseGuardian); - } - /** * @notice Sets the factory for a Comet proxy * @dev Note: Only callable by governor @@ -289,6 +233,61 @@ contract Configurator is ConfiguratorStorage { emit SetTargetReserves(cometProxy, oldTargetReserves, newTargetReserves); } + /** + * @notice Sets a new market admin. + * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the governor. + * Emits an event with the old and new market admin addresses. + * Note that there is no enforced zero address check on `newMarketAdmin` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the market admin role. + * @param newMarketAdmin The address of the new market admin. + */ + function setMarketAdmin(address newMarketAdmin) external { + if (msg.sender != governor) revert Unauthorized(); + address oldMarketAdmin = marketAdmin; + marketAdmin = newMarketAdmin; + emit SetMarketAdmin(oldMarketAdmin, newMarketAdmin); + } + + /** + * @notice Sets a new market admin pause guardian. + * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the owner. + * @param newPauseGuardian The address of the new market admin pause guardian. + * Note that there is no enforced zero address check on `newPauseGuadian` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the pause guadian. + */ + function setMarketAdminPauseGuardian(address newPauseGuardian) external { + if (msg.sender != governor) revert Unauthorized(); + address oldPauseGuardian = marketAdminPauseGuardian; + marketAdminPauseGuardian = newPauseGuardian; + emit SetMarketAdminPauseGuardian(oldPauseGuardian, newPauseGuardian); + } + + /** + * @notice Pauses the market admin role. + * @dev Can only be called by the governor or the market admin pause guardian. + * Reverts with Unauthorized if the caller is neither. + */ + function pauseMarketAdmin() external { + if (marketAdminPaused) revert AlreadyPaused(); + if (msg.sender != governor && msg.sender != marketAdminPauseGuardian) revert Unauthorized(); + marketAdminPaused = true; + emit MarketAdminPaused(msg.sender, true); + } + + /** + * @notice Unpauses the market admin role. + * @dev Can only be called by the governor. + * Reverts with Unauthorized if the caller is not the governor. + */ + function unpauseMarketAdmin() external { + if (!marketAdminPaused) revert AlreadyUnPaused(); + if (msg.sender != governor) revert Unauthorized(); + marketAdminPaused = false; + emit MarketAdminPaused(msg.sender, false); + } + function addAsset(address cometProxy, AssetConfig calldata assetConfig) external { if (msg.sender != governor) revert Unauthorized(); diff --git a/contracts/marketupdates/MarketUpdateProposer.sol b/contracts/marketupdates/MarketUpdateProposer.sol index 9ff643c4..6794e611 100644 --- a/contracts/marketupdates/MarketUpdateProposer.sol +++ b/contracts/marketupdates/MarketUpdateProposer.sol @@ -7,12 +7,15 @@ import "./../ITimelock.sol"; * @title MarketUpdateProposer * @notice This contract allows for the creation of proposals that can be executed by the timelock * @dev This contract is used to propose market updates -* Here owner will be the market update multi-sig. The owner can set the new owner by calling `transferOwnership`. -* If multi-sig is compromised, the new owner will only be able to call timelock. marketUpdatePauseGuardian in -* Configurator or CometProxyAdmin can pause these updated. +* Few important points to note: +* 1) The marketAdmin can propose updates. The marketAdmin can be set by the governor. marketAdmin will be a multi-sig. +* 2) Here governor is the main-governor-timelock. This terminology(using governor as variable for timelock) is for +* consistency with Configurator.sol. +* 3) If marketAdmin/multi-sig is compromised, the new marketAdmin can be set by the governor. +* 4) While the marketAdmin/multi-sig is compromised, the new marketAdmin can propose updates. But those updates will be +* sent to timelock and can be paused by the marketAdminPauseGuardian Configurator and CometProxyAdmin. +* 5) The proposalGuardian can also be used for the same purpose and can cancel the proposal. * -* Other logic can be that only main-governor-timelock can update the owner of this contract, but that logic can be an -* overkill * */ contract MarketUpdateProposer { @@ -55,7 +58,7 @@ contract MarketUpdateProposer { } address public governor; - address public pauseGuardian; + address public proposalGuardian; address public marketAdmin; ITimelock public timelock; @@ -64,31 +67,31 @@ contract MarketUpdateProposer { /// @notice The total number of proposals uint public proposalCount; - /// @notice Initial proposal id set at become + /// @notice The initial proposal ID, set when the contract is deployed uint public initialProposalId = 0; /// @notice An event emitted when a new proposal is created event MarketUpdateProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, string description); event MarketUpdateProposalExecuted(uint id); event MarketUpdateProposalCancelled(uint id); - event SetPauseGuardian(address indexed oldPauseGuardian, address indexed newPauseGuardian); + event SetProposalGuardian(address indexed oldProposalGuardian, address indexed newProposalGuardian); event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); event SetGovernor(address indexed oldGovernor, address indexed newGovernor); error Unauthorized(); error InvalidAddress(); - constructor(address governor_, address marketAdmin_, address pauseGuardian_, ITimelock timelock_) public { + constructor(address governor_, address marketAdmin_, address proposalGuardian_, ITimelock timelock_) public { if (address(governor_) == address(0) || address(marketAdmin_) == address(0) || address(timelock_) == address(0)) revert InvalidAddress(); governor = governor_; marketAdmin = marketAdmin_; - pauseGuardian = pauseGuardian_; + proposalGuardian = proposalGuardian_; timelock = timelock_; } /** * @notice Transfers the governor rights to a new address - * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the owner. + * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the governor. * Emits an event with the old and new governor addresses. * @param newGovernor The address of the new governor. */ @@ -102,19 +105,19 @@ contract MarketUpdateProposer { } /** - * @notice Sets a new pause guardian. + * @notice Sets a new proposalGuardian. * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the owner. - * Emits an event with the old and new pause guardian addresses. - * Note that there is no enforced zero address check on `newPauseGuadian` as it may be a deliberate choice + * Emits an event with the old and new proposalGuardian addresses. + * Note that there is no enforced zero address check on `newProposalGuardian` as it may be a deliberate choice * to assign the zero address in certain scenarios. This design allows flexibility if the zero address - * is intended to represent a specific state, such as temporarily disabling the pause guadian. - * @param newPauseGuardian The address of the new market admin pause guardian. + * is intended to represent a specific state, such as temporarily disabling the proposalGuardian. + * @param newProposalGuardian The address of the new market admin proposalGuardian. */ - function setPauseGuardian(address newPauseGuardian) external { + function setProposalGuardian(address newProposalGuardian) external { if (msg.sender != governor) revert Unauthorized(); - address oldPauseGuardian = pauseGuardian; - pauseGuardian = newPauseGuardian; - emit SetPauseGuardian(oldPauseGuardian, newPauseGuardian); + address oldProposalGuardian = proposalGuardian; + proposalGuardian = newProposalGuardian; + emit SetProposalGuardian(oldProposalGuardian, newProposalGuardian); } /** @@ -188,11 +191,11 @@ contract MarketUpdateProposer { } /** - * @notice Cancels a proposal only if sender is the proposer, or proposer delegates dropped below proposal threshold + * @notice Cancels a proposal only if sender is the proposer, proposalGuardian, or marketAdmin, and the proposal is not already executed * @param proposalId The id of the proposal to cancel */ function cancel(uint proposalId) external { - if (msg.sender != governor && msg.sender != pauseGuardian && msg.sender != marketAdmin) revert Unauthorized(); + if (msg.sender != governor && msg.sender != proposalGuardian && msg.sender != marketAdmin) revert Unauthorized(); require(state(proposalId) != ProposalState.Executed, "MarketUpdateProposer::cancel: cannot cancel executed proposal"); MarketUpdateProposal storage proposal = proposals[proposalId]; @@ -226,31 +229,31 @@ contract MarketUpdateProposer { } function getProposal(uint proposalId) public view - returns ( - uint id, - address proposer, - uint eta, - address[] memory targets, - uint[] memory values, - string[] memory signatures, - bytes[] memory calldatas, - string memory description, - bool canceled, - bool executed - ) - { - MarketUpdateProposal storage proposal = proposals[proposalId]; - return ( - proposal.id, - proposal.proposer, - proposal.eta, - proposal.targets, - proposal.values, - proposal.signatures, - proposal.calldatas, - proposal.description, - proposal.canceled, - proposal.executed - ); - } + returns ( + uint id, + address proposer, + uint eta, + address[] memory targets, + uint[] memory values, + string[] memory signatures, + bytes[] memory calldatas, + string memory description, + bool canceled, + bool executed + ) + { + MarketUpdateProposal storage proposal = proposals[proposalId]; + return ( + proposal.id, + proposal.proposer, + proposal.eta, + proposal.targets, + proposal.values, + proposal.signatures, + proposal.calldatas, + proposal.description, + proposal.canceled, + proposal.executed + ); + } } diff --git a/contracts/marketupdates/MarketUpdateTimelock.sol b/contracts/marketupdates/MarketUpdateTimelock.sol index e0487889..e3f83a93 100644 --- a/contracts/marketupdates/MarketUpdateTimelock.sol +++ b/contracts/marketupdates/MarketUpdateTimelock.sol @@ -1,21 +1,17 @@ // SPDX-License-Identifier: BSD-3-Clause pragma solidity 0.8.15; -/* - -Right now governor and marketUpdateProposer can cancel one another's transactions, but -this is not a realistic scenario as governor is the main-governor-timelock which will not be -queuing, executing, or cancelling transactions. So we are not handling or testing it. +/** +* @title MarketUpdateTimelock +* @notice This contract allows for the execution of transactions after a delay and a proposal mechanism. +* @dev This contract is used for the market updates. The market updates are proposed by the marketAdmin. +* Few important points to note: +* 1) The call to queue, cancel, and execute transaction functions should come from the marketUpdateProposer. +* 2) The marketUpdateProposer can only be set by the governor. +* */ -contract MarketUpdateTimelock { - - event SetGovernor(address indexed oldGovernor, address indexed newGovernor); - event SetMarketUpdateProposer(address indexed oldMarketAdmin, address indexed newMarketAdmin); - event SetDelay(uint indexed newDelay); - event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); - event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); - event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); +contract MarketUpdateTimelock { uint public constant GRACE_PERIOD = 14 days; uint public constant MINIMUM_DELAY = 2 days; uint public constant MAXIMUM_DELAY = 30 days; @@ -24,12 +20,14 @@ contract MarketUpdateTimelock { address public marketUpdateProposer; uint public delay; - mapping (bytes32 => bool) public queuedTransactions; + mapping(bytes32 => bool) public queuedTransactions; - modifier governorOrMarketUpdater { - require(msg.sender == governor || msg.sender == marketUpdateProposer, "MarketUpdateTimelock::Unauthorized: call must come from governor or marketAdmin"); - _; - } + event SetGovernor(address indexed oldGovernor, address indexed newGovernor); + event SetMarketUpdateProposer(address indexed oldMarketAdmin, address indexed newMarketAdmin); + event SetDelay(uint indexed newDelay); + event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); + event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); + event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); constructor(address governor_, uint delay_) public { require(delay_ >= MINIMUM_DELAY, "MarketUpdateTimelock::constructor: Delay must exceed minimum delay."); @@ -43,7 +41,7 @@ contract MarketUpdateTimelock { function setDelay(uint delay_) public { - require(msg.sender == address(this), "MarketUpdateTimelock::setDelay: Call must come from Timelock."); + require(msg.sender == governor, "MarketUpdateTimelock::setDelay: Call must come from the Main Governor Timelock."); require(delay_ >= MINIMUM_DELAY, "MarketUpdateTimelock::setDelay: Delay must exceed minimum delay."); require(delay_ <= MAXIMUM_DELAY, "MarketUpdateTimelock::setDelay: Delay must not exceed maximum delay."); delay = delay_; @@ -65,7 +63,8 @@ contract MarketUpdateTimelock { emit SetMarketUpdateProposer(oldMarketUpdateProposer, newMarketUpdateProposer); } - function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public governorOrMarketUpdater returns (bytes32) { + function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) { + require(msg.sender == marketUpdateProposer, "MarketUpdateTimelock::queueTransaction: Call must come from marketUpdateProposer."); require(eta >= getBlockTimestamp() + delay, "MarketUpdateTimelock::queueTransaction: Estimated execution block must satisfy delay."); bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); @@ -75,14 +74,16 @@ contract MarketUpdateTimelock { return txHash; } - function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public governorOrMarketUpdater { + function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public { + require(msg.sender == marketUpdateProposer, "MarketUpdateTimelock::cancelTransaction: Call must come from marketUpdateProposer."); bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); queuedTransactions[txHash] = false; emit CancelTransaction(txHash, target, value, signature, data, eta); } - function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable governorOrMarketUpdater returns (bytes memory) { + function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) { + require(msg.sender == marketUpdateProposer, "MarketUpdateTimelock::executeTransaction: Call must come from marketUpdateProposer."); bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); require(queuedTransactions[txHash], "MarketUpdateTimelock::executeTransaction: Transaction hasn't been queued."); require(getBlockTimestamp() >= eta, "MarketUpdateTimelock::executeTransaction: Transaction hasn't surpassed time lock."); diff --git a/test/marketupdates/market-update-proposer-test.ts b/test/marketupdates/market-update-proposer-test.ts index 537b8c57..fdb3064e 100644 --- a/test/marketupdates/market-update-proposer-test.ts +++ b/test/marketupdates/market-update-proposer-test.ts @@ -53,7 +53,7 @@ describe('MarketUpdateProposer', function() { ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); }); - it('only GovernorTimelock can set a new pause guardian for MarketUpdateProposer', async () => { + it('only GovernorTimelock can set a new proposalGuardian for MarketUpdateProposer', async () => { const { governorTimelockSigner, marketUpdateProposer, @@ -69,12 +69,12 @@ describe('MarketUpdateProposer', function() { await marketUpdateProposer .connect(governorTimelockSigner) - .setPauseGuardian(alice.address); + .setProposalGuardian(alice.address); - expect(await marketUpdateProposer.pauseGuardian()).to.equal(alice.address); + expect(await marketUpdateProposer.proposalGuardian()).to.equal(alice.address); await expect( - marketUpdateProposer.connect(bob).setPauseGuardian(alice.address) + marketUpdateProposer.connect(bob).setProposalGuardian(alice.address) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); }); @@ -280,8 +280,8 @@ describe('MarketUpdateProposer', function() { const { governorTimelockSigner, marketUpdateMultiSig, - pauseGuardianSigner, - marketUpdateTimelock + proposalGuardianSigner, + marketUpdateTimelock, } = await makeMarketAdmin(); const marketUpdaterProposerFactory = (await ethers.getContractFactory( @@ -289,36 +289,66 @@ describe('MarketUpdateProposer', function() { )) as MarketUpdateProposer__factory; // Governor as zero address - await expect(marketUpdaterProposerFactory - .deploy(ethers.constants.AddressZero, marketUpdateMultiSig.address, pauseGuardianSigner.address, marketUpdateTimelock.address)) - .to.be.revertedWithCustomError(marketUpdaterProposerFactory, 'InvalidAddress'); + await expect( + marketUpdaterProposerFactory.deploy( + ethers.constants.AddressZero, + marketUpdateMultiSig.address, + proposalGuardianSigner.address, + marketUpdateTimelock.address + ) + ).to.be.revertedWithCustomError( + marketUpdaterProposerFactory, + 'InvalidAddress' + ); // Market admin as zero address - await expect(marketUpdaterProposerFactory - .deploy(governorTimelockSigner.address, ethers.constants.AddressZero, pauseGuardianSigner.address, marketUpdateTimelock.address)) - .to.be.revertedWithCustomError(marketUpdaterProposerFactory, 'InvalidAddress'); + await expect( + marketUpdaterProposerFactory.deploy( + governorTimelockSigner.address, + ethers.constants.AddressZero, + proposalGuardianSigner.address, + marketUpdateTimelock.address + ) + ).to.be.revertedWithCustomError( + marketUpdaterProposerFactory, + 'InvalidAddress' + ); - await expect(marketUpdaterProposerFactory - .deploy(governorTimelockSigner.address, marketUpdateMultiSig.address, pauseGuardianSigner.address, ethers.constants.AddressZero)) - .to.be.revertedWithCustomError(marketUpdaterProposerFactory, 'InvalidAddress'); + await expect( + marketUpdaterProposerFactory.deploy( + governorTimelockSigner.address, + marketUpdateMultiSig.address, + proposalGuardianSigner.address, + ethers.constants.AddressZero + ) + ).to.be.revertedWithCustomError( + marketUpdaterProposerFactory, + 'InvalidAddress' + ); - const marketUpdateProposer = await marketUpdaterProposerFactory - .deploy(governorTimelockSigner.address, marketUpdateMultiSig.address, pauseGuardianSigner.address, marketUpdateTimelock.address); + const marketUpdateProposer = await marketUpdaterProposerFactory.deploy( + governorTimelockSigner.address, + marketUpdateMultiSig.address, + proposalGuardianSigner.address, + marketUpdateTimelock.address + ); expect(await marketUpdateProposer.governor()).to.be.equal(governorTimelockSigner.address); expect(await marketUpdateProposer.marketAdmin()).to.be.equal(marketUpdateMultiSig.address); - expect(await marketUpdateProposer.pauseGuardian()).to.be.equal(pauseGuardianSigner.address); + expect(await marketUpdateProposer.proposalGuardian()).to.be.equal( + proposalGuardianSigner.address + ); expect(await marketUpdateProposer.timelock()).to.be.equal(marketUpdateTimelock.address); }); it('only governor can update a governor', async () => { - // include checks for pauseGuardian, marketAdmin, and nonGovernor for failure scenario + // include checks for proposalGuardian, marketAdmin, and nonGovernor for failure scenario const { governorTimelockSigner, marketUpdateProposer, marketUpdateMultiSig, - pauseGuardianSigner, + proposalGuardianSigner, } = await makeMarketAdmin(); const { @@ -339,9 +369,11 @@ describe('MarketUpdateProposer', function() { marketUpdateProposer.connect(marketUpdateMultiSig).setGovernor(alice.address) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); - // failure case: pause guardian cannot update the governor + // failure case: proposalGuardian cannot update the governor await expect( - marketUpdateProposer.connect(pauseGuardianSigner).setGovernor(alice.address) + marketUpdateProposer + .connect(proposalGuardianSigner) + .setGovernor(alice.address) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); // failure case: Non-governor cannot update the governor @@ -349,13 +381,14 @@ describe('MarketUpdateProposer', function() { marketUpdateProposer.connect(bob).setGovernor(alice.address) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); }); + it('only governor can update a marketAdmin', async () => { - // include checks for pauseGuardian, marketAdmin, and nonGovernor for failure scenario + // include checks for proposalGuardian, marketAdmin, and nonGovernor for failure scenario const { governorTimelockSigner, marketUpdateProposer, marketUpdateMultiSig, - pauseGuardianSigner, + proposalGuardianSigner, } = await makeMarketAdmin(); const { @@ -376,9 +409,11 @@ describe('MarketUpdateProposer', function() { marketUpdateProposer.connect(marketUpdateMultiSig).setMarketAdmin(alice.address) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); - // failure case: pause guardian cannot update the market admin + // failure case: proposalGuardian cannot update the market admin await expect( - marketUpdateProposer.connect(pauseGuardianSigner).setMarketAdmin(alice.address) + marketUpdateProposer + .connect(proposalGuardianSigner) + .setMarketAdmin(alice.address) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); // failure case: Non-governor cannot update the market admin @@ -386,8 +421,9 @@ describe('MarketUpdateProposer', function() { marketUpdateProposer.connect(bob).setGovernor(alice.address) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); }); - it('only governor can update a pauseGuardian', async () => { - // include checks for pauseGuardian, marketAdmin, and nonGovernor for failure scenario + + it('only governor can update a proposalGuardian', async () => { + // include checks for proposalGuardian, marketAdmin, and nonGovernor for failure scenario const { governorTimelockSigner, marketUpdateProposer, @@ -400,37 +436,37 @@ describe('MarketUpdateProposer', function() { expect(await marketUpdateProposer.governor()).to.be.equal(governorTimelockSigner.address); - // Ensure only the governor can set a new pause guardian + // Ensure only the governor can set a new proposalGuardian await marketUpdateProposer .connect(governorTimelockSigner) - .setPauseGuardian(alice.address); + .setProposalGuardian(alice.address); - expect(await marketUpdateProposer.pauseGuardian()).to.equal(alice.address); + expect(await marketUpdateProposer.proposalGuardian()).to.equal(alice.address); - // failure case: market admin cannot update the pause guardian + // failure case: market admin cannot update the proposalGuardian await expect( - marketUpdateProposer.connect(marketUpdateMultiSig).setPauseGuardian(bob.address) + marketUpdateProposer.connect(marketUpdateMultiSig).setProposalGuardian(bob.address) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); - // failure case: pause guardian cannot update the pause guardian - // alice is the pause guardian by the above governor call + // failure case: proposalGuardian cannot update the proposalGuardian + // alice is the proposalGuardian by the above governor call await expect( - marketUpdateProposer.connect(alice).setPauseGuardian(bob.address) + marketUpdateProposer.connect(alice).setProposalGuardian(bob.address) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); - // failure case: Non-governor cannot update the pause guardian + // failure case: Non-governor cannot update the proposalGuardian await expect( marketUpdateProposer.connect(john).setGovernor(alice.address) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); }); it('only marketAdmin can create a proposal', async () => { - // include checks for pauseGuardian, and governor, and anonymous address + // include checks for proposalGuardian, governor, and anonymous address const { governorTimelockSigner, marketUpdateProposer, marketUpdateMultiSig, - pauseGuardianSigner + proposalGuardianSigner, } = await makeMarketAdmin(); const { configuratorProxy, cometProxy, users: [alice] } = await makeConfigurator(); @@ -470,10 +506,10 @@ describe('MarketUpdateProposer', function() { ) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); - // Failure case: Pause guardian cannot create a proposal + // Failure case: proposalGuardian cannot create a proposal await expect( marketUpdateProposer - .connect(pauseGuardianSigner) + .connect(proposalGuardianSigner) .propose( [configuratorProxy.address], [0], @@ -498,13 +534,13 @@ describe('MarketUpdateProposer', function() { }); it('only marketAdmin can execute a proposal', async () => { - // include checks for pauseGuardian, marketAdmin, and governor, and anonymous address + // include checks for proposalGuardian, marketAdmin, governor, and anonymous address const { governorTimelockSigner, marketUpdateProposer, marketUpdateMultiSig, marketUpdateTimelock, - pauseGuardianSigner + proposalGuardianSigner, } = await makeMarketAdmin(); const { @@ -549,9 +585,9 @@ describe('MarketUpdateProposer', function() { marketUpdateProposer.connect(governorTimelockSigner).execute(proposalId) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); - // Failure case: Pause guardian cannot execute the proposal + // Failure case: proposalGuardian cannot execute the proposal await expect( - marketUpdateProposer.connect(pauseGuardianSigner).execute(proposalId) + marketUpdateProposer.connect(proposalGuardianSigner).execute(proposalId) ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); // Failure case: anonymous cannot execute the proposal @@ -566,13 +602,13 @@ describe('MarketUpdateProposer', function() { await marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId); }); - it('only marketAdmin, pauseGuardian, or governor can cancel a proposal', async () => { - // include checks for pauseGuardian, marketAdmin, and governor, and anonymous address + it('only marketAdmin, proposalGuardian, or governor can cancel a proposal', async () => { + // include checks for proposalGuardian, marketAdmin, and governor, and anonymous address const { governorTimelockSigner, marketUpdateProposer, marketUpdateMultiSig, - pauseGuardianSigner + proposalGuardianSigner, } = await makeMarketAdmin(); const { configuratorProxy, cometProxy, users: [bob] } = await makeConfigurator(); @@ -606,8 +642,12 @@ describe('MarketUpdateProposer', function() { // Success case: MarketAdmin can cancel the proposal await marketUpdateProposer.connect(marketUpdateMultiSig).cancel(proposalId); - // Success case: Pause guardian can cancel the proposal - expect(await marketUpdateProposer.connect(pauseGuardianSigner).cancel(proposalId)); + // Success case: proposalGuardian can cancel the proposal + expect( + await marketUpdateProposer + .connect(proposalGuardianSigner) + .cancel(proposalId) + ); // Failure case: anonymous cannot cancel the proposal await expect( diff --git a/test/marketupdates/market-update-timelock-test.ts b/test/marketupdates/market-update-timelock-test.ts index b3b913c7..246460d2 100644 --- a/test/marketupdates/market-update-timelock-test.ts +++ b/test/marketupdates/market-update-timelock-test.ts @@ -35,7 +35,8 @@ describe('MarketUpdateTimelock', function() { ); }); - it('only MarketUpdateProposer or main-governor-timelock can queue transactions', async () => { + it('only MarketUpdateProposer can queue transactions', async () => { + // include checks for marketAdmin, governor, and anonymous address const { marketUpdateTimelock, governorTimelockSigner, @@ -58,21 +59,7 @@ describe('MarketUpdateTimelock', function() { // Ensure eta is sufficiently in the future const eta = currentTimestamp + delay + 5; // eta is current timestamp + delay + a few seconds - // ensuring that main gover-timelock can queue transactions - await marketUpdateTimelock - .connect(governorTimelockSigner) - .queueTransaction( - configuratorProxy.address, - 0, - 'setSupplyKink(address, uint64)', - ethers.utils.defaultAbiCoder.encode( - ['address', 'uint64'], - [cometProxy.address, 100] - ), - eta - ); - - // ensuring that market update proposer can queue transactions + // Success case: market update proposer can queue transactions await marketUpdateProposer .connect(marketUpdateMultiSig) .propose( @@ -88,7 +75,25 @@ describe('MarketUpdateTimelock', function() { 'Setting supply kink to 100' ); - // ensuring that none other than the main-governor-timelock or MarketUpdateProposer can queue transactions + // Failure case: Main Governor Timelock cannot queue transactions + await expect( + marketUpdateTimelock + .connect(governorTimelockSigner) + .queueTransaction( + configuratorProxy.address, + 0, + 'setSupplyKink(address, uint64)', + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + eta + ) + ).to.be.revertedWith( + 'MarketUpdateTimelock::queueTransaction: Call must come from marketUpdateProposer.' + ); + + // Failure case: none other than MarketUpdateProposer can queue transactions await expect( marketUpdateTimelock .connect(bob) @@ -103,11 +108,11 @@ describe('MarketUpdateTimelock', function() { eta ) ).to.be.revertedWith( - 'MarketUpdateTimelock::Unauthorized: call must come from governor or marketAdmin' + 'MarketUpdateTimelock::queueTransaction: Call must come from marketUpdateProposer.' ); }); - it('only MarketUpdateProposer or main-governor-timelock can execute transactions', async () => { + it('only MarketUpdateProposer can execute transactions', async () => { const { marketUpdateTimelock, governorTimelockSigner, @@ -134,37 +139,7 @@ describe('MarketUpdateTimelock', function() { let eta = currentTimestamp + delay + 5; // Ensure eta is in the future - // ensuring that main gover-timelock can execute transactions - await marketUpdateTimelock - .connect(governorTimelockSigner) - .queueTransaction( - configuratorProxy.address, - 0, - 'setSupplyKink(address,uint64)', - ethers.utils.defaultAbiCoder.encode( - ['address', 'uint64'], - [cometProxy.address, 100000] - ), - eta - ); - - // Fast-forward time by delay + few seconds to surpass the eta - await advanceTimeAndMineBlock(delay); - - await marketUpdateTimelock - .connect(governorTimelockSigner) - .executeTransaction( - configuratorProxy.address, - 0, - 'setSupplyKink(address,uint64)', - ethers.utils.defaultAbiCoder.encode( - ['address', 'uint64'], - [cometProxy.address, 100000] - ), - eta - ); - - // ensuring that market update proposer can queue transactions + // Success case: market update proposer can execute transactions await marketUpdateProposer .connect(marketUpdateMultiSig) .propose( @@ -187,18 +162,34 @@ describe('MarketUpdateTimelock', function() { .connect(marketUpdateMultiSig) .execute(proposalId); - // ensuring that none other than the main-governor-timelock or MarketUpdateProposer can execute transactions + // Failure case: Main Governor Timelock cannot execute transactions - // first queuing a transaction latestBlock = await ethers.provider.getBlock('latest'); currentTimestamp = latestBlock.timestamp; eta = currentTimestamp + delay + 5; // Ensure eta is in the future - // ensuring that MarketUpdateProposer can execute transactions - await marketUpdateTimelock + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + ], + 'Setting supply kink to 100' + ); + + // Fast-forward time by delay + few seconds to surpass the eta + await advanceTimeAndMineBlock(delay); + + await expect(marketUpdateTimelock .connect(governorTimelockSigner) - .queueTransaction( + .executeTransaction( configuratorProxy.address, 0, 'setSupplyKink(address,uint64)', @@ -207,6 +198,29 @@ describe('MarketUpdateTimelock', function() { [cometProxy.address, 100000] ), eta + )).to.be.revertedWith('MarketUpdateTimelock::executeTransaction: Call must come from marketUpdateProposer.'); + + // Failure case: none other than MarketUpdateProposer can execute transactions + + // first queuing a transaction + latestBlock = await ethers.provider.getBlock('latest'); + currentTimestamp = latestBlock.timestamp; + + eta = currentTimestamp + delay + 5; // Ensure eta is in the future + + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + ], + 'Setting supply kink to 100' ); // Fast-forward time by delay + few seconds to surpass the eta @@ -226,11 +240,11 @@ describe('MarketUpdateTimelock', function() { eta ) ).to.be.revertedWith( - 'MarketUpdateTimelock::Unauthorized: call must come from governor or marketAdmin' + 'MarketUpdateTimelock::executeTransaction: Call must come from marketUpdateProposer.' ); }); - it('only MarketUpdateProposer or main-governor-timelock can cancel transactions', async () => { + it('only MarketUpdateProposer can cancel transactions', async () => { const { marketUpdateTimelock, governorTimelockSigner, @@ -258,34 +272,7 @@ describe('MarketUpdateTimelock', function() { let eta = currentTimestamp + delay + 5; // Ensure eta is in the future - // ensuring that main governor-timelock can cancel transactions - await marketUpdateTimelock - .connect(governorTimelockSigner) - .queueTransaction( - configuratorProxy.address, - 0, - 'setSupplyKink(address,uint64)', - ethers.utils.defaultAbiCoder.encode( - ['address', 'uint64'], - [cometProxy.address, 100000] - ), - eta - ); - - await marketUpdateTimelock - .connect(governorTimelockSigner) - .cancelTransaction( - configuratorProxy.address, - 0, - 'setSupplyKink(address,uint64)', - ethers.utils.defaultAbiCoder.encode( - ['address', 'uint64'], - [cometProxy.address, 100000] - ), - eta - ); - - // ensuring that MarketUpdateProposer can cancel transactions + // Success case: MarketUpdateProposer can cancel transactions await marketUpdateProposer .connect(marketUpdateMultiSig) .propose( @@ -324,18 +311,25 @@ describe('MarketUpdateTimelock', function() { false ); - // ensuring that none other than the main-governor-timelock or MarketUpdateProposer can execute transactions - - // first queuing a transaction - latestBlock = await ethers.provider.getBlock('latest'); - currentTimestamp = latestBlock.timestamp; - - eta = currentTimestamp + delay + 5; // Ensure eta is in the future + // Failure case: Main Governor Timelock cannot cancel transactions + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + ], + 'Setting supply kink to 100' + ); - // ensuring that MarketUpdateProposer can execute transactions - await marketUpdateTimelock + await expect(marketUpdateTimelock .connect(governorTimelockSigner) - .queueTransaction( + .cancelTransaction( configuratorProxy.address, 0, 'setSupplyKink(address,uint64)', @@ -344,6 +338,29 @@ describe('MarketUpdateTimelock', function() { [cometProxy.address, 100000] ), eta + )).to.be.revertedWith('MarketUpdateTimelock::cancelTransaction: Call must come from marketUpdateProposer.'); + + // Failure case: none other than MarketUpdateProposer can execute transactions + + // first queuing a transaction + latestBlock = await ethers.provider.getBlock('latest'); + currentTimestamp = latestBlock.timestamp; + + eta = currentTimestamp + delay + 5; // Ensure eta is in the future + + await marketUpdateProposer + .connect(marketUpdateMultiSig) + .propose( + [configuratorProxy.address], + [0], + ['setSupplyKink(address,uint64)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'uint64'], + [cometProxy.address, 100] + ), + ], + 'Setting supply kink to 100' ); await expect( @@ -360,7 +377,7 @@ describe('MarketUpdateTimelock', function() { eta ) ).to.be.revertedWith( - 'MarketUpdateTimelock::Unauthorized: call must come from governor or marketAdmin' + 'MarketUpdateTimelock::cancelTransaction: Call must come from marketUpdateProposer.' ); }); diff --git a/test/marketupdates/market-updates-helper.ts b/test/marketupdates/market-updates-helper.ts index 46d9c74d..785ac31f 100644 --- a/test/marketupdates/market-updates-helper.ts +++ b/test/marketupdates/market-updates-helper.ts @@ -14,7 +14,7 @@ export async function makeMarketAdmin() { const signers = await ethers.getSigners(); const marketUpdateMultiSig = signers[10]; - const pauseGuardianSigner = signers[11]; + const proposalGuardianSigner = signers[11]; const marketAdminTimelockFactory = (await ethers.getContractFactory( 'MarketUpdateTimelock' @@ -54,8 +54,12 @@ export async function makeMarketAdmin() { }); // This sets the owner of the MarketUpdateProposer to the marketUpdateMultiSig - const marketUpdateProposer = await marketUpdaterProposerFactory - .deploy(governorTimelockSigner.address, marketUpdateMultiSig.address, pauseGuardianSigner.address, marketUpdateTimelock.address); + const marketUpdateProposer = await marketUpdaterProposerFactory.deploy( + governorTimelockSigner.address, + marketUpdateMultiSig.address, + proposalGuardianSigner.address, + marketUpdateTimelock.address + ); expect(await marketUpdateProposer.governor()).to.be.equal( governorTimelockSigner.address @@ -68,7 +72,7 @@ export async function makeMarketAdmin() { return { governorTimelockSigner, marketUpdateMultiSig, - pauseGuardianSigner, + proposalGuardianSigner, marketUpdateTimelock, marketUpdateTimelockSigner, marketUpdateProposer, From 368842d1299b75ee6ba4cddb25c79b91a1bd9481 Mon Sep 17 00:00:00 2001 From: robin Date: Fri, 20 Sep 2024 10:19:07 -0400 Subject: [PATCH 07/28] Add separate permission checker and address other feedback --- contracts/CometProxyAdmin.sol | 105 ++---- contracts/Configurator.sol | 96 ++--- contracts/ConfiguratorStorage.sol | 11 +- .../MarketAdminPermissionChecker.sol | 91 +++++ .../MarketAdminPermissionCheckerInterface.sol | 22 ++ .../marketupdates/MarketUpdateProposer.sol | 2 +- deployments/localhost/dai/deploy.ts | 118 +++--- test/configurator-test.ts | 21 +- test/helpers.ts | 22 +- .../market-update-comet-proxy-admin-test.ts | 230 ++--------- .../market-update-configurator-test.ts | 357 +++++------------- .../market-update-deployment-test.ts | 148 +++++--- .../market-update-permission-checker-test.ts | 214 +++++++++++ .../market-update-proposer-test.ts | 251 ++++++------ .../market-update-timelock-test.ts | 84 ++--- test/marketupdates/market-updates-helper.ts | 70 +++- 16 files changed, 940 insertions(+), 902 deletions(-) create mode 100644 contracts/marketupdates/MarketAdminPermissionChecker.sol create mode 100644 contracts/marketupdates/MarketAdminPermissionCheckerInterface.sol create mode 100644 test/marketupdates/market-update-permission-checker-test.ts diff --git a/contracts/CometProxyAdmin.sol b/contracts/CometProxyAdmin.sol index 8ea158e6..866ff0ec 100644 --- a/contracts/CometProxyAdmin.sol +++ b/contracts/CometProxyAdmin.sol @@ -2,102 +2,33 @@ pragma solidity 0.8.15; import "./vendor/proxy/transparent/ProxyAdmin.sol"; +import "./marketupdates/MarketAdminPermissionCheckerInterface.sol"; interface Deployable { function deploy(address cometProxy) external returns (address); } contract CometProxyAdmin is ProxyAdmin { - /// @notice Pause flag for the market update admin - bool public marketAdminPaused; - /// @notice The address of the market update admin. This will be the address of a timelock contract. - address public marketAdmin; + /// @notice MarketAdminPermissionChecker contract which is used to check if the caller has permission to perform market updates(or deployment) + MarketAdminPermissionCheckerInterface public marketAdminPermissionChecker; - /// @notice address of the market admin pause guardian. We don't use `pauseGuardian` because we have `setPauseGuardian` which sets the pauseGuardian on comet. - address public marketAdminPauseGuardian; - - event MarketAdminPaused(address indexed caller, bool isMarketAdminPaused); - event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); - event SetMarketAdminPauseGuardian( - address indexed oldPauseGuardian, - address indexed newPauseGuardian - ); + event SetMarketAdminPermissionChecker(address indexed oldMarketAdminPermissionChecker, address indexed newMarketAdminPermissionChecker); error Unauthorized(); - error MarketAdminIsPaused(); - error AlreadyPaused(); - error AlreadyUnPaused(); /** - * @dev Throws if called by any account other than the owner and market update admin + * @dev Ensures that the caller is either the owner or the market admin. + * This delegates the permission check logic to the MarketAdminPermissionChecker contract. */ - modifier ownerOrMarketAdmin() { - // using revert instead of require to keep it consistent with other calls - if (owner() != _msgSender() && marketAdmin != _msgSender()) revert Unauthorized(); - // If the sender is the marketAdmin, check that the marketAdmin is not paused - if (_msgSender() == marketAdmin && marketAdminPaused) revert MarketAdminIsPaused(); + modifier ownerOrMarketAdmin { + if(_msgSender() != owner()) marketAdminPermissionChecker.checkUpdatePermission(_msgSender()); _; } - /** - * @notice Sets a new market admin for the contract. - * @dev This function can only be called by the owner of the contract. - * If the caller is not the owner, the function will revert with an Unauthorized error. - * Note that there is no enforced zero address check on `newAdmin` as it may be a deliberate choice - * to assign the zero address in certain scenarios. This design allows flexibility if the zero address - * is intended to represent a specific state, such as temporarily disabling the market admin role. - * @param newAdmin The address of the new market admin. - */ - function setMarketAdmin(address newAdmin) public { - address oldAdmin = marketAdmin; - if (msg.sender != owner()) revert Unauthorized(); - marketAdmin = newAdmin; - emit SetMarketAdmin(oldAdmin, newAdmin); - } - - /** - * @notice Sets a new market admin pause guardian. - * @dev Can only be called by the owner. Reverts with Unauthorized if the caller is not the owner. - * @param newPauseGuardian The address of the new market admin pause guardian. - * Note that there is no enforced zero address check on `newPauseGuadian` as it may be a deliberate choice - * to assign the zero address in certain scenarios. This design allows flexibility if the zero address - * is intended to represent a specific state, such as temporarily disabling the pause guadian. - */ - function setMarketAdminPauseGuardian(address newPauseGuardian) external { - if (msg.sender != owner()) revert Unauthorized(); - address oldPauseGuardian = marketAdminPauseGuardian; - marketAdminPauseGuardian = newPauseGuardian; - emit SetMarketAdminPauseGuardian(oldPauseGuardian, newPauseGuardian); - } - - /** - * @notice Pauses the market admin role. - * @dev Can only be called by the owner or the market admin pause guardian. - * Reverts with Unauthorized if the caller is neither. - */ - function pauseMarketAdmin() external { - if (marketAdminPaused) revert AlreadyPaused(); - if (msg.sender != owner() && msg.sender != marketAdminPauseGuardian) revert Unauthorized(); - marketAdminPaused = true; - emit MarketAdminPaused(msg.sender, true); - } - - /** - * @notice Unpauses the market admin role. - * @dev Can only be called by the owner. - * Reverts with Unauthorized if the caller is not the owner. - */ - function unpauseMarketAdmin() external { - if (!marketAdminPaused) revert AlreadyUnPaused(); - if (msg.sender != owner()) revert Unauthorized(); - marketAdminPaused = false; - emit MarketAdminPaused(msg.sender, false); - } - /** * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy * Requirements: - * - This contract must be the admin or market admin of `CometProxy` + * - This contract must be the admin of `CometProxy` */ function deployAndUpgradeTo(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy) public virtual ownerOrMarketAdmin { address newCometImpl = configuratorProxy.deploy(address(cometProxy)); @@ -107,7 +38,7 @@ contract CometProxyAdmin is ProxyAdmin { /** * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy, then call the function * Requirements: - * - This contract must be the admin or market admin of `CometProxy` + * - This contract must be the admin of `CometProxy` */ function deployUpgradeToAndCall(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy, bytes memory data) public virtual ownerOrMarketAdmin { address newCometImpl = configuratorProxy.deploy(address(cometProxy)); @@ -115,14 +46,26 @@ contract CometProxyAdmin is ProxyAdmin { } /** - * @dev Custom upgrade function that allows owner and marketUpdateAdmin to call it + * @notice Sets the MarketAdminPermissionChecker contract + * @dev Note: Only callable by main-governor-timelock + **/ + function setMarketAdminPermissionChecker(MarketAdminPermissionCheckerInterface newMarketAdminPermissionChecker) external { + if (_msgSender() != owner()) revert Unauthorized(); + address oldMarketAdminPermissionChecker = address(marketAdminPermissionChecker); + marketAdminPermissionChecker = newMarketAdminPermissionChecker; + emit SetMarketAdminPermissionChecker(oldMarketAdminPermissionChecker, address(newMarketAdminPermissionChecker)); + } + + + /** + * @dev Custom upgrade function that allows owner and marketAdmin to call it */ function _upgrade(TransparentUpgradeableProxy proxy, address implementation) private ownerOrMarketAdmin { proxy.upgradeTo(implementation); } /** - * @dev Custom upgradeAndCall function that allows owner and marketUpdateAdmin to call it + * @dev Custom upgradeAndCall function that allows owner and marketAdmin to call it */ function _upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) private ownerOrMarketAdmin { proxy.upgradeToAndCall(implementation, data); diff --git a/contracts/Configurator.sol b/contracts/Configurator.sol index 231c854a..374a753f 100644 --- a/contracts/Configurator.sol +++ b/contracts/Configurator.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.15; import "./CometFactory.sol"; import "./CometConfiguration.sol"; import "./ConfiguratorStorage.sol"; +import "./marketupdates/MarketAdminPermissionCheckerInterface.sol"; contract Configurator is ConfiguratorStorage { @@ -11,11 +12,11 @@ contract Configurator is ConfiguratorStorage { event AddAsset(address indexed cometProxy, AssetConfig assetConfig); event CometDeployed(address indexed cometProxy, address indexed newComet); event GovernorTransferred(address indexed oldGovernor, address indexed newGovernor); - event MarketAdminPaused(address indexed caller, bool isMarketAdminPaused); event SetFactory(address indexed cometProxy, address indexed oldFactory, address indexed newFactory); event SetGovernor(address indexed cometProxy, address indexed oldGovernor, address indexed newGovernor); event SetConfiguration(address indexed cometProxy, Configuration oldConfiguration, Configuration newConfiguration); event SetPauseGuardian(address indexed cometProxy, address indexed oldPauseGuardian, address indexed newPauseGuardian); + event SetMarketAdminPermissionChecker(address indexed oldMarketAdminPermissionChecker, address indexed newMarketAdminPermissionChecker); event SetBaseTokenPriceFeed(address indexed cometProxy, address indexed oldBaseTokenPriceFeed, address indexed newBaseTokenPriceFeed); event SetExtensionDelegate(address indexed cometProxy, address indexed oldExt, address indexed newExt); event SetSupplyKink(address indexed cometProxy,uint64 oldKink, uint64 newKink); @@ -32,8 +33,6 @@ contract Configurator is ConfiguratorStorage { event SetBaseMinForRewards(address indexed cometProxy, uint104 oldBaseMinForRewards, uint104 newBaseMinForRewards); event SetBaseBorrowMin(address indexed cometProxy, uint104 oldBaseBorrowMin, uint104 newBaseBorrowMin); event SetTargetReserves(address indexed cometProxy, uint104 oldTargetReserves, uint104 newTargetReserves); - event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); - event SetMarketAdminPauseGuardian(address indexed oldPauseGuardian, address indexed newPauseGuardian); event UpdateAsset(address indexed cometProxy, AssetConfig oldAssetConfig, AssetConfig newAssetConfig); event UpdateAssetPriceFeed(address indexed cometProxy, address indexed asset, address oldPriceFeed, address newPriceFeed); event UpdateAssetBorrowCollateralFactor(address indexed cometProxy, address indexed asset, uint64 oldBorrowCF, uint64 newBorrowCF); @@ -47,29 +46,24 @@ contract Configurator is ConfiguratorStorage { error ConfigurationAlreadyExists(); error InvalidAddress(); error Unauthorized(); - error MarketAdminIsPaused(); - error AlreadyPaused(); - error AlreadyUnPaused(); + + /** + * @notice Constructs a new Configurator instance + **/ + constructor() { + // Set a high version to prevent the implementation contract from being initialized + version = type(uint256).max; + } /** * @dev Ensures that the caller is either the governor or the market admin. - * Reverts with Unauthorized if the caller is neither. If the caller is the market admin, - * it also checks if the market admin is paused, reverting with MarketAdminIsPaused if so. - * Uses revert instead of require for consistency with other calls. + * This delegates the permission check logic to the MarketAdminPermissionChecker contract. */ modifier governorOrMarketAdmin { - // using revert instead of require to keep it consistent with other calls - if(msg.sender != governor && msg.sender != marketAdmin) revert Unauthorized(); - // If the sender is the marketAdmin, check that the market admin is not paused - if (msg.sender == marketAdmin && marketAdminPaused) revert MarketAdminIsPaused(); + if(msg.sender != governor) marketAdminPermissionChecker.checkUpdatePermission(msg.sender); _; } - constructor() { - // Set a high version to prevent the implementation contract from being initialized - version = type(uint256).max; - } - /** * @notice Initializes the storage for Configurator * @param governor_ The address of the governor @@ -127,6 +121,17 @@ contract Configurator is ConfiguratorStorage { emit SetPauseGuardian(cometProxy, oldPauseGuardian, newPauseGuardian); } + /** + * @notice Sets the MarketAdminPermissionChecker contract + * @dev Note: Only callable by governor + **/ + function setMarketAdminPermissionChecker(MarketAdminPermissionCheckerInterface newMarketAdminPermissionChecker) external { + if (msg.sender != governor) revert Unauthorized(); + address oldMarketAdminPermissionChecker = address(marketAdminPermissionChecker); + marketAdminPermissionChecker = newMarketAdminPermissionChecker; + emit SetMarketAdminPermissionChecker(oldMarketAdminPermissionChecker, address(newMarketAdminPermissionChecker)); + } + function setBaseTokenPriceFeed(address cometProxy, address newBaseTokenPriceFeed) external { if (msg.sender != governor) revert Unauthorized(); @@ -233,61 +238,6 @@ contract Configurator is ConfiguratorStorage { emit SetTargetReserves(cometProxy, oldTargetReserves, newTargetReserves); } - /** - * @notice Sets a new market admin. - * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the governor. - * Emits an event with the old and new market admin addresses. - * Note that there is no enforced zero address check on `newMarketAdmin` as it may be a deliberate choice - * to assign the zero address in certain scenarios. This design allows flexibility if the zero address - * is intended to represent a specific state, such as temporarily disabling the market admin role. - * @param newMarketAdmin The address of the new market admin. - */ - function setMarketAdmin(address newMarketAdmin) external { - if (msg.sender != governor) revert Unauthorized(); - address oldMarketAdmin = marketAdmin; - marketAdmin = newMarketAdmin; - emit SetMarketAdmin(oldMarketAdmin, newMarketAdmin); - } - - /** - * @notice Sets a new market admin pause guardian. - * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the owner. - * @param newPauseGuardian The address of the new market admin pause guardian. - * Note that there is no enforced zero address check on `newPauseGuadian` as it may be a deliberate choice - * to assign the zero address in certain scenarios. This design allows flexibility if the zero address - * is intended to represent a specific state, such as temporarily disabling the pause guadian. - */ - function setMarketAdminPauseGuardian(address newPauseGuardian) external { - if (msg.sender != governor) revert Unauthorized(); - address oldPauseGuardian = marketAdminPauseGuardian; - marketAdminPauseGuardian = newPauseGuardian; - emit SetMarketAdminPauseGuardian(oldPauseGuardian, newPauseGuardian); - } - - /** - * @notice Pauses the market admin role. - * @dev Can only be called by the governor or the market admin pause guardian. - * Reverts with Unauthorized if the caller is neither. - */ - function pauseMarketAdmin() external { - if (marketAdminPaused) revert AlreadyPaused(); - if (msg.sender != governor && msg.sender != marketAdminPauseGuardian) revert Unauthorized(); - marketAdminPaused = true; - emit MarketAdminPaused(msg.sender, true); - } - - /** - * @notice Unpauses the market admin role. - * @dev Can only be called by the governor. - * Reverts with Unauthorized if the caller is not the governor. - */ - function unpauseMarketAdmin() external { - if (!marketAdminPaused) revert AlreadyUnPaused(); - if (msg.sender != governor) revert Unauthorized(); - marketAdminPaused = false; - emit MarketAdminPaused(msg.sender, false); - } - function addAsset(address cometProxy, AssetConfig calldata assetConfig) external { if (msg.sender != governor) revert Unauthorized(); diff --git a/contracts/ConfiguratorStorage.sol b/contracts/ConfiguratorStorage.sol index 37ff6ae3..fabd9cb9 100644 --- a/contracts/ConfiguratorStorage.sol +++ b/contracts/ConfiguratorStorage.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.15; import "./CometConfiguration.sol"; +import "./marketupdates/MarketAdminPermissionCheckerInterface.sol"; /** * @title Compound's Comet Configuration Storage Interface @@ -25,12 +26,6 @@ contract ConfiguratorStorage is CometConfiguration { /// @notice Mapping of Comet proxy addresses to their Comet factory contracts mapping(address => address) public factory; - /// @notice The address of the market admin. This will be the address of a timelock contract. - address public marketAdmin; - - /// @notice Pause flag for the market admin - bool public marketAdminPaused; - - /// @notice address of the market admin pause guardian. We don't use `pauseGuardian` role because we have `setPauseGuardian` already which sets the pauseGuardian on comet. - address public marketAdminPauseGuardian; + /// @notice MarketAdminPermissionChecker contract which is used to check if the caller has permission to perform market updates + MarketAdminPermissionCheckerInterface public marketAdminPermissionChecker; } diff --git a/contracts/marketupdates/MarketAdminPermissionChecker.sol b/contracts/marketupdates/MarketAdminPermissionChecker.sol new file mode 100644 index 00000000..249d6ba3 --- /dev/null +++ b/contracts/marketupdates/MarketAdminPermissionChecker.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "../vendor/access/Ownable.sol"; +import "./MarketAdminPermissionCheckerInterface.sol"; + +contract MarketAdminPermissionChecker is MarketAdminPermissionCheckerInterface, Ownable { + /// @notice The address of the market admin. This will be the address of the market update timelock contract. + address public marketAdmin; + + /// @notice Pause flag for the market admin + bool public marketAdminPaused; + + /// @notice address of the market admin pause guardian. + address public marketAdminPauseGuardian; + + event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin); + event SetMarketAdminPauseGuardian(address indexed oldPauseGuardian, address indexed newPauseGuardian); + event MarketAdminPaused(address indexed caller, bool isMarketAdminPaused); + + /** + * @notice Construct a new MarketAdminPermissionChecker contract. + * Not adding any checks for zero address as it may be a deliberate choice to assign the zero address i.e. keep the + * market updates disabled. + * @param marketAdmin_ The address of the market admin. + * @param marketAdminPauseGuardian_ The address of the market admin pause guardian. + */ + constructor(address marketAdmin_, address marketAdminPauseGuardian_) { + marketAdmin = marketAdmin_; + marketAdminPauseGuardian = marketAdminPauseGuardian_; + } + /** + * @notice Sets a new market admin. + * @dev Can only be called by the main-governor-timelock. Reverts with Unauthorized if the caller is not the main-governor-timelock. + * Emits an event with the old and new market admin addresses. + * Note that there is no enforced zero address check on `newMarketAdmin` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the market admin role. + * @param newMarketAdmin The address of the new market admin. + */ + function setMarketAdmin(address newMarketAdmin) external onlyOwner { + address oldMarketAdmin = marketAdmin; + marketAdmin = newMarketAdmin; + emit SetMarketAdmin(oldMarketAdmin, newMarketAdmin); + } + + /** + * @notice Sets a new market admin pause guardian. + * @dev Can only be called by the main-governor-timelock. Reverts with Unauthorized if the caller is not the owner. + * @param newPauseGuardian The address of the new market admin pause guardian. + * Note that there is no enforced zero address check on `newPauseGuardian` as it may be a deliberate choice + * to assign the zero address in certain scenarios. This design allows flexibility if the zero address + * is intended to represent a specific state, such as temporarily disabling the pause guardian. + */ + function setMarketAdminPauseGuardian(address newPauseGuardian) external onlyOwner { + address oldPauseGuardian = marketAdminPauseGuardian; + marketAdminPauseGuardian = newPauseGuardian; + emit SetMarketAdminPauseGuardian(oldPauseGuardian, newPauseGuardian); + } + + /** + * @notice Pauses the market admin role. + * @dev Can only be called by the main-governor-timelock or the market admin pause guardian. + * Reverts with Unauthorized if the caller is neither. + */ + function pauseMarketAdmin() external { + if (msg.sender != owner() && msg.sender != marketAdminPauseGuardian) revert Unauthorized(); + marketAdminPaused = true; + emit MarketAdminPaused(msg.sender, true); + } + + /** + * @notice Unpauses the market admin role. + * @dev Can only be called by the main-governor-timelock. + * Reverts with Unauthorized if the caller is not the main-governor-timelock. + */ + function unpauseMarketAdmin() external onlyOwner { + marketAdminPaused = false; + emit MarketAdminPaused(msg.sender, false); + } + + /** + * @notice Checks if the caller can perform market updates or not. + * Throws an error if the callerAddress is not same as market admin, or if the market admin is paused + * @param callerAddress The address of the caller + */ + function checkUpdatePermission(address callerAddress) external view { + if (callerAddress != marketAdmin) revert Unauthorized(); + if (marketAdminPaused) revert MarketAdminIsPaused(); + } +} diff --git a/contracts/marketupdates/MarketAdminPermissionCheckerInterface.sol b/contracts/marketupdates/MarketAdminPermissionCheckerInterface.sol new file mode 100644 index 00000000..d7576c55 --- /dev/null +++ b/contracts/marketupdates/MarketAdminPermissionCheckerInterface.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +/** + * @dev Interface for interacting with MarketAdminPermissionChecker + */ +interface MarketAdminPermissionCheckerInterface { + + /// @notice Error which represents that the caller passed is not market admin + error Unauthorized(); + + /// @notice Error which represents that the caller passed is market admin, but market admin is paused and can't + /// perform market updates + error MarketAdminIsPaused(); + + /** + * @notice Checks if the caller can perform market updates or not. + * Throws an error if the callerAddress is not same as market admin, or if the market admin is paused + * @param callerAddress The address of the caller + */ + function checkUpdatePermission(address callerAddress) external view; +} diff --git a/contracts/marketupdates/MarketUpdateProposer.sol b/contracts/marketupdates/MarketUpdateProposer.sol index 6794e611..9b9e58dd 100644 --- a/contracts/marketupdates/MarketUpdateProposer.sol +++ b/contracts/marketupdates/MarketUpdateProposer.sol @@ -68,7 +68,7 @@ contract MarketUpdateProposer { uint public proposalCount; /// @notice The initial proposal ID, set when the contract is deployed - uint public initialProposalId = 0; + uint public initialProposalId; /// @notice An event emitted when a new proposal is created event MarketUpdateProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, string description); diff --git a/deployments/localhost/dai/deploy.ts b/deployments/localhost/dai/deploy.ts index 42b09d3c..af92db1a 100644 --- a/deployments/localhost/dai/deploy.ts +++ b/deployments/localhost/dai/deploy.ts @@ -6,7 +6,6 @@ import { wait, getConfiguration, sameAddress, - COMP_WHALES, getConfigurationStruct } from '../../../src/deploy'; import '@nomiclabs/hardhat-ethers'; @@ -43,7 +42,6 @@ export default async function deploy(deploymentManager: DeploymentManager, deplo const signer = await deploymentManager.getSigner(); const ethers = deploymentManager.hre.ethers; const admin = signer; - const voterAddress = COMP_WHALES.testnet[0]; // Deploy governance contracts const clone = { @@ -383,29 +381,24 @@ export default async function deploy(deploymentManager: DeploymentManager, deplo const signers = await ethers.getSigners(); + const marketUpdateTimelock = (await deploymentManager.deploy( + 'marketUpdateTimelock', + 'marketupdates/MarketUpdateTimelock.sol', + [governor, 2 * 24 * 60 * 60], + maybeForce() + )) as MarketUpdateTimelock; + // 1) Deploy the address of MarketAdminMultiSig const marketUpdateMultiSig = signers[3]; + const proposalGuardian = signers[11]; const marketUpdateProposer = await deploymentManager.deploy( 'marketUpdateProposer', 'marketupdates/MarketUpdateProposer.sol', - [], + [governor, marketUpdateMultiSig.address, proposalGuardian.address, marketUpdateTimelock.address], maybeForce() ) as MarketUpdateProposer; - - - const marketUpdateTimelock = await deploymentManager.deploy( - 'marketUpdateTimelock', - 'marketupdates/MarketUpdateTimelock.sol', - [governor, 2 * 24 * 60 * 60], - maybeForce() - ) as MarketUpdateTimelock; - - await marketUpdateProposer.initialize(marketUpdateTimelock.address); - - await marketUpdateProposer.transferOwnership(marketUpdateMultiSig.address); - const cometProxyAdminNew = await deploymentManager.deploy( 'cometProxyAdminNew', 'CometProxyAdmin.sol', @@ -422,37 +415,74 @@ export default async function deploy(deploymentManager: DeploymentManager, deplo maybeForce() ); + const marketAdminPermissionChecker = await deploymentManager.deploy( + 'marketAdminPermissionChecker', + 'marketupdates/MarketAdminPermissionChecker.sol', + [ethers.constants.AddressZero, ethers.constants.AddressZero], + maybeForce() + ); + + await marketAdminPermissionChecker.transferOwnership( + governor + ); + const newSupplyKinkByGovernorTimelock = 300n; trace('Trigger updates to enable market admin'); - const firstProposalTxn = await governorBravo.connect(admin).propose( - [ - cometProxyAdminOld.address, - cometProxyAdminOld.address, - cometProxyAdminNew.address, - configuratorProxyContract.address, - cometProxyAdminNew.address, - marketUpdateTimelock.address - ], - [0, 0, 0, 0, 0, 0], - [ - 'changeProxyAdmin(address,address)', - 'changeProxyAdmin(address,address)', - 'upgrade(address,address)', - 'setMarketAdmin(address)', - 'setMarketAdmin(address)', - 'setMarketUpdateProposer(address)', - ], - [ - ethers.utils.defaultAbiCoder.encode(['address', 'address'], [configuratorProxyContract.address, cometProxyAdminNew.address]), - ethers.utils.defaultAbiCoder.encode(['address', 'address'], [cometProxy.address, cometProxyAdminNew.address]), - ethers.utils.defaultAbiCoder.encode(['address', 'address'], [configuratorProxyContract.address, configuratorNew.address]), - ethers.utils.defaultAbiCoder.encode(['address'], [marketUpdateTimelock.address]), - ethers.utils.defaultAbiCoder.encode(['address'], [marketUpdateTimelock.address]), - ethers.utils.defaultAbiCoder.encode(['address'], [marketUpdateProposer.address]) - ], - 'Proposal to trigger updates for market admin' - ); + const firstProposalTxn = await governorBravo + .connect(admin) + .propose( + [ + cometProxyAdminOld.address, + cometProxyAdminOld.address, + cometProxyAdminNew.address, + marketAdminPermissionChecker.address, + configuratorProxyContract.address, + cometProxyAdminNew.address, + marketUpdateTimelock.address, + ], + [0, 0, 0, 0, 0, 0, 0], + [ + 'changeProxyAdmin(address,address)', + 'changeProxyAdmin(address,address)', + 'upgrade(address,address)', + 'setMarketAdmin(address)', + 'setMarketAdminPermissionChecker(address)', + 'setMarketAdminPermissionChecker(address)', + 'setMarketUpdateProposer(address)', + ], + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, cometProxyAdminNew.address] + ), + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [cometProxy.address, cometProxyAdminNew.address] + ), + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, configuratorNew.address] + ), + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketUpdateTimelock.address] + ), + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketAdminPermissionChecker.address] + ), + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketAdminPermissionChecker.address] + ), + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketUpdateProposer.address] + ), + ], + 'Proposal to trigger updates for market admin' + ); const firstProposalReceipt = await firstProposalTxn.wait(); const firstProposalID = firstProposalReceipt.events.find( diff --git a/test/configurator-test.ts b/test/configurator-test.ts index 07a6b724..2d8849b7 100644 --- a/test/configurator-test.ts +++ b/test/configurator-test.ts @@ -1,5 +1,10 @@ import { annualize, defactor, defaultAssets, ethers, event, exp, expect, factor, makeConfigurator, Numeric, truncateDecimals, wait } from './helpers'; -import { CometModifiedFactory__factory, SimplePriceFeed__factory, SimpleTimelock__factory } from '../build/types'; +import { + CometModifiedFactory__factory, + MarketAdminPermissionChecker__factory, + SimplePriceFeed__factory, + SimpleTimelock__factory +} from '../build/types'; import { AssetInfoStructOutput } from '../build/types/CometHarnessInterface'; import { ConfigurationStructOutput } from '../build/types/Configurator'; import { BigNumber } from 'ethers'; @@ -97,7 +102,17 @@ describe('configurator', function () { it('reverts if deploy is called from non-governor', async () => { const { configuratorProxy, proxyAdmin, cometProxy, users: [alice] } = await makeConfigurator(); - await expect(proxyAdmin.connect(alice).deployAndUpgradeTo(configuratorProxy.address, cometProxy.address)).to.be.revertedWith('Ownable: caller is not the owner'); + const MarketAdminPermissionCheckerFactory = (await ethers.getContractFactory( + 'MarketAdminPermissionChecker' + )) as MarketAdminPermissionChecker__factory; + + + const marketAdminPermissionCheckerContract = await MarketAdminPermissionCheckerFactory.deploy( + ethers.constants.AddressZero, + ethers.constants.AddressZero + ); + + await expect(proxyAdmin.connect(alice).deployAndUpgradeTo(configuratorProxy.address, cometProxy.address)).to.be.revertedWithCustomError(marketAdminPermissionCheckerContract, 'Unauthorized'); }); it('e2e governance actions from timelock', async () => { @@ -939,4 +954,4 @@ describe('configurator', function () { ).to.be.revertedWith("custom error 'Unauthorized()'"); }); }); -}); \ No newline at end of file +}); diff --git a/test/helpers.ts b/test/helpers.ts index 028b4a61..42e29714 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -32,6 +32,7 @@ import { CometInterface, NonStandardFaucetFeeToken, NonStandardFaucetFeeToken__factory, + MarketAdminPermissionChecker, MarketAdminPermissionChecker__factory, } from '../build/types'; import { BigNumber } from 'ethers'; import { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider'; @@ -87,6 +88,7 @@ export type ProtocolOpts = { baseBorrowMin?: Numeric; targetReserves?: Numeric; baseTokenBalance?: Numeric; + marketAdminPermissionCheckerContract?: MarketAdminPermissionChecker; }; export type Protocol = { @@ -470,11 +472,29 @@ export async function makeConfigurator(opts: ProtocolOpts = {}): Promise { const { governorTimelockSigner, - marketUpdateTimelock, marketUpdateTimelockSigner, + marketAdminPermissionCheckerContract } = await makeMarketAdmin(); const { @@ -45,15 +45,12 @@ describe('CometProxyAdmin', function() { users: [alice], } = await makeConfigurator({ governor: governorTimelockSigner, + marketAdminPermissionCheckerContract }); - await proxyAdmin - .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address); + expect(await proxyAdmin.marketAdminPermissionChecker()).to.be.equal(marketAdminPermissionCheckerContract.address); + expect(await marketAdminPermissionCheckerContract.marketAdmin()).to.be.equal(marketUpdateTimelockSigner.address); - expect(await proxyAdmin.marketAdmin()).to.be.equal( - marketUpdateTimelock.address - ); await expect( proxyAdmin @@ -62,183 +59,12 @@ describe('CometProxyAdmin', function() { ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it('only main-governor-timelock can set or update marketAdminPauseGuardian', async () => { - const { - governorTimelockSigner, - marketUpdateTimelock, - marketUpdateMultiSig, - marketUpdateTimelockSigner, - } = await makeMarketAdmin(); - - const { - proxyAdmin, - users: [alice], - } = await makeConfigurator({ - governor: governorTimelockSigner, - }); - - const oldMarketAdminPauseGuardian = await proxyAdmin.marketAdminPauseGuardian(); - expect(oldMarketAdminPauseGuardian).to.be.equal( - ethers.constants.AddressZero - ); - - const txn = await wait( - proxyAdmin - .connect(governorTimelockSigner) - .setMarketAdminPauseGuardian(alice.address) - ); - expect(event(txn, 0)).to.be.deep.equal({ - SetMarketAdminPauseGuardian: { - oldPauseGuardian: oldMarketAdminPauseGuardian, - newPauseGuardian: alice.address, - }, - }); - const newMarketAdminPauseGuardian = await proxyAdmin.marketAdminPauseGuardian(); - expect(newMarketAdminPauseGuardian).to.be.equal(alice.address); - expect(newMarketAdminPauseGuardian).to.be.not.equal( - oldMarketAdminPauseGuardian - ); - await expect( - proxyAdmin - .connect(marketUpdateMultiSig) - .setMarketAdminPauseGuardian(marketUpdateTimelock.address) - ).to.be.revertedWithCustomError(proxyAdmin, 'Unauthorized'); - - await expect( - proxyAdmin - .connect(marketUpdateTimelockSigner) - .setMarketAdminPauseGuardian(marketUpdateTimelock.address) - ).to.be.revertedWithCustomError(proxyAdmin, 'Unauthorized'); - }); - - it('main-governor-timelock can pause and unpause market admin', async () => { - const { governorTimelockSigner } = await makeMarketAdmin(); - const { proxyAdmin } = await makeConfigurator({ - governor: governorTimelockSigner, - }); - - expect(await proxyAdmin.marketAdminPaused()).to.be.false; - - const txnOfPause = await wait( - proxyAdmin.connect(governorTimelockSigner).pauseMarketAdmin() - ); - - expect(event(txnOfPause, 0)).to.be.deep.equal({ - MarketAdminPaused: { - isMarketAdminPaused: true, - }, - }); - expect(await proxyAdmin.marketAdminPaused()).to.be.true; - - const txnOfUnpause = await wait( - proxyAdmin.connect(governorTimelockSigner).unpauseMarketAdmin() - ); - - expect(event(txnOfUnpause, 0)).to.be.deep.equal({ - MarketAdminPaused: { - isMarketAdminPaused: false, - }, - }); - expect(await proxyAdmin.marketAdminPaused()).to.be.false; - }); - - it('marketAdminPauseGuardian can pause market admin', async () => { - const { - governorTimelockSigner, - marketUpdateTimelock, - marketUpdateMultiSig, - marketUpdateProposer, - } = await makeMarketAdmin(); - - const { - configuratorProxy, - cometProxy, - proxyAdmin, - users: [alice], - } = await makeConfigurator({ - governor: governorTimelockSigner, - }); - - expect(await proxyAdmin.marketAdminPaused()).to.be.false; - - await proxyAdmin - .connect(governorTimelockSigner) - .setMarketAdminPauseGuardian(alice.address); - - expect(await proxyAdmin.marketAdminPauseGuardian()).to.be.equal( - alice.address - ); - - const txn = await wait(proxyAdmin.connect(alice).pauseMarketAdmin()); - - expect(event(txn, 0)).to.be.deep.equal({ - MarketAdminPaused: { - isMarketAdminPaused: true, - }, - }); - expect(await proxyAdmin.marketAdminPaused()).to.be.true; - - await proxyAdmin - .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address); - - expect(await proxyAdmin.marketAdmin()).to.be.equal( - marketUpdateTimelock.address - ); - - const proposalId = 1n; - - await marketUpdateProposer - .connect(marketUpdateMultiSig) - .propose( - [proxyAdmin.address], - [0], - ['deployAndUpgradeTo(address,address)'], - [ - ethers.utils.defaultAbiCoder.encode( - ['address', 'address'], - [configuratorProxy.address, cometProxy.address] - ), - ], - 'Upgrading comet proxy admin implementation' - ); - - await expect( - marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId) - ).to.be.rejectedWith( - 'MarketUpdateTimelock::executeTransaction: Transaction execution reverted.' - ); - }); - - it('marketAdminPauseGuardian cannot unpause market admin', async () => { - const { governorTimelockSigner } = await makeMarketAdmin(); - - const { - proxyAdmin, - users: [alice], - } = await makeConfigurator({ - governor: governorTimelockSigner, - }); - - expect(await proxyAdmin.marketAdminPaused()).to.be.false; - await proxyAdmin - .connect(governorTimelockSigner) - .setMarketAdminPauseGuardian(alice.address); - - expect(await proxyAdmin.marketAdminPauseGuardian()).to.be.equal( - alice.address - ); - - await expect( - proxyAdmin.connect(alice).unpauseMarketAdmin() - ).to.be.revertedWithCustomError(proxyAdmin, 'Unauthorized'); - }); it('deployAndUpgradeTo can be called by main-governor-timelock or market-admin', async () => { const { governorTimelockSigner, - marketUpdateTimelock, + marketAdminPermissionCheckerContract, marketUpdateTimelockSigner, } = await makeMarketAdmin(); @@ -248,6 +74,7 @@ describe('CometProxyAdmin', function() { proxyAdmin, } = await makeConfigurator({ governor: governorTimelockSigner, + marketAdminPermissionCheckerContract }); const abi = [ @@ -279,13 +106,9 @@ describe('CometProxyAdmin', function() { expect(eventsForGovernorTimelock[0].name).to.be.equal('CometDeployed'); expect(eventsForGovernorTimelock[1].name).to.be.equal('Upgraded'); - await proxyAdmin - .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address); + expect(await proxyAdmin.marketAdminPermissionChecker()).to.be.equal(marketAdminPermissionCheckerContract.address); + expect(await marketAdminPermissionCheckerContract.marketAdmin()).to.be.equal(marketUpdateTimelockSigner.address); - expect(await proxyAdmin.marketAdmin()).to.be.equal( - marketUpdateTimelock.address - ); const txnForMarketAdmin = (await wait( proxyAdmin @@ -312,7 +135,7 @@ describe('CometProxyAdmin', function() { it('deployUpgradeToAndCall can be called by main-governor-timelock or market-admin', async () => { const { governorTimelockSigner, - marketUpdateTimelock, + marketAdminPermissionCheckerContract, marketUpdateTimelockSigner, } = await makeMarketAdmin(); @@ -322,6 +145,7 @@ describe('CometProxyAdmin', function() { proxyAdmin, } = await makeConfigurator({ governor: governorTimelockSigner, + marketAdminPermissionCheckerContract, }); const functionAbi = new ethers.utils.Interface(['function getReserves()']); @@ -360,13 +184,9 @@ describe('CometProxyAdmin', function() { expect(eventsForGovernorTimelock[0].name).to.be.equal('CometDeployed'); expect(eventsForGovernorTimelock[1].name).to.be.equal('Upgraded'); - await proxyAdmin - .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address); + expect(await proxyAdmin.marketAdminPermissionChecker()).to.be.equal(marketAdminPermissionCheckerContract.address); + expect(await marketAdminPermissionCheckerContract.marketAdmin()).to.be.equal(marketUpdateTimelockSigner.address); - expect(await proxyAdmin.marketAdmin()).to.be.equal( - marketUpdateTimelock.address - ); const txnForMarketAdmin = (await wait( proxyAdmin @@ -395,7 +215,7 @@ describe('CometProxyAdmin', function() { }); it('no other address can call deployAndUpgradeTo', async () => { - const { governorTimelockSigner } = await makeMarketAdmin(); + const { governorTimelockSigner, marketAdminPermissionCheckerContract } = await makeMarketAdmin(); const { configuratorProxy, @@ -404,19 +224,20 @@ describe('CometProxyAdmin', function() { users: [alice], } = await makeConfigurator({ governor: governorTimelockSigner, + marketAdminPermissionCheckerContract }); await expect( proxyAdmin .connect(alice) .deployAndUpgradeTo(configuratorProxy.address, cometProxy.address) - ).to.be.revertedWith( - 'Unauthorized: caller is not owner or market update admin' + ).to.be.revertedWithCustomError( + marketAdminPermissionCheckerContract, 'Unauthorized' ); }); it('no other address can call deployUpgradeToAndCall', async () => { - const { governorTimelockSigner } = await makeMarketAdmin(); + const { governorTimelockSigner, marketAdminPermissionCheckerContract } = await makeMarketAdmin(); const { configuratorProxy, @@ -425,6 +246,7 @@ describe('CometProxyAdmin', function() { users: [alice], } = await makeConfigurator({ governor: governorTimelockSigner, + marketAdminPermissionCheckerContract }); const callData = '0x'; @@ -437,8 +259,9 @@ describe('CometProxyAdmin', function() { cometProxy.address, callData ) - ).to.be.revertedWith( - 'Unauthorized: caller is not owner or market update admin' + ).to.be.revertedWithCustomError( + marketAdminPermissionCheckerContract, + 'Unauthorized' ); }); @@ -470,7 +293,7 @@ describe('CometProxyAdmin', function() { it('a new comet implementation gets deployed when market admin calls deployAndUpgradeTo', async () => { const { governorTimelockSigner, - marketUpdateTimelock, + marketAdminPermissionCheckerContract, marketUpdateTimelockSigner, } = await makeMarketAdmin(); @@ -480,15 +303,12 @@ describe('CometProxyAdmin', function() { proxyAdmin, } = await makeConfigurator({ governor: governorTimelockSigner, + marketAdminPermissionCheckerContract }); - await proxyAdmin - .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address); + expect(await proxyAdmin.marketAdminPermissionChecker()).to.be.equal(marketAdminPermissionCheckerContract.address); + expect(await marketAdminPermissionCheckerContract.marketAdmin()).to.be.equal(marketUpdateTimelockSigner.address); - expect(await proxyAdmin.marketAdmin()).to.be.equal( - marketUpdateTimelock.address - ); const oldCometImplementation = await proxyAdmin.getProxyImplementation( cometProxy.address diff --git a/test/marketupdates/market-update-configurator-test.ts b/test/marketupdates/market-update-configurator-test.ts index 8508006a..5a850d7f 100644 --- a/test/marketupdates/market-update-configurator-test.ts +++ b/test/marketupdates/market-update-configurator-test.ts @@ -1,12 +1,10 @@ import { expect, makeConfigurator, event, wait } from './../helpers'; import { makeMarketAdmin } from './market-updates-helper'; -import { ethers } from 'hardhat'; describe('Configurator', function() { it('already initialized and is not able to initialize again with main-governor-timelock as admin', async () => { const { governorTimelockSigner, - governorTimelock, } = await makeMarketAdmin(); const { configurator, configuratorProxy } = await makeConfigurator({ @@ -18,252 +16,26 @@ describe('Configurator', function() { // check already initialized properly expect(await configuratorAsProxy.version()).to.be.equal(1); expect(await configuratorAsProxy.governor()).to.be.equal( - governorTimelock.address + governorTimelockSigner.address ); expect(await configuratorAsProxy.governor()).to.be.equal( - governorTimelock.address + governorTimelockSigner.address ); // check is not able to initialize again await expect( - configuratorAsProxy.initialize(governorTimelock.address) + configuratorAsProxy.initialize(governorTimelockSigner.address) ).to.be.revertedWith("custom error 'AlreadyInitialized()'"); }); - it('only main-governor-timelock can set market admin', async () => { - const { - governorTimelockSigner, - marketUpdateTimelock, - marketUpdateTimelockSigner, - marketUpdateMultiSig, - } = await makeMarketAdmin(); - - const { configurator, configuratorProxy } = await makeConfigurator({ - governor: governorTimelockSigner, - }); - - const configuratorAsProxy = configurator.attach(configuratorProxy.address); - - const oldMarketAdmin = await configuratorAsProxy.marketAdmin(); - - // Add a check to make sure its set as address(0) initially. So here oldMarketAdmin should be (0) - expect(oldMarketAdmin).to.be.equal(ethers.constants.AddressZero); - const txn = await wait( - configuratorAsProxy - .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address) - ); - expect(event(txn, 0)).to.be.deep.equal({ - SetMarketAdmin: { - oldAdmin: oldMarketAdmin, - newAdmin: marketUpdateTimelock.address, - }, - }); - const newMarketAdmin = await configuratorAsProxy.marketAdmin(); - expect(newMarketAdmin).to.be.equal(marketUpdateTimelock.address); - expect(newMarketAdmin).to.be.not.equal(oldMarketAdmin); - - await expect( - configuratorAsProxy - .connect(marketUpdateMultiSig) - .setMarketAdmin(marketUpdateTimelock.address) - ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); - - await expect( - configuratorAsProxy - .connect(marketUpdateTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address) - ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); - }); - - it('only main-governor-timelock can set or update marketAdminPauseGuardian', async () => { - const { - governorTimelockSigner, - marketUpdateTimelock, - marketUpdateMultiSig, - marketUpdateTimelockSigner, - } = await makeMarketAdmin(); - - const { - configurator, - configuratorProxy, - users: [alice], - } = await makeConfigurator({ - governor: governorTimelockSigner, - }); - - const configuratorAsProxy = configurator.attach(configuratorProxy.address); - - const oldMarketAdminPauseGuardian = await configuratorAsProxy.marketAdminPauseGuardian(); - expect(oldMarketAdminPauseGuardian).to.be.equal( - ethers.constants.AddressZero - ); - - const txn = await wait( - configuratorAsProxy - .connect(governorTimelockSigner) - .setMarketAdminPauseGuardian(alice.address) - ); - expect(event(txn, 0)).to.be.deep.equal({ - SetMarketAdminPauseGuardian: { - oldPauseGuardian: oldMarketAdminPauseGuardian, - newPauseGuardian: alice.address, - }, - }); - const newMarketAdminPauseGuardian = await configuratorAsProxy.marketAdminPauseGuardian(); - expect(newMarketAdminPauseGuardian).to.be.equal(alice.address); - expect(newMarketAdminPauseGuardian).to.be.not.equal( - oldMarketAdminPauseGuardian - ); - await expect( - configuratorAsProxy - .connect(marketUpdateMultiSig) - .setMarketAdminPauseGuardian(marketUpdateTimelock.address) - ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); - - await expect( - configuratorAsProxy - .connect(marketUpdateTimelockSigner) - .setMarketAdminPauseGuardian(marketUpdateTimelock.address) - ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); - }); - - it('main-governor-timelock can pause and unpause market admin', async () => { - const { governorTimelockSigner } = await makeMarketAdmin(); - const { configurator, configuratorProxy } = await makeConfigurator({ - governor: governorTimelockSigner, - }); - - const configuratorAsProxy = configurator.attach(configuratorProxy.address); - expect(await configuratorAsProxy.marketAdminPaused()).to.be.false; - - const txnOfPause = await wait( - configuratorAsProxy.connect(governorTimelockSigner).pauseMarketAdmin() - ); - - expect(event(txnOfPause, 0)).to.be.deep.equal({ - MarketAdminPaused: { - isMarketAdminPaused: true, - }, - }); - expect(await configuratorAsProxy.marketAdminPaused()).to.be.true; - - const txnOfUnpause = await wait( - configuratorAsProxy.connect(governorTimelockSigner).unpauseMarketAdmin() - ); - - expect(event(txnOfUnpause, 0)).to.be.deep.equal({ - MarketAdminPaused: { - isMarketAdminPaused: false, - }, - }); - expect(await configuratorAsProxy.marketAdminPaused()).to.be.false; - }); - - it('marketAdminPauseGuardian can pause market admin', async () => { - const { - governorTimelockSigner, - marketUpdateMultiSig, - marketUpdateProposer, - marketUpdateTimelock, - } = await makeMarketAdmin(); - - const { - configurator, - configuratorProxy, - cometProxy, - users: [alice], - } = await makeConfigurator({ - governor: governorTimelockSigner, - }); - - const configuratorAsProxy = configurator.attach(configuratorProxy.address); - - expect(await configuratorAsProxy.marketAdminPaused()).to.be.false; - - await configuratorAsProxy - .connect(governorTimelockSigner) - .setMarketAdminPauseGuardian(alice.address); - - expect(await configuratorAsProxy.marketAdminPauseGuardian()).to.be.equal( - alice.address - ); - - const txn = await wait( - configuratorAsProxy.connect(alice).pauseMarketAdmin() - ); - - expect(event(txn, 0)).to.be.deep.equal({ - MarketAdminPaused: { - isMarketAdminPaused: true, - }, - }); - expect(await configuratorAsProxy.marketAdminPaused()).to.be.true; - - await configuratorAsProxy - .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address); - - expect(await configuratorAsProxy.marketAdmin()).to.be.equal( - marketUpdateTimelock.address - ); - const proposalId = 1n; - - await marketUpdateProposer - .connect(marketUpdateMultiSig) - .propose( - [configuratorProxy.address], - [0], - ['setSupplyKink(address,uint64)'], - [ - ethers.utils.defaultAbiCoder.encode( - ['address', 'uint64'], - [cometProxy.address, 100] - ), - ], - 'Setting supply kink to 100' - ); - await expect( - marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId) - ).to.be.rejectedWith( - 'MarketUpdateTimelock::executeTransaction: Transaction execution reverted.' - ); - }); - it('marketAdminPauseGuardian cannot unpause market admin', async () => { - const { governorTimelockSigner } = await makeMarketAdmin(); - - const { - configurator, - configuratorProxy, - users: [alice], - } = await makeConfigurator({ - governor: governorTimelockSigner, - }); - - const configuratorAsProxy = configurator.attach(configuratorProxy.address); - - expect(await configuratorAsProxy.marketAdminPaused()).to.be.false; - - await configuratorAsProxy - .connect(governorTimelockSigner) - .setMarketAdminPauseGuardian(alice.address); - - expect(await configuratorAsProxy.marketAdminPauseGuardian()).to.be.equal( - alice.address - ); - - await expect( - configuratorAsProxy.connect(alice).unpauseMarketAdmin() - ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); - }); it('only main-governor-timelock or market admin can call market update functions', async () => { const { governorTimelockSigner, - marketUpdateTimelock, marketUpdateTimelockSigner, + marketAdminPermissionCheckerContract } = await makeMarketAdmin(); const { @@ -272,6 +44,7 @@ describe('Configurator', function() { cometProxy, } = await makeConfigurator({ governor: governorTimelockSigner, + marketAdminPermissionCheckerContract: marketAdminPermissionCheckerContract }); const configuratorAsProxy = configurator.attach(configuratorProxy.address); @@ -299,12 +72,12 @@ describe('Configurator', function() { .supplyKink ).to.be.equal(newSupplyKink); - await configuratorAsProxy + await marketAdminPermissionCheckerContract .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address); + .setMarketAdmin(marketUpdateTimelockSigner.address); - expect(await configuratorAsProxy.marketAdmin()).to.be.equal( - marketUpdateTimelock.address + expect(await marketAdminPermissionCheckerContract.marketAdmin()).to.be.equal( + marketUpdateTimelockSigner.address ); const oldBorrowKink = ( @@ -335,8 +108,8 @@ describe('Configurator', function() { it('market admin cannot call NON market update functions', async () => { const { governorTimelockSigner, - marketUpdateTimelock, marketUpdateTimelockSigner, + marketAdminPermissionCheckerContract } = await makeMarketAdmin(); const { @@ -346,12 +119,14 @@ describe('Configurator', function() { users: [alice], } = await makeConfigurator({ governor: governorTimelockSigner, + marketAdminPermissionCheckerContract: marketAdminPermissionCheckerContract }); const configuratorAsProxy = configurator.attach(configuratorProxy.address); - await configuratorAsProxy + + await marketAdminPermissionCheckerContract .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address); + .setMarketAdmin(marketUpdateTimelockSigner.address); await expect( configuratorAsProxy @@ -362,8 +137,9 @@ describe('Configurator', function() { it('market admin cannot call market update functions when marketAdminPaused', async () => { const { + marketAdminPermissionCheckerContract, + governorTimelockSigner, - marketUpdateTimelock, marketUpdateTimelockSigner, } = await makeMarketAdmin(); @@ -373,33 +149,35 @@ describe('Configurator', function() { cometProxy, } = await makeConfigurator({ governor: governorTimelockSigner, + marketAdminPermissionCheckerContract: marketAdminPermissionCheckerContract }); const configuratorAsProxy = configurator.attach(configuratorProxy.address); - await configuratorAsProxy + + await marketAdminPermissionCheckerContract .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address); + .setMarketAdmin(marketUpdateTimelockSigner.address); - expect(await configuratorAsProxy.marketAdmin()).to.be.equal( - marketUpdateTimelock.address + expect(await marketAdminPermissionCheckerContract.marketAdmin()).to.be.equal( + marketUpdateTimelockSigner.address ); - await configuratorAsProxy + await marketAdminPermissionCheckerContract .connect(governorTimelockSigner) .pauseMarketAdmin(); - expect(await configuratorAsProxy.marketAdminPaused()).to.be.true; + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.true; const newBorrowKink = 100n; await expect( configuratorAsProxy .connect(marketUpdateTimelockSigner) .setBorrowKink(cometProxy.address, newBorrowKink) - ).to.be.revertedWith('Market admin is paused'); + ).to.be.revertedWithCustomError(marketAdminPermissionCheckerContract,'MarketAdminIsPaused'); }); - it('main-governor-timelock can call market update functions when marketAdminPause', async () => { - const { governorTimelockSigner } = await makeMarketAdmin(); + it('main-governor-timelock can call market update functions when marketAdminPaused', async () => { + const { marketAdminPermissionCheckerContract, governorTimelockSigner } = await makeMarketAdmin(); const { configurator, @@ -411,10 +189,11 @@ describe('Configurator', function() { const configuratorAsProxy = configurator.attach(configuratorProxy.address); - await configuratorAsProxy + + await marketAdminPermissionCheckerContract .connect(governorTimelockSigner) .pauseMarketAdmin(); - expect(await configuratorAsProxy.marketAdminPaused()).to.be.true; + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.true; const oldSupplyKink = ( await configuratorAsProxy.getConfiguration(cometProxy.address) @@ -442,8 +221,9 @@ describe('Configurator', function() { it('governor cannot be updated by market admin', async () => { const { + marketAdminPermissionCheckerContract, + governorTimelockSigner, - marketUpdateTimelock, marketUpdateTimelockSigner, } = await makeMarketAdmin(); @@ -457,9 +237,10 @@ describe('Configurator', function() { }); const configuratorAsProxy = configurator.attach(configuratorProxy.address); - await configuratorAsProxy + + await marketAdminPermissionCheckerContract .connect(governorTimelockSigner) - .setMarketAdmin(marketUpdateTimelock.address); + .setMarketAdmin(marketUpdateTimelockSigner.address); await expect( configuratorAsProxy @@ -467,4 +248,72 @@ describe('Configurator', function() { .setGovernor(cometProxy.address, alice.address) ).to.be.revertedWithCustomError(configuratorAsProxy, 'Unauthorized'); }); + + it('market admin can call market update functions when marketAdminPaused is changed to unpaused', async () => { + const { + marketAdminPermissionCheckerContract, + + governorTimelockSigner, + marketUpdateTimelockSigner, + } = await makeMarketAdmin(); + + const { + configurator, + configuratorProxy, + cometProxy, + } = await makeConfigurator({ + governor: governorTimelockSigner, + marketAdminPermissionCheckerContract: marketAdminPermissionCheckerContract + }); + + const configuratorAsProxy = configurator.attach(configuratorProxy.address); + + + await marketAdminPermissionCheckerContract + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelockSigner.address); + + expect(await marketAdminPermissionCheckerContract.marketAdmin()).to.be.equal( + marketUpdateTimelockSigner.address + ); + + await marketAdminPermissionCheckerContract + .connect(governorTimelockSigner) + .pauseMarketAdmin(); + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.true; + + const newBorrowKink = 100n; + await expect( + configuratorAsProxy + .connect(marketUpdateTimelockSigner) + .setBorrowKink(cometProxy.address, newBorrowKink) + ).to.be.revertedWithCustomError(marketAdminPermissionCheckerContract,'MarketAdminIsPaused'); + + await marketAdminPermissionCheckerContract + .connect(governorTimelockSigner) + .unpauseMarketAdmin(); + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.false; + + const oldBorrowKink = ( + await configuratorAsProxy.getConfiguration(cometProxy.address) + ).borrowKink; + + expect(oldBorrowKink).to.be.not.equal(newBorrowKink); + + const txnOfMarketAdmin = await wait( + configuratorAsProxy + .connect(marketUpdateTimelockSigner) + .setBorrowKink(cometProxy.address, newBorrowKink) + ); + + expect(event(txnOfMarketAdmin, 0)).to.be.deep.equal({ + SetBorrowKink: { + cometProxy: cometProxy.address, + oldKink: oldBorrowKink, + newKink: newBorrowKink, + }, + }); + + + }); }); diff --git a/test/marketupdates/market-update-deployment-test.ts b/test/marketupdates/market-update-deployment-test.ts index e30d97d0..e761fe5c 100644 --- a/test/marketupdates/market-update-deployment-test.ts +++ b/test/marketupdates/market-update-deployment-test.ts @@ -11,6 +11,7 @@ import { Configurator__factory, ConfiguratorOld__factory, ConfiguratorProxy__factory, + MarketAdminPermissionChecker__factory, SimpleTimelock, TransparentUpgradeableProxy__factory, } from './../../build/types'; @@ -37,19 +38,19 @@ describe('MarketUpdateDeployment', function() { ------- Deploy New Contracts ----------- 1) Deploy the address of MarketAdminMultiSig - 2) Deploy MarketUpdateProposer with MarketAdminMultiSig as the owner + 2) Deploy MarketUpdateTimelock with Governor Timelock as the owner - 3) Deploy MarketUpdateTimelock with Governor Timelock as the owner + 3) Deploy MarketUpdateProposer with MarketAdminMultiSig as the owner - 4) Initialize the MarketUpdateProposer with MarketUpdateTimelock + 4) Deploy the new CometProxyAdmin - 5) Deploy the new CometProxyAdmin + 5) Set MainGovernorTimelock as the owner of new CometProxyAdmin by calling transferOwnership - 6) Set MainGovernorTimelock as the owner of new CometProxyAdmin by calling transferOwnership + 6) Deploy the new Configurator's Implementation - 7) Deploy the new Configurator's Implementation + 7) Deploy the MarketAdminPermissionChecker contract - 8) Initialize the new Configurator with Governor Timelock + 8) Transfer the ownership of MarketAdminPermissionChecker to Governor Timelock ------- Update Existing Contracts ----------- @@ -59,18 +60,18 @@ describe('MarketUpdateDeployment', function() { 2) Call Old CometProxyAdmin and call `changeProxyAdmin` function to set Configurator's Proxy's admin as the new CometProxyAdmin // This will allow the new CometProxyAdmin to upgrade the Configurator's implementation if needed in future - -- Set new configurator as implementation --- + -- Set new configurator's implementation --- - 3) Set marketUpdateAdmin on Configurator + 3) Set marketUpdateAdmin on MarketAdminPermissionChecker - 4) Set marketUpdateAdmin on CometProxyAdmin + 4) Set MarketAdminPermissionChecker on Configurator - 5) Set marketAdminPauseGuardian on Configurator + 5) Set MarketAdminPermissionChecker on CometProxyAdmin - 6) Set marketAdminPauseGuardian on CometProxyAdmin + 6) Set Market Update proposer in MarketUpdateTimelock 7) Deploy market update // This will make sure existing functionality is working fine - - setSupplyCap + - setSupplyKink - deployAndUpgrade */ @@ -124,20 +125,11 @@ describe('MarketUpdateDeployment', function() { value: ethers.utils.parseEther('1.0'), // Sending 1 Ether to cover gas fees }); - // 2) Deploy MarketUpdateProposer with MarketAdminMultiSig as the owner - const marketUpdateProposer = await marketUpdaterProposerFactory - .connect(marketUpdateMultiSig) - .deploy(); - - expect(await marketUpdateProposer.owner()).to.be.equal( - marketUpdateMultiSig.address - ); - const marketAdminTimelockFactory = await ethers.getContractFactory( 'MarketUpdateTimelock' ); - // 3) Deploy MarketUpdateTimelock with Governor Timelock as the owner + // 2) Deploy MarketUpdateTimelock with Governor Timelock as the owner const marketUpdateTimelock = await marketAdminTimelockFactory.deploy( governorTimelock.address, 2 * 24 * 60 * 60 // This is 2 days in seconds @@ -149,22 +141,55 @@ describe('MarketUpdateDeployment', function() { value: ethers.utils.parseEther('1.0'), // Sending 1 Ether to cover gas fees }); - // 4) Initialize the MarketUpdateProposer with MarketUpdateTimelock - marketUpdateProposer + // 3) Deploy MarketUpdateProposer with MarketAdminMultiSig as the owner + const proposalGuardian = signers[5]; + const marketUpdateProposer = await marketUpdaterProposerFactory .connect(marketUpdateMultiSig) - .initialize(marketUpdateTimelock.address); + .deploy( + governorTimelock.address, + marketUpdateMultiSig.address, + proposalGuardian.address, + marketUpdateTimelock.address + ); + // 4) Deploy the new CometProxyAdmin + const ProxyAdmin = (await ethers.getContractFactory( + 'CometProxyAdmin' + )) as CometProxyAdmin__factory; + const proxyAdminNew = await ProxyAdmin.connect( + marketUpdateMultiSig + ).deploy(); - const ProxyAdmin = (await ethers.getContractFactory('CometProxyAdmin')) as CometProxyAdmin__factory; - const proxyAdminNew = await ProxyAdmin.connect(marketUpdateMultiSig).deploy(); + // 5) Set MainGovernorTimelock as the owner of new CometProxyAdmin by calling transferOwnership + await proxyAdminNew + .connect(marketUpdateMultiSig) + .transferOwnership(governorTimelock.address); + + // 6) Deploy the new Configurator's Implementation + const ConfiguratorFactory = (await ethers.getContractFactory( + 'Configurator' + )) as Configurator__factory; + const configuratorNew = await ConfiguratorFactory.connect( + marketUpdateMultiSig + ).deploy(); + await configuratorNew.deployed(); - // 6) Set MainGovernorTimelock as the owner of new CometProxyAdmin by calling transferOwnership - await proxyAdminNew.connect(marketUpdateMultiSig).transferOwnership(governorTimelock.address); + // 7) Deploy the MarketAdminPermissionChecker contract + const MarketAdminPermissionCheckerFactory = + (await ethers.getContractFactory( + 'MarketAdminPermissionChecker' + )) as MarketAdminPermissionChecker__factory; - // 7) Deploy the new Configurator's Implementation - const ConfiguratorFactory = (await ethers.getContractFactory('Configurator')) as Configurator__factory; - const configuratorNew = await ConfiguratorFactory.connect(marketUpdateMultiSig).deploy(); - await configuratorNew.deployed(); + const marketAdminPermissionCheckerContract = + await MarketAdminPermissionCheckerFactory.deploy( + ethers.constants.AddressZero, + ethers.constants.AddressZero + ); + + // 8) Transfer the ownership of MarketAdminPermissionChecker to Governor Timelock + await marketAdminPermissionCheckerContract.transferOwnership( + governorTimelock.address + ); // ------- Update Existing Contracts ----------- console.log('Updating the existing contracts'); @@ -174,10 +199,12 @@ describe('MarketUpdateDeployment', function() { [oldCometProxyAdmin.address], [0], ['changeProxyAdmin(address,address)'], - [ethers.utils.defaultAbiCoder.encode( - ['address', 'address'], - [proxyOfComet.address, proxyAdminNew.address] - )] + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [proxyOfComet.address, proxyAdminNew.address] + ), + ] ); // Call Old CometProxyAdmin and call `changeProxyAdmin` function to set Configurator's Proxy's admin as the new CometProxyAdmin // This will allow the new CometProxyAdmin to upgrade the Configurator's implementation if needed in future @@ -185,27 +212,29 @@ describe('MarketUpdateDeployment', function() { [oldCometProxyAdmin.address], [0], ['changeProxyAdmin(address,address)'], - [ethers.utils.defaultAbiCoder.encode( - ['address', 'address'], - [configuratorProxyContract.address, proxyAdminNew.address] - )] + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, proxyAdminNew.address] + ), + ] ); - // - await governorTimelock.executeTransactions( [proxyAdminNew.address], [0], ['upgrade(address,address)'], - [ethers.utils.defaultAbiCoder.encode( - ['address', 'address'], - [configuratorProxyContract.address, configuratorNew.address] - )] + [ + ethers.utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyContract.address, configuratorNew.address] + ), + ] ); - // Setting Market Update Admin in Configurator + // Setting Market Update Admin in MarketAdminPermissionChecker await governorTimelock.executeTransactions( - [configuratorProxyContract.address], + [marketAdminPermissionCheckerContract.address], [0], ['setMarketAdmin(address)'], [ @@ -216,15 +245,28 @@ describe('MarketUpdateDeployment', function() { ] ); - // Setting Market Update Admin in CometProxyAdmin + // Setting MarketAdminPermissionChecker on Configurator + await governorTimelock.executeTransactions( + [configuratorProxyContract.address], + [0], + ['setMarketAdminPermissionChecker(address)'], + [ + ethers.utils.defaultAbiCoder.encode( + ['address'], + [marketAdminPermissionCheckerContract.address] + ), + ] + ); + + // Setting MarketAdminPermissionChecker on CometProxyAdmin await governorTimelock.executeTransactions( [proxyAdminNew.address], [0], - ['setMarketAdmin(address)'], + ['setMarketAdminPermissionChecker(address)'], [ ethers.utils.defaultAbiCoder.encode( ['address'], - [marketUpdateTimelock.address] + [marketAdminPermissionCheckerContract.address] ), ] ); diff --git a/test/marketupdates/market-update-permission-checker-test.ts b/test/marketupdates/market-update-permission-checker-test.ts new file mode 100644 index 00000000..6d0acb4e --- /dev/null +++ b/test/marketupdates/market-update-permission-checker-test.ts @@ -0,0 +1,214 @@ +import {event, expect, wait} from './../helpers'; +import {createRandomWallet, makeMarketAdmin} from './market-updates-helper'; +import { ethers } from 'hardhat'; + +describe('MarketUpdatePermissionChecker', () => { + it('only the owner can update the market admin', async () => { + const { + marketAdminPermissionCheckerContract, + + governorTimelockSigner, + marketUpdateTimelockSigner, + marketUpdateMultiSig, + } = await makeMarketAdmin(); + + expect(await marketAdminPermissionCheckerContract.connect(governorTimelockSigner.address).owner()).to.be.equal(governorTimelockSigner.address); + const oldMarketAdmin = await marketAdminPermissionCheckerContract.marketAdmin(); + + // Add a check to make sure its set to marketUpdateTimelockSigner initially + expect(oldMarketAdmin).to.be.equal(marketUpdateTimelockSigner.address); + + const newMarketAdminWallet = ethers.Wallet.createRandom(); + + const txn = await wait( + marketAdminPermissionCheckerContract + .connect(governorTimelockSigner) + .setMarketAdmin(newMarketAdminWallet.address) + ); + expect(event(txn, 0)).to.be.deep.equal({ + SetMarketAdmin: { + oldAdmin: oldMarketAdmin, + newAdmin: newMarketAdminWallet.address, + }, + }); + const newMarketAdmin = await marketAdminPermissionCheckerContract.marketAdmin(); + expect(newMarketAdmin).to.be.equal(newMarketAdminWallet.address); + expect(newMarketAdmin).to.be.not.equal(oldMarketAdmin); + + await expect( + marketAdminPermissionCheckerContract + .connect(marketUpdateMultiSig) + .setMarketAdmin(newMarketAdminWallet.address) + ).to.be.revertedWith('Ownable: caller is not the owner'); + + await expect( + marketAdminPermissionCheckerContract + .connect(marketUpdateTimelockSigner) + .setMarketAdmin(newMarketAdminWallet.address) + ).to.be.revertedWith('Ownable: caller is not the owner'); + }); + + it('only the owner can set the market admin pause guardian', async () => { + const { + marketAdminPermissionCheckerContract, + governorTimelockSigner, + marketUpdateMultiSig, + marketUpdateTimelockSigner, + marketAdminPauseGuardianSigner + } = await makeMarketAdmin(); + + const alice = ethers.Wallet.createRandom(); + + const oldMarketAdminPauseGuardian = await marketAdminPermissionCheckerContract.marketAdminPauseGuardian(); + expect(oldMarketAdminPauseGuardian).to.be.equal( + marketAdminPauseGuardianSigner.address + ); + + const txn = await wait( + marketAdminPermissionCheckerContract + .connect(governorTimelockSigner) + .setMarketAdminPauseGuardian(alice.address) + ); + expect(event(txn, 0)).to.be.deep.equal({ + SetMarketAdminPauseGuardian: { + oldPauseGuardian: oldMarketAdminPauseGuardian, + newPauseGuardian: alice.address, + }, + }); + const newMarketAdminPauseGuardian = await marketAdminPermissionCheckerContract.marketAdminPauseGuardian(); + expect(newMarketAdminPauseGuardian).to.be.equal(alice.address); + expect(newMarketAdminPauseGuardian).to.be.not.equal( + oldMarketAdminPauseGuardian + ); + await expect( + marketAdminPermissionCheckerContract + .connect(marketUpdateMultiSig) + .setMarketAdminPauseGuardian(marketUpdateTimelockSigner.address) + ).to.be.revertedWith('Ownable: caller is not the owner'); + + await expect( + marketAdminPermissionCheckerContract + .connect(marketUpdateTimelockSigner) + .setMarketAdminPauseGuardian(marketUpdateTimelockSigner.address) + ).to.be.revertedWith('Ownable: caller is not the owner'); + + }); + + it('only the owner can pause the market admin', async () => { + const { + marketAdminPermissionCheckerContract, + governorTimelockSigner, + } = await makeMarketAdmin(); + + const alice = await createRandomWallet(); + + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.false; + + await marketAdminPermissionCheckerContract + .connect(governorTimelockSigner) + .setMarketAdminPauseGuardian(alice.address); + + expect( + await marketAdminPermissionCheckerContract.marketAdminPauseGuardian() + ).to.be.equal(alice.address); + + const txn = await wait( + marketAdminPermissionCheckerContract.connect(alice).pauseMarketAdmin() + ); + + expect(event(txn, 0)).to.be.deep.equal({ + MarketAdminPaused: { + caller: alice.address, + isMarketAdminPaused: true, + }, + }); + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.true; + }); + + it('only the owner can unpause the market admin', async () => { + const { marketAdminPermissionCheckerContract, governorTimelockSigner } = await makeMarketAdmin(); + + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.false; + + const txnOfPause = await wait( + marketAdminPermissionCheckerContract.connect(governorTimelockSigner).pauseMarketAdmin() + ); + + expect(event(txnOfPause, 0)).to.be.deep.equal({ + MarketAdminPaused: { + caller: governorTimelockSigner.address, + isMarketAdminPaused: true, + }, + }); + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.true; + + const txnOfUnpause = await wait( + marketAdminPermissionCheckerContract.connect(governorTimelockSigner).unpauseMarketAdmin() + ); + + expect(event(txnOfUnpause, 0)).to.be.deep.equal({ + MarketAdminPaused: { + caller: governorTimelockSigner.address, + isMarketAdminPaused: false, + }, + }); + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.false; + + }); + + it('should throw an error if the passed address is not market admin when checking permission', async () => { + const { marketAdminPermissionCheckerContract } = await makeMarketAdmin(); + + const alice = await createRandomWallet(); + + await expect( + marketAdminPermissionCheckerContract + .checkUpdatePermission(alice.address) + ).to.be.revertedWithCustomError(marketAdminPermissionCheckerContract, 'Unauthorized'); + }); + + it('should throw an error if the passed address is governor(timelock) when checking permission', async () => { + const { marketAdminPermissionCheckerContract, governorTimelockSigner } = await makeMarketAdmin(); + + await expect( + marketAdminPermissionCheckerContract + .checkUpdatePermission(governorTimelockSigner.address) + ).to.be.revertedWithCustomError(marketAdminPermissionCheckerContract, 'Unauthorized'); + }); + + it('should throw and error if the passed address is market admin but market admin is paused', async () => { + const { marketAdminPermissionCheckerContract, governorTimelockSigner, marketUpdateTimelockSigner } = await makeMarketAdmin(); + + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.false; + + const txn = await wait( + marketAdminPermissionCheckerContract.connect(governorTimelockSigner).pauseMarketAdmin() + ); + + expect(event(txn, 0)).to.be.deep.equal({ + MarketAdminPaused: { + caller: governorTimelockSigner.address, + isMarketAdminPaused: true, + }, + }); + + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.true; + + await expect( + marketAdminPermissionCheckerContract + .checkUpdatePermission(marketUpdateTimelockSigner.address) + ).to.be.revertedWithCustomError(marketAdminPermissionCheckerContract, 'MarketAdminIsPaused'); + }); + + it('should not throw an error if the passed address is market admin and market admin is not paused', async () => { + const { marketAdminPermissionCheckerContract, marketUpdateTimelockSigner } = await makeMarketAdmin(); + + expect(await marketAdminPermissionCheckerContract.marketAdminPaused()).to.be.false; + + await expect( + marketAdminPermissionCheckerContract + .checkUpdatePermission(marketUpdateTimelockSigner.address) + ).to.be.not.reverted; + }); + +}); diff --git a/test/marketupdates/market-update-proposer-test.ts b/test/marketupdates/market-update-proposer-test.ts index fdb3064e..7fb753a4 100644 --- a/test/marketupdates/market-update-proposer-test.ts +++ b/test/marketupdates/market-update-proposer-test.ts @@ -1,6 +1,6 @@ import { makeMarketAdmin, advanceTimeAndMineBlock } from './market-updates-helper'; import { expect, makeConfigurator, ethers, wait, event } from '../helpers'; -import { MarketUpdateProposer__factory } from '../../build/types'; +import { MarketAdminPermissionChecker__factory, MarketUpdateProposer__factory } from '../../build/types'; describe('MarketUpdateProposer', function() { // We are not checking market updates here. we are just checking interaction @@ -8,22 +8,22 @@ describe('MarketUpdateProposer', function() { // on MarketUpdateProposer it('is initialized properly with timelock', async () => { const { - marketUpdateProposer, - marketUpdateTimelock, + marketUpdateProposerContract, + marketUpdateTimelockContract, } = await makeMarketAdmin(); - expect(await marketUpdateProposer.timelock()).to.equal( - marketUpdateTimelock.address + expect(await marketUpdateProposerContract.timelock()).to.equal( + marketUpdateTimelockContract.address ); }); it('MarketUpdateMultisig is set as the marketAdmin of MarketUpdateProposer', async () => { const { - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, } = await makeMarketAdmin(); - expect(await marketUpdateProposer.marketAdmin()).to.equal( + expect(await marketUpdateProposerContract.marketAdmin()).to.equal( marketUpdateMultiSig.address ); }); @@ -31,56 +31,56 @@ describe('MarketUpdateProposer', function() { it('only GovernorTimelock can set a new governor for MarketUpdateProposer', async () => { const { governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, } = await makeMarketAdmin(); const { users: [alice, bob], } = await makeConfigurator(); - expect(await marketUpdateProposer.governor()).to.equal( + expect(await marketUpdateProposerContract.governor()).to.equal( governorTimelockSigner.address ); - await marketUpdateProposer + await marketUpdateProposerContract .connect(governorTimelockSigner) .setGovernor(alice.address); - expect(await marketUpdateProposer.governor()).to.equal(alice.address); + expect(await marketUpdateProposerContract.governor()).to.equal(alice.address); await expect( - marketUpdateProposer.connect(bob).setGovernor(alice.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(bob).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); }); it('only GovernorTimelock can set a new proposalGuardian for MarketUpdateProposer', async () => { const { governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, } = await makeMarketAdmin(); const { users: [alice, bob], } = await makeConfigurator(); - expect(await marketUpdateProposer.governor()).to.equal( + expect(await marketUpdateProposerContract.governor()).to.equal( governorTimelockSigner.address ); - await marketUpdateProposer + await marketUpdateProposerContract .connect(governorTimelockSigner) .setProposalGuardian(alice.address); - expect(await marketUpdateProposer.proposalGuardian()).to.equal(alice.address); + expect(await marketUpdateProposerContract.proposalGuardian()).to.equal(alice.address); await expect( - marketUpdateProposer.connect(bob).setProposalGuardian(alice.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(bob).setProposalGuardian(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); }); it('only allows MarketUpdateMultisig to create proposal', async () => { const { - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, } = await makeMarketAdmin(); @@ -100,7 +100,7 @@ describe('MarketUpdateProposer', function() { // Creates a proposal successfully as the signer is the multisig const txn = await wait( - marketUpdateProposer + marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -125,7 +125,7 @@ describe('MarketUpdateProposer', function() { // this will fail because the signer is not the multisig await expect( - marketUpdateProposer + marketUpdateProposerContract .connect(alice) .propose( [configuratorProxy.address], @@ -134,12 +134,12 @@ describe('MarketUpdateProposer', function() { [setSupplyKinkCalldata], proposalDescription ) - ).to.be.revertedWithCustomError(marketUpdateProposer,'Unauthorized'); + ).to.be.revertedWithCustomError(marketUpdateProposerContract,'Unauthorized'); }); it('keeps track of all the proposals', async () => { const { - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, } = await makeMarketAdmin(); @@ -154,7 +154,7 @@ describe('MarketUpdateProposer', function() { const proposalDescription = 'Test Proposal'; // Creates a proposal successfully as the signer is the multisig - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -165,7 +165,7 @@ describe('MarketUpdateProposer', function() { ); // Checks the proposal - const proposal = await marketUpdateProposer.getProposal(proposalId); + const proposal = await marketUpdateProposerContract.getProposal(proposalId); expect(proposal.id).to.equal(proposalId); expect(proposal.proposer).to.equal(marketUpdateMultiSig.address); @@ -180,7 +180,7 @@ describe('MarketUpdateProposer', function() { // Cancel the proposal // Check if the proposal is cancelled const { - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, } = await makeMarketAdmin(); @@ -195,7 +195,7 @@ describe('MarketUpdateProposer', function() { const proposalDescription = 'Test Proposal'; // Creates a proposal successfully as the signer is the multisig - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -206,18 +206,18 @@ describe('MarketUpdateProposer', function() { ); expect( - (await marketUpdateProposer.proposals(proposalId)).canceled + (await marketUpdateProposerContract.proposals(proposalId)).canceled ).to.be.equal(false); // Cancel the proposal - await marketUpdateProposer.connect(marketUpdateMultiSig).cancel(proposalId); + await marketUpdateProposerContract.connect(marketUpdateMultiSig).cancel(proposalId); expect( - (await marketUpdateProposer.proposals(proposalId)).canceled + (await marketUpdateProposerContract.proposals(proposalId)).canceled ).to.be.equal(true); await expect( - marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId) + marketUpdateProposerContract.connect(marketUpdateMultiSig).execute(proposalId) ).to.be.revertedWith( 'MarketUpdateProposer::execute: proposal can only be executed if it is queued' ); @@ -225,7 +225,7 @@ describe('MarketUpdateProposer', function() { it('marks the proposal as expired after grace period', async () => { const { - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, } = await makeMarketAdmin(); @@ -240,7 +240,7 @@ describe('MarketUpdateProposer', function() { const proposalDescription = 'Test Proposal'; // Creates a proposal successfully as the signer is the multisig - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -251,7 +251,7 @@ describe('MarketUpdateProposer', function() { ); // Get the timelock address from the MarketUpdateProposer contract - const timelockAddress = await marketUpdateProposer.timelock(); + const timelockAddress = await marketUpdateProposerContract.timelock(); // Create a contract instance for the timelock using its interface const timelockContract = await ethers.getContractAt( @@ -266,10 +266,10 @@ describe('MarketUpdateProposer', function() { const GRACE_PERIOD = 14 * 24 * 60 * 60; // 14 days in seconds await advanceTimeAndMineBlock(GRACE_PERIOD + delay + 1);// Increase by 14 days(GRACE_PERIOD) + timelock delay + 1 second - expect(await marketUpdateProposer.state(proposalId)).to.equal(3); // Proposal should be expired + expect(await marketUpdateProposerContract.state(proposalId)).to.equal(3); // Proposal should be expired await expect( - marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId) + marketUpdateProposerContract.connect(marketUpdateMultiSig).execute(proposalId) ).to.be.revertedWith( 'MarketUpdateProposer::execute: proposal can only be executed if it is queued' ); @@ -280,8 +280,8 @@ describe('MarketUpdateProposer', function() { const { governorTimelockSigner, marketUpdateMultiSig, - proposalGuardianSigner, - marketUpdateTimelock, + marketUpdateProposalGuardianSigner, + marketUpdateTimelockContract, } = await makeMarketAdmin(); const marketUpdaterProposerFactory = (await ethers.getContractFactory( @@ -293,8 +293,8 @@ describe('MarketUpdateProposer', function() { marketUpdaterProposerFactory.deploy( ethers.constants.AddressZero, marketUpdateMultiSig.address, - proposalGuardianSigner.address, - marketUpdateTimelock.address + marketUpdateProposalGuardianSigner.address, + marketUpdateTimelockContract.address ) ).to.be.revertedWithCustomError( marketUpdaterProposerFactory, @@ -306,8 +306,8 @@ describe('MarketUpdateProposer', function() { marketUpdaterProposerFactory.deploy( governorTimelockSigner.address, ethers.constants.AddressZero, - proposalGuardianSigner.address, - marketUpdateTimelock.address + marketUpdateProposalGuardianSigner.address, + marketUpdateTimelockContract.address ) ).to.be.revertedWithCustomError( marketUpdaterProposerFactory, @@ -318,7 +318,7 @@ describe('MarketUpdateProposer', function() { marketUpdaterProposerFactory.deploy( governorTimelockSigner.address, marketUpdateMultiSig.address, - proposalGuardianSigner.address, + marketUpdateProposalGuardianSigner.address, ethers.constants.AddressZero ) ).to.be.revertedWithCustomError( @@ -329,16 +329,16 @@ describe('MarketUpdateProposer', function() { const marketUpdateProposer = await marketUpdaterProposerFactory.deploy( governorTimelockSigner.address, marketUpdateMultiSig.address, - proposalGuardianSigner.address, - marketUpdateTimelock.address + marketUpdateProposalGuardianSigner.address, + marketUpdateTimelockContract.address ); expect(await marketUpdateProposer.governor()).to.be.equal(governorTimelockSigner.address); expect(await marketUpdateProposer.marketAdmin()).to.be.equal(marketUpdateMultiSig.address); expect(await marketUpdateProposer.proposalGuardian()).to.be.equal( - proposalGuardianSigner.address + marketUpdateProposalGuardianSigner.address ); - expect(await marketUpdateProposer.timelock()).to.be.equal(marketUpdateTimelock.address); + expect(await marketUpdateProposer.timelock()).to.be.equal(marketUpdateTimelockContract.address); }); @@ -346,87 +346,87 @@ describe('MarketUpdateProposer', function() { // include checks for proposalGuardian, marketAdmin, and nonGovernor for failure scenario const { governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, - proposalGuardianSigner, + marketUpdateProposalGuardianSigner, } = await makeMarketAdmin(); const { users: [alice, bob], } = await makeConfigurator(); - expect(await marketUpdateProposer.governor()).to.be.equal(governorTimelockSigner.address); + expect(await marketUpdateProposerContract.governor()).to.be.equal(governorTimelockSigner.address); // Ensure only the governor can set a new governor - await marketUpdateProposer + await marketUpdateProposerContract .connect(governorTimelockSigner) .setGovernor(alice.address); - expect(await marketUpdateProposer.governor()).to.equal(alice.address); + expect(await marketUpdateProposerContract.governor()).to.equal(alice.address); // failure case: market admin cannot update the governor await expect( - marketUpdateProposer.connect(marketUpdateMultiSig).setGovernor(alice.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(marketUpdateMultiSig).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // failure case: proposalGuardian cannot update the governor await expect( - marketUpdateProposer - .connect(proposalGuardianSigner) + marketUpdateProposerContract + .connect(marketUpdateProposalGuardianSigner) .setGovernor(alice.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // failure case: Non-governor cannot update the governor await expect( - marketUpdateProposer.connect(bob).setGovernor(alice.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(bob).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); }); it('only governor can update a marketAdmin', async () => { // include checks for proposalGuardian, marketAdmin, and nonGovernor for failure scenario const { governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, - proposalGuardianSigner, + marketUpdateProposalGuardianSigner, } = await makeMarketAdmin(); const { users: [alice, bob], } = await makeConfigurator(); - expect(await marketUpdateProposer.governor()).to.be.equal(governorTimelockSigner.address); + expect(await marketUpdateProposerContract.governor()).to.be.equal(governorTimelockSigner.address); // Ensure only the governor can set a new market admin - await marketUpdateProposer + await marketUpdateProposerContract .connect(governorTimelockSigner) .setMarketAdmin(alice.address); - expect(await marketUpdateProposer.marketAdmin()).to.equal(alice.address); + expect(await marketUpdateProposerContract.marketAdmin()).to.equal(alice.address); // failure case: market admin cannot update the market admin await expect( - marketUpdateProposer.connect(marketUpdateMultiSig).setMarketAdmin(alice.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(marketUpdateMultiSig).setMarketAdmin(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // failure case: proposalGuardian cannot update the market admin await expect( - marketUpdateProposer - .connect(proposalGuardianSigner) + marketUpdateProposerContract + .connect(marketUpdateProposalGuardianSigner) .setMarketAdmin(alice.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // failure case: Non-governor cannot update the market admin await expect( - marketUpdateProposer.connect(bob).setGovernor(alice.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(bob).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); }); it('only governor can update a proposalGuardian', async () => { // include checks for proposalGuardian, marketAdmin, and nonGovernor for failure scenario const { governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, } = await makeMarketAdmin(); @@ -434,44 +434,44 @@ describe('MarketUpdateProposer', function() { users: [alice, bob, john], } = await makeConfigurator(); - expect(await marketUpdateProposer.governor()).to.be.equal(governorTimelockSigner.address); + expect(await marketUpdateProposerContract.governor()).to.be.equal(governorTimelockSigner.address); // Ensure only the governor can set a new proposalGuardian - await marketUpdateProposer + await marketUpdateProposerContract .connect(governorTimelockSigner) .setProposalGuardian(alice.address); - expect(await marketUpdateProposer.proposalGuardian()).to.equal(alice.address); + expect(await marketUpdateProposerContract.proposalGuardian()).to.equal(alice.address); // failure case: market admin cannot update the proposalGuardian await expect( - marketUpdateProposer.connect(marketUpdateMultiSig).setProposalGuardian(bob.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(marketUpdateMultiSig).setProposalGuardian(bob.address) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // failure case: proposalGuardian cannot update the proposalGuardian // alice is the proposalGuardian by the above governor call await expect( - marketUpdateProposer.connect(alice).setProposalGuardian(bob.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(alice).setProposalGuardian(bob.address) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // failure case: Non-governor cannot update the proposalGuardian await expect( - marketUpdateProposer.connect(john).setGovernor(alice.address) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(john).setGovernor(alice.address) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); }); it('only marketAdmin can create a proposal', async () => { // include checks for proposalGuardian, governor, and anonymous address const { governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, - proposalGuardianSigner, + marketUpdateProposalGuardianSigner, } = await makeMarketAdmin(); const { configuratorProxy, cometProxy, users: [alice] } = await makeConfigurator(); - expect(await marketUpdateProposer.marketAdmin()).to.be.equal( + expect(await marketUpdateProposerContract.marketAdmin()).to.be.equal( marketUpdateMultiSig.address ); @@ -483,7 +483,7 @@ describe('MarketUpdateProposer', function() { const proposalDescription = 'Test Proposal'; // only MarketAdmin can create a proposal - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -495,7 +495,7 @@ describe('MarketUpdateProposer', function() { // Failure case: Governor cannot create a proposal await expect( - marketUpdateProposer + marketUpdateProposerContract .connect(governorTimelockSigner) .propose( [configuratorProxy.address], @@ -504,12 +504,12 @@ describe('MarketUpdateProposer', function() { [setSupplyKinkCalldata], proposalDescription ) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // Failure case: proposalGuardian cannot create a proposal await expect( - marketUpdateProposer - .connect(proposalGuardianSigner) + marketUpdateProposerContract + .connect(marketUpdateProposalGuardianSigner) .propose( [configuratorProxy.address], [0], @@ -517,11 +517,11 @@ describe('MarketUpdateProposer', function() { [setSupplyKinkCalldata], proposalDescription ) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // Failure case: anonymous cannot create a proposal await expect( - marketUpdateProposer + marketUpdateProposerContract .connect(alice) .propose( [configuratorProxy.address], @@ -530,17 +530,18 @@ describe('MarketUpdateProposer', function() { [setSupplyKinkCalldata], proposalDescription ) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); }); it('only marketAdmin can execute a proposal', async () => { // include checks for proposalGuardian, marketAdmin, governor, and anonymous address const { governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, - marketUpdateTimelock, - proposalGuardianSigner, + marketUpdateTimelockContract, + marketUpdateProposalGuardianSigner, + marketAdminPermissionCheckerContract } = await makeMarketAdmin(); const { @@ -549,10 +550,10 @@ describe('MarketUpdateProposer', function() { cometProxy, users: [bob], } = await makeConfigurator( - {governor: governorTimelockSigner} + { governor: governorTimelockSigner, marketAdminPermissionCheckerContract: marketAdminPermissionCheckerContract } ); - expect(await marketUpdateProposer.marketAdmin()).to.be.equal( + expect(await marketUpdateProposerContract.marketAdmin()).to.be.equal( marketUpdateMultiSig.address ); @@ -564,7 +565,7 @@ describe('MarketUpdateProposer', function() { const proposalDescription = 'Test Proposal'; // only MarketAdmin can create a proposal - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -574,7 +575,7 @@ describe('MarketUpdateProposer', function() { proposalDescription ); - const delay = (await marketUpdateTimelock.delay()).toNumber(); // Example: 172800 for 2 days + const delay = (await marketUpdateTimelockContract.delay()).toNumber(); // Example: 172800 for 2 days // Fast-forward time by delay + few seconds to surpass the eta await advanceTimeAndMineBlock(delay); @@ -582,38 +583,50 @@ describe('MarketUpdateProposer', function() { // Failure case: Governor cannot execute the proposal await expect( - marketUpdateProposer.connect(governorTimelockSigner).execute(proposalId) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(governorTimelockSigner).execute(proposalId) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // Failure case: proposalGuardian cannot execute the proposal await expect( - marketUpdateProposer.connect(proposalGuardianSigner).execute(proposalId) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(marketUpdateProposalGuardianSigner).execute(proposalId) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // Failure case: anonymous cannot execute the proposal await expect( - marketUpdateProposer.connect(bob).execute(proposalId) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(bob).execute(proposalId) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); // Success case: only MarketAdmin can execute the proposal const configuratorAsProxy = configurator.attach(configuratorProxy.address); - await configuratorAsProxy.connect(governorTimelockSigner).setMarketAdmin(marketUpdateTimelock.address); - expect (await configuratorAsProxy.marketAdmin()).to.be.equal(marketUpdateTimelock.address); - await marketUpdateProposer.connect(marketUpdateMultiSig).execute(proposalId); + const marketAdminCheckerAddress = await configuratorAsProxy.marketAdminPermissionChecker(); + const MarketAdminPermissionChecker = (await ethers.getContractFactory( + 'MarketAdminPermissionChecker' + )) as MarketAdminPermissionChecker__factory; + const marketAdminCheckerInstance = MarketAdminPermissionChecker.attach( + marketAdminCheckerAddress + ); + await marketAdminCheckerInstance + .connect(governorTimelockSigner) + .setMarketAdmin(marketUpdateTimelockContract.address); + + expect(await marketAdminCheckerInstance.marketAdmin()).to.be.equal( + marketUpdateTimelockContract.address + ); + await marketUpdateProposerContract.connect(marketUpdateMultiSig).execute(proposalId); }); it('only marketAdmin, proposalGuardian, or governor can cancel a proposal', async () => { // include checks for proposalGuardian, marketAdmin, and governor, and anonymous address const { governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, - proposalGuardianSigner, + marketUpdateProposalGuardianSigner, } = await makeMarketAdmin(); const { configuratorProxy, cometProxy, users: [bob] } = await makeConfigurator(); - expect(await marketUpdateProposer.marketAdmin()).to.be.equal( + expect(await marketUpdateProposerContract.marketAdmin()).to.be.equal( marketUpdateMultiSig.address ); @@ -625,7 +638,7 @@ describe('MarketUpdateProposer', function() { const proposalDescription = 'Test Proposal'; // only MarketAdmin can create a proposal - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -637,22 +650,22 @@ describe('MarketUpdateProposer', function() { const proposalId = 1n; // Success case: Governor can cancel the proposal - expect(await marketUpdateProposer.connect(governorTimelockSigner).cancel(proposalId)); + expect(await marketUpdateProposerContract.connect(governorTimelockSigner).cancel(proposalId)); // Success case: MarketAdmin can cancel the proposal - await marketUpdateProposer.connect(marketUpdateMultiSig).cancel(proposalId); + await marketUpdateProposerContract.connect(marketUpdateMultiSig).cancel(proposalId); // Success case: proposalGuardian can cancel the proposal expect( - await marketUpdateProposer - .connect(proposalGuardianSigner) + await marketUpdateProposerContract + .connect(marketUpdateProposalGuardianSigner) .cancel(proposalId) ); // Failure case: anonymous cannot cancel the proposal await expect( - marketUpdateProposer.connect(bob).cancel(proposalId) - ).to.be.revertedWithCustomError(marketUpdateProposer, 'Unauthorized'); + marketUpdateProposerContract.connect(bob).cancel(proposalId) + ).to.be.revertedWithCustomError(marketUpdateProposerContract, 'Unauthorized'); }); }); diff --git a/test/marketupdates/market-update-timelock-test.ts b/test/marketupdates/market-update-timelock-test.ts index 246460d2..31a96a49 100644 --- a/test/marketupdates/market-update-timelock-test.ts +++ b/test/marketupdates/market-update-timelock-test.ts @@ -3,16 +3,16 @@ import { expect, makeConfigurator, ethers } from '../helpers'; describe('MarketUpdateTimelock', function() { it('is created properly with main-governor-timelock as governor', async () => { - const { marketUpdateTimelock, governorTimelockSigner } = await makeMarketAdmin(); + const { marketUpdateTimelockContract, governorTimelockSigner } = await makeMarketAdmin(); - expect(await marketUpdateTimelock.governor()).to.equal( + expect(await marketUpdateTimelockContract.governor()).to.equal( governorTimelockSigner.address ); }); it('only allows main-governor-timelock to set MarketUpdateProposer', async () => { const { - marketUpdateTimelock, + marketUpdateTimelockContract, governorTimelockSigner, } = await makeMarketAdmin(); @@ -20,16 +20,16 @@ describe('MarketUpdateTimelock', function() { users: [alice, bob], } = await makeConfigurator(); - await marketUpdateTimelock + await marketUpdateTimelockContract .connect(governorTimelockSigner) .setMarketUpdateProposer(alice.address); - expect(await marketUpdateTimelock.marketUpdateProposer()).to.equal( + expect(await marketUpdateTimelockContract.marketUpdateProposer()).to.equal( alice.address ); await expect( - marketUpdateTimelock.connect(bob).setMarketUpdateProposer(bob.address) + marketUpdateTimelockContract.connect(bob).setMarketUpdateProposer(bob.address) ).to.be.revertedWith( 'MarketUpdateTimelock::setMarketUpdateProposer: Call must come from governor.' ); @@ -38,9 +38,9 @@ describe('MarketUpdateTimelock', function() { it('only MarketUpdateProposer can queue transactions', async () => { // include checks for marketAdmin, governor, and anonymous address const { - marketUpdateTimelock, + marketUpdateTimelockContract, governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, } = await makeMarketAdmin(); @@ -51,7 +51,7 @@ describe('MarketUpdateTimelock', function() { } = await makeConfigurator(); // Get the delay from the contract - const delay = (await marketUpdateTimelock.delay()).toNumber(); // Example: 172800 for 2 days + const delay = (await marketUpdateTimelockContract.delay()).toNumber(); // Example: 172800 for 2 days const latestBlock = await ethers.provider.getBlock('latest'); const currentTimestamp = latestBlock.timestamp; @@ -60,7 +60,7 @@ describe('MarketUpdateTimelock', function() { const eta = currentTimestamp + delay + 5; // eta is current timestamp + delay + a few seconds // Success case: market update proposer can queue transactions - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -77,7 +77,7 @@ describe('MarketUpdateTimelock', function() { // Failure case: Main Governor Timelock cannot queue transactions await expect( - marketUpdateTimelock + marketUpdateTimelockContract .connect(governorTimelockSigner) .queueTransaction( configuratorProxy.address, @@ -95,7 +95,7 @@ describe('MarketUpdateTimelock', function() { // Failure case: none other than MarketUpdateProposer can queue transactions await expect( - marketUpdateTimelock + marketUpdateTimelockContract .connect(bob) .queueTransaction( configuratorProxy.address, @@ -114,9 +114,9 @@ describe('MarketUpdateTimelock', function() { it('only MarketUpdateProposer can execute transactions', async () => { const { - marketUpdateTimelock, + marketUpdateTimelockContract, governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, } = await makeMarketAdmin(); @@ -128,11 +128,11 @@ describe('MarketUpdateTimelock', function() { } = await makeConfigurator(); const configuratorAsProxy = configurator.attach(configuratorProxy.address); - configuratorAsProxy.transferGovernor(marketUpdateTimelock.address); + configuratorAsProxy.transferGovernor(marketUpdateTimelockContract.address); const proposalId = 1n; // Get the delay from the contract - const delay = (await marketUpdateTimelock.delay()).toNumber(); // Example: 172800 for 2 days + const delay = (await marketUpdateTimelockContract.delay()).toNumber(); // Example: 172800 for 2 days let latestBlock = await ethers.provider.getBlock('latest'); let currentTimestamp = latestBlock.timestamp; @@ -140,7 +140,7 @@ describe('MarketUpdateTimelock', function() { let eta = currentTimestamp + delay + 5; // Ensure eta is in the future // Success case: market update proposer can execute transactions - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -158,7 +158,7 @@ describe('MarketUpdateTimelock', function() { // Fast-forward time by delay + seconds to surpass the eta await advanceTimeAndMineBlock(delay); - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .execute(proposalId); @@ -169,7 +169,7 @@ describe('MarketUpdateTimelock', function() { eta = currentTimestamp + delay + 5; // Ensure eta is in the future - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -187,7 +187,7 @@ describe('MarketUpdateTimelock', function() { // Fast-forward time by delay + few seconds to surpass the eta await advanceTimeAndMineBlock(delay); - await expect(marketUpdateTimelock + await expect(marketUpdateTimelockContract .connect(governorTimelockSigner) .executeTransaction( configuratorProxy.address, @@ -208,7 +208,7 @@ describe('MarketUpdateTimelock', function() { eta = currentTimestamp + delay + 5; // Ensure eta is in the future - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -227,7 +227,7 @@ describe('MarketUpdateTimelock', function() { await advanceTimeAndMineBlock(delay); await expect( - marketUpdateTimelock + marketUpdateTimelockContract .connect(bob) .executeTransaction( configuratorProxy.address, @@ -246,9 +246,9 @@ describe('MarketUpdateTimelock', function() { it('only MarketUpdateProposer can cancel transactions', async () => { const { - marketUpdateTimelock, + marketUpdateTimelockContract, governorTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, marketUpdateMultiSig, } = await makeMarketAdmin(); @@ -260,12 +260,12 @@ describe('MarketUpdateTimelock', function() { } = await makeConfigurator(); const configuratorAsProxy = configurator.attach(configuratorProxy.address); - await configuratorAsProxy.transferGovernor(marketUpdateTimelock.address); + await configuratorAsProxy.transferGovernor(marketUpdateTimelockContract.address); const proposalId = 1n; // Get the delay from the contract - const delay = (await marketUpdateTimelock.delay()).toNumber(); // Example: 172800 for 2 days + const delay = (await marketUpdateTimelockContract.delay()).toNumber(); // Example: 172800 for 2 days let latestBlock = await ethers.provider.getBlock('latest'); let currentTimestamp = latestBlock.timestamp; @@ -273,7 +273,7 @@ describe('MarketUpdateTimelock', function() { let eta = currentTimestamp + delay + 5; // Ensure eta is in the future // Success case: MarketUpdateProposer can cancel transactions - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -288,7 +288,7 @@ describe('MarketUpdateTimelock', function() { 'Setting supply kink to 100' ); - await marketUpdateProposer.connect(marketUpdateMultiSig).cancel(proposalId); + await marketUpdateProposerContract.connect(marketUpdateMultiSig).cancel(proposalId); // Checking the state of the transaction using the txHash const txHash = ethers.utils.keccak256( @@ -307,12 +307,12 @@ describe('MarketUpdateTimelock', function() { ) ); - expect(await marketUpdateTimelock.queuedTransactions(txHash)).to.equal( + expect(await marketUpdateTimelockContract.queuedTransactions(txHash)).to.equal( false ); // Failure case: Main Governor Timelock cannot cancel transactions - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -327,7 +327,7 @@ describe('MarketUpdateTimelock', function() { 'Setting supply kink to 100' ); - await expect(marketUpdateTimelock + await expect(marketUpdateTimelockContract .connect(governorTimelockSigner) .cancelTransaction( configuratorProxy.address, @@ -348,7 +348,7 @@ describe('MarketUpdateTimelock', function() { eta = currentTimestamp + delay + 5; // Ensure eta is in the future - await marketUpdateProposer + await marketUpdateProposerContract .connect(marketUpdateMultiSig) .propose( [configuratorProxy.address], @@ -364,7 +364,7 @@ describe('MarketUpdateTimelock', function() { ); await expect( - marketUpdateTimelock + marketUpdateTimelockContract .connect(bob) .cancelTransaction( configuratorProxy.address, @@ -383,7 +383,7 @@ describe('MarketUpdateTimelock', function() { it('only main-governor-timelock can set new governor', async () => { const { - marketUpdateTimelock, + marketUpdateTimelockContract, governorTimelockSigner, } = await makeMarketAdmin(); @@ -391,14 +391,14 @@ describe('MarketUpdateTimelock', function() { users: [alice, bob], } = await makeConfigurator(); - await marketUpdateTimelock + await marketUpdateTimelockContract .connect(governorTimelockSigner) .setGovernor(alice.address); - expect(await marketUpdateTimelock.governor()).to.equal(alice.address); + expect(await marketUpdateTimelockContract.governor()).to.equal(alice.address); await expect( - marketUpdateTimelock.connect(bob).setGovernor(bob.address) + marketUpdateTimelockContract.connect(bob).setGovernor(bob.address) ).to.be.revertedWith( 'MarketUpdateTimelock::setGovernor: Call must come from governor.' ); @@ -406,7 +406,7 @@ describe('MarketUpdateTimelock', function() { it('MarketUpdateProposer cannot set or update MarketUpdateProposer', async () => { const { - marketUpdateTimelock, + marketUpdateTimelockContract, marketUpdateMultiSig, } = await makeMarketAdmin(); @@ -415,7 +415,7 @@ describe('MarketUpdateTimelock', function() { } = await makeConfigurator(); await expect( - marketUpdateTimelock + marketUpdateTimelockContract .connect(marketUpdateMultiSig) .setMarketUpdateProposer(bob.address) ).to.be.revertedWith( @@ -425,7 +425,7 @@ describe('MarketUpdateTimelock', function() { it('MarketUpdateProposer cannot set or update main-governor-timelock', async () => { const { - marketUpdateTimelock, + marketUpdateTimelockContract, marketUpdateMultiSig, } = await makeMarketAdmin(); @@ -434,9 +434,9 @@ describe('MarketUpdateTimelock', function() { } = await makeConfigurator(); await expect( - marketUpdateTimelock.connect(marketUpdateMultiSig).setGovernor(bob.address) + marketUpdateTimelockContract.connect(marketUpdateMultiSig).setGovernor(bob.address) ).to.be.revertedWith( 'MarketUpdateTimelock::setGovernor: Call must come from governor.' ); }); -}); \ No newline at end of file +}); diff --git a/test/marketupdates/market-updates-helper.ts b/test/marketupdates/market-updates-helper.ts index 785ac31f..c44a0d28 100644 --- a/test/marketupdates/market-updates-helper.ts +++ b/test/marketupdates/market-updates-helper.ts @@ -1,7 +1,7 @@ import { SimpleTimelock__factory, MarketUpdateTimelock__factory, - MarketUpdateProposer__factory, + MarketUpdateProposer__factory, MarketAdminPermissionChecker__factory, } from './../../build/types'; import hre from 'hardhat'; import { ethers, expect } from './../helpers'; @@ -14,17 +14,18 @@ export async function makeMarketAdmin() { const signers = await ethers.getSigners(); const marketUpdateMultiSig = signers[10]; - const proposalGuardianSigner = signers[11]; - + const marketUpdateProposalGuardianSigner = signers[11]; + const marketAdminPauseGuardianSigner = signers[9]; + const marketAdminTimelockFactory = (await ethers.getContractFactory( 'MarketUpdateTimelock' )) as MarketUpdateTimelock__factory; - const marketUpdateTimelock = await marketAdminTimelockFactory.deploy( + const marketUpdateTimelockContract = await marketAdminTimelockFactory.deploy( governorTimelockSigner.address, 2 * 24 * 60 * 60 // This is 2 days in seconds ); - const marketUpdateTimelockAddress = await marketUpdateTimelock.deployed(); + const marketUpdateTimelockAddress = await marketUpdateTimelockContract.deployed(); // Impersonate the account await hre.network.provider.request({ @@ -34,7 +35,7 @@ export async function makeMarketAdmin() { // Fund the impersonated account await signers[0].sendTransaction({ - to: marketUpdateTimelock.address, + to: marketUpdateTimelockContract.address, value: ethers.utils.parseEther('1.0'), // Sending 1 Ether to cover gas fees }); @@ -54,28 +55,47 @@ export async function makeMarketAdmin() { }); // This sets the owner of the MarketUpdateProposer to the marketUpdateMultiSig - const marketUpdateProposer = await marketUpdaterProposerFactory.deploy( + const marketUpdateProposerContract = await marketUpdaterProposerFactory.deploy( governorTimelockSigner.address, marketUpdateMultiSig.address, - proposalGuardianSigner.address, - marketUpdateTimelock.address + marketUpdateProposalGuardianSigner.address, + marketUpdateTimelockContract.address ); - expect(await marketUpdateProposer.governor()).to.be.equal( + expect(await marketUpdateProposerContract.governor()).to.be.equal( governorTimelockSigner.address ); - await marketUpdateTimelock + await marketUpdateTimelockContract .connect(governorTimelockSigner) - .setMarketUpdateProposer(marketUpdateProposer.address); + .setMarketUpdateProposer(marketUpdateProposerContract.address); + + const MarketAdminPermissionCheckerFactory = (await ethers.getContractFactory( + 'MarketAdminPermissionChecker' + )) as MarketAdminPermissionChecker__factory; + + + const marketAdminPermissionCheckerContract = await MarketAdminPermissionCheckerFactory.deploy( + marketUpdateTimelockContract.address, + marketAdminPauseGuardianSigner.address + ); + await marketAdminPermissionCheckerContract.transferOwnership(governorTimelockSigner.address); + + await marketUpdateTimelockContract + .connect(governorTimelockSigner) + .setMarketUpdateProposer(marketUpdateProposerContract.address); return { - governorTimelockSigner, - marketUpdateMultiSig, - proposalGuardianSigner, - marketUpdateTimelock, - marketUpdateTimelockSigner, - marketUpdateProposer, + marketUpdateProposerContract, + marketAdminPermissionCheckerContract, + marketUpdateTimelockContract, + + governorTimelockSigner, // used to impersonate the main governor timelock + + marketUpdateMultiSig, // used to impersonate the market update multisig + marketAdminPauseGuardianSigner, // used to impersonate the market admin pause guardian + marketUpdateProposalGuardianSigner, // used to impersonate the market update proposal guardian + marketUpdateTimelockSigner, // used to impersonate the market update timelock }; } @@ -109,3 +129,17 @@ export async function advanceTimeAndMineBlock(delay: number) { await ethers.provider.send('evm_increaseTime', [delay + 10]); await ethers.provider.send('evm_mine', []); // Mine a new block to apply the time increase } + + +export async function createRandomWallet() { + const signers = await ethers.getSigners(); + const gov = signers[0]; + const random = ethers.Wallet.createRandom({}); + random.connect(ethers.providers.getDefaultProvider()); + + await gov.sendTransaction({ + to: random.address, + value: ethers.utils.parseEther('100.0'), // Sending 1 Ether to cover gas fees + }); + return random.connect(gov.provider); +} From f05d35c48fcb0b79a2e949796ccba32bcbfa7ad0 Mon Sep 17 00:00:00 2001 From: Robin Nagpal Date: Thu, 3 Oct 2024 18:18:08 -0400 Subject: [PATCH 08/28] L2 market tests (#39) --- .gitignore | 2 + contracts/CometProxyAdmin.sol | 6 + contracts/Create2DeployerInterface.sol | 19 + contracts/IGovernorBravo.sol | 9 +- .../marketupdates/CometProxyAdminOld.sol | 7 + .../MarketAdminPermissionChecker.sol | 5 +- contracts/vendor/access/Ownable.sol | 54 +- .../vendor/proxy/transparent/ProxyAdmin.sol | 8 +- forge/lib/forge-std | 2 +- .../marketupdates/DeployContracts.s.sol | 50 + .../marketupdates/GovernorProposal.s.sol | 44 + .../marketupdates/helpers/BridgeHelper.sol | 118 + .../marketupdates/helpers/ChainAddresses.sol | 117 + .../helpers/DeployedAddresses.sol | 11 + .../helpers/GovernanceHelper.sol | 222 + .../marketupdates/helpers/MarketAddresses.sol | 129 + .../helpers/MarketUpdateAddresses.sol | 57 + .../helpers/MarketUpdateContractsDeployer.sol | 176 + forge/simulate.md | 6 + .../MarketUpdateArbitrumDeploymentTest.t.sol | 79 + .../test/MarketUpdateBaseDeploymentTest.t.sol | 65 + forge/test/MarketUpdateDeploymentBaseTest.sol | 205 + .../MarketUpdateMainnetDeploymentTest.t.sol | 71 + .../MarketUpdateOptimismDeploymentTest.t.sol | 65 + .../MarketUpdatePolygonDeploymentTest.t.sol | 51 + .../MarketUpdateScrollDeploymentTest.t.sol | 37 + foundry.toml | 17 + hardhat.config.ts | 55 + package.json | 3 +- remappings.txt | 6 + scripts/marketupdates/deploy.ts | 144 + scripts/marketupdates/deploySafe.ts | 80 + yarn.lock | 10716 +++++++--------- 33 files changed, 6809 insertions(+), 5827 deletions(-) create mode 100644 contracts/Create2DeployerInterface.sol create mode 100644 forge/script/marketupdates/DeployContracts.s.sol create mode 100644 forge/script/marketupdates/GovernorProposal.s.sol create mode 100644 forge/script/marketupdates/helpers/BridgeHelper.sol create mode 100644 forge/script/marketupdates/helpers/ChainAddresses.sol create mode 100644 forge/script/marketupdates/helpers/DeployedAddresses.sol create mode 100644 forge/script/marketupdates/helpers/GovernanceHelper.sol create mode 100644 forge/script/marketupdates/helpers/MarketAddresses.sol create mode 100644 forge/script/marketupdates/helpers/MarketUpdateAddresses.sol create mode 100644 forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol create mode 100644 forge/simulate.md create mode 100644 forge/test/MarketUpdateArbitrumDeploymentTest.t.sol create mode 100644 forge/test/MarketUpdateBaseDeploymentTest.t.sol create mode 100644 forge/test/MarketUpdateDeploymentBaseTest.sol create mode 100644 forge/test/MarketUpdateMainnetDeploymentTest.t.sol create mode 100644 forge/test/MarketUpdateOptimismDeploymentTest.t.sol create mode 100644 forge/test/MarketUpdatePolygonDeploymentTest.t.sol create mode 100644 forge/test/MarketUpdateScrollDeploymentTest.t.sol create mode 100644 remappings.txt create mode 100644 scripts/marketupdates/deploy.ts create mode 100644 scripts/marketupdates/deploySafe.ts diff --git a/.gitignore b/.gitignore index def80361..53901c04 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ scenario-results.json *.iml deployments/localhost/dai/roots.json +forge/Makefile +.envrc diff --git a/contracts/CometProxyAdmin.sol b/contracts/CometProxyAdmin.sol index 866ff0ec..09ddbaf2 100644 --- a/contracts/CometProxyAdmin.sol +++ b/contracts/CometProxyAdmin.sol @@ -25,6 +25,12 @@ contract CometProxyAdmin is ProxyAdmin { _; } + /** + * @dev Initializes the contract setting the specified address as the initial owner. + * @param initialOwner The address to set as the owner of the contract. + */ + constructor(address initialOwner) ProxyAdmin(initialOwner) {} + /** * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy * Requirements: diff --git a/contracts/Create2DeployerInterface.sol b/contracts/Create2DeployerInterface.sol new file mode 100644 index 00000000..e8e0223c --- /dev/null +++ b/contracts/Create2DeployerInterface.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +interface ICreate2Deployer { + /** + * @dev Deploys a contract using `CREATE2`. + * @param value Amount of ETH to send with the contract creation. + * @param salt A unique salt used to compute the deployment address. + * @param code The bytecode of the contract to deploy. + */ + function deploy(uint256 value, bytes32 salt, bytes memory code) external; + + /** + * @dev Returns the address where a contract will be stored if deployed via `deploy`. + * @param salt A unique salt used to compute the deployment address. + * @param codeHash The keccak256 hash of the contract bytecode. + */ + function computeAddress(bytes32 salt, bytes32 codeHash) external view returns (address); +} diff --git a/contracts/IGovernorBravo.sol b/contracts/IGovernorBravo.sol index 99e0f00f..61796c07 100644 --- a/contracts/IGovernorBravo.sol +++ b/contracts/IGovernorBravo.sol @@ -71,4 +71,11 @@ interface IGovernorBravo { string[] memory signatures, bytes[] memory calldatas ); -} \ No newline at end of file + + function castVoteWithReason( + uint proposalId, + uint8 support, + string calldata reason + ) external; + function quorumVotes() external view returns (uint256); +} diff --git a/contracts/marketupdates/CometProxyAdminOld.sol b/contracts/marketupdates/CometProxyAdminOld.sol index 772d015d..a168369d 100644 --- a/contracts/marketupdates/CometProxyAdminOld.sol +++ b/contracts/marketupdates/CometProxyAdminOld.sol @@ -11,6 +11,13 @@ interface Deployable { * @dev This contract is just to simulate the full deployment process of market updates. Should be deleted after the market updates are deployed. */ contract CometProxyAdminOld is ProxyAdmin { + + /** + * @dev Initializes the contract setting the specified address as the initial owner. + * @param initialOwner The address to set as the owner of the contract. + */ + constructor(address initialOwner) ProxyAdmin(initialOwner) {} + /** * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy * Requirements: diff --git a/contracts/marketupdates/MarketAdminPermissionChecker.sol b/contracts/marketupdates/MarketAdminPermissionChecker.sol index 249d6ba3..9720db5a 100644 --- a/contracts/marketupdates/MarketAdminPermissionChecker.sol +++ b/contracts/marketupdates/MarketAdminPermissionChecker.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.15; -import "../vendor/access/Ownable.sol"; +import "./../vendor/access/Ownable.sol"; import "./MarketAdminPermissionCheckerInterface.sol"; contract MarketAdminPermissionChecker is MarketAdminPermissionCheckerInterface, Ownable { @@ -22,10 +22,11 @@ contract MarketAdminPermissionChecker is MarketAdminPermissionCheckerInterface, * @notice Construct a new MarketAdminPermissionChecker contract. * Not adding any checks for zero address as it may be a deliberate choice to assign the zero address i.e. keep the * market updates disabled. + * @param initialOwner The address of the owner. * @param marketAdmin_ The address of the market admin. * @param marketAdminPauseGuardian_ The address of the market admin pause guardian. */ - constructor(address marketAdmin_, address marketAdminPauseGuardian_) { + constructor(address initialOwner, address marketAdmin_, address marketAdminPauseGuardian_) Ownable(initialOwner) { marketAdmin = marketAdmin_; marketAdminPauseGuardian = marketAdminPauseGuardian_; } diff --git a/contracts/vendor/access/Ownable.sol b/contracts/vendor/access/Ownable.sol index 0b2ca8e3..ec4d952c 100644 --- a/contracts/vendor/access/Ownable.sol +++ b/contracts/vendor/access/Ownable.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) +// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) -pragma solidity ^0.8.0; +pragma solidity ^0.8.15; -import "../utils/Context.sol"; +import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. + * The initial owner is set to the address provided by the deployer. This can + * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to @@ -20,13 +20,34 @@ import "../utils/Context.sol"; abstract contract Ownable is Context { address private _owner; + /** + * @dev The caller account is not authorized to perform an operation. + */ + error OwnableUnauthorizedAccount(address account); + + /** + * @dev The owner is not a valid owner account. (eg. `address(0)`) + */ + error OwnableInvalidOwner(address owner); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** - * @dev Initializes the contract setting the deployer as the initial owner. + * @dev Initializes the contract setting the address provided by the deployer as the initial owner. + */ + constructor(address initialOwner) { + if (initialOwner == address(0)) { + revert OwnableInvalidOwner(address(0)); + } + _transferOwnership(initialOwner); + } + + /** + * @dev Throws if called by any account other than the owner. */ - constructor() { - _transferOwnership(_msgSender()); + modifier onlyOwner() { + _checkOwner(); + _; } /** @@ -37,19 +58,20 @@ abstract contract Ownable is Context { } /** - * @dev Throws if called by any account other than the owner. + * @dev Throws if the sender is not the owner. */ - modifier onlyOwner() { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - _; + function _checkOwner() internal view virtual { + if (owner() != _msgSender()) { + revert OwnableUnauthorizedAccount(_msgSender()); + } } /** * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. + * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. + * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); @@ -60,7 +82,9 @@ abstract contract Ownable is Context { * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); + if (newOwner == address(0)) { + revert OwnableInvalidOwner(address(0)); + } _transferOwnership(newOwner); } diff --git a/contracts/vendor/proxy/transparent/ProxyAdmin.sol b/contracts/vendor/proxy/transparent/ProxyAdmin.sol index 83953429..0962a078 100644 --- a/contracts/vendor/proxy/transparent/ProxyAdmin.sol +++ b/contracts/vendor/proxy/transparent/ProxyAdmin.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol) -pragma solidity ^0.8.0; +pragma solidity ^0.8.15; import "./TransparentUpgradeableProxy.sol"; import "../../access/Ownable.sol"; @@ -11,6 +11,12 @@ import "../../access/Ownable.sol"; * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}. */ contract ProxyAdmin is Ownable { + + /** + * @dev Sets the initial owner who can perform upgrades. + */ + constructor(address initialOwner) Ownable(initialOwner) {} + /** * @dev Returns the current implementation of `proxy`. * diff --git a/forge/lib/forge-std b/forge/lib/forge-std index 2a2ce369..8f24d6b0 160000 --- a/forge/lib/forge-std +++ b/forge/lib/forge-std @@ -1 +1 @@ -Subproject commit 2a2ce3692b8c1523b29de3ec9d961ee9fbbc43a6 +Subproject commit 8f24d6b04c92975e0795b5868aa0d783251cdeaa diff --git a/forge/script/marketupdates/DeployContracts.s.sol b/forge/script/marketupdates/DeployContracts.s.sol new file mode 100644 index 00000000..b27437b5 --- /dev/null +++ b/forge/script/marketupdates/DeployContracts.s.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@forge-std/src/Script.sol"; +import "@forge-std/src/console.sol"; +import "@comet-contracts/marketupdates/MarketUpdateTimelock.sol"; +import "@comet-contracts/marketupdates/MarketUpdateProposer.sol"; +import "@comet-contracts/Configurator.sol"; +import "@comet-contracts/CometProxyAdmin.sol"; +import "@comet-contracts/marketupdates/MarketAdminPermissionChecker.sol"; +import "@comet-contracts/Create2DeployerInterface.sol"; +import "./helpers/MarketUpdateAddresses.sol"; +import "./helpers/MarketUpdateContractsDeployer.sol"; + +contract DeployContracts is Script { + address public deployedWalletAddress; + + struct ContractDeploymentParams { + bytes creationCode; + bytes constructorArgs; + bytes expectedRuntimeCode; + string contractName; + } + + function run() external { + address timelock = 0x6d903f6003cca6255D85CcA4D3B5E5146dC33925; + + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + + bytes32 salt = keccak256(abi.encodePacked("Salt-31")); + + /// Call library function + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer.deployContracts( + salt, + MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS, + MarketUpdateAddresses.MARKET_ADMIN_PAUSE_GUARDIAN_ADDRESS, + MarketUpdateAddresses.MARKET_UPDATE_PROPOSAL_GUARDIAN_ADDRESS, + timelock + ); + + /// Console log deployed contracts + console.log("MarketUpdateTimelock: ", deployedContracts.marketUpdateTimelock); + console.log("MarketUpdateProposer: ", deployedContracts.marketUpdateProposer); + console.log("NewConfiguratorImplementation: ", deployedContracts.newConfiguratorImplementation); + console.log("NewCometProxyAdmin: ", deployedContracts.newCometProxyAdmin); + console.log("MarketAdminPermissionChecker: ", deployedContracts.marketAdminPermissionChecker); + + vm.stopBroadcast(); + } +} diff --git a/forge/script/marketupdates/GovernorProposal.s.sol b/forge/script/marketupdates/GovernorProposal.s.sol new file mode 100644 index 00000000..8b7e4055 --- /dev/null +++ b/forge/script/marketupdates/GovernorProposal.s.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@forge-std/src/Script.sol"; +import "@forge-std/src/console.sol"; + +import "@comet-contracts/IGovernorBravo.sol"; +import "@comet-contracts/IComp.sol"; +import "@comet-contracts/marketupdates/CometProxyAdminOld.sol"; + +import "./helpers/DeployedAddresses.sol"; +import "./helpers/GovernanceHelper.sol"; +import "./helpers/MarketUpdateAddresses.sol"; + +contract GovernorProposal is Script, DeployedAddresses { + + function run() external { + string memory chainName = vm.envString("CHAIN_NAME"); // Access the env variable + + // Define the address of the Governor Bravo Proxy + address governorBravoProxyAddress = 0xc0Da02939E1441F497fd74F78cE7Decb17B66529; + + // Cast the proxy address to the GovernorBravoDelegate interface + IGovernorBravo governorBravo = IGovernorBravo(governorBravoProxyAddress); + + + MarketUpdateAddresses.MarketUpdateAddressesStruct memory addresses = MarketUpdateAddresses.getAddressesForChain(MarketUpdateAddresses.getChainFromString(chainName)); + uint256 proposalId = GovernanceHelper.createDeploymentProposal(vm, addresses, addresses); + + GovernanceHelper.moveProposalToActive(vm, proposalId); + + GovernanceHelper.voteOnProposal(vm, proposalId); + + GovernanceHelper.moveProposalToSucceed(vm, proposalId); + + governorBravo.queue(proposalId); + + GovernanceHelper.moveProposalToExecution(vm, proposalId); + + governorBravo.execute(proposalId); + + console.log("proposal state after execution: ", uint(governorBravo.state(proposalId))); + } +} diff --git a/forge/script/marketupdates/helpers/BridgeHelper.sol b/forge/script/marketupdates/helpers/BridgeHelper.sol new file mode 100644 index 00000000..19aa9bba --- /dev/null +++ b/forge/script/marketupdates/helpers/BridgeHelper.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import "./MarketUpdateAddresses.sol"; +import "./ChainAddresses.sol"; +import "./GovernanceHelper.sol"; +import "@comet-contracts/bridges/BaseBridgeReceiver.sol"; +import "@comet-contracts/bridges/arbitrum/ArbitrumBridgeReceiver.sol"; +import "@comet-contracts/bridges/optimism/OptimismBridgeReceiver.sol"; +import "@comet-contracts/bridges/optimism/IOvmL2CrossDomainMessengerInterface.sol"; +import "@comet-contracts/bridges/polygon/PolygonBridgeReceiver.sol"; +import "@comet-contracts/bridges/scroll/ScrollBridgeReceiver.sol"; +import "@comet-contracts/bridges/scroll/IScrollMessenger.sol"; +import "@comet-contracts/bridges/arbitrum/AddressAliasHelper.sol"; +import "@comet-contracts/ITimelock.sol"; + +library BridgeHelper { + + function simulateMessageAndExecuteProposal( + Vm vm, + ChainAddresses.Chain chain, + address messageSender, + GovernanceHelper.ProposalRequest memory proposalRequest + ) external { + bytes memory l2Payload = abi.encode( + proposalRequest.targets, + proposalRequest.values, + proposalRequest.signatures, + proposalRequest.calldatas + ); + + if (chain == ChainAddresses.Chain.ARBITRUM) { + ArbitrumBridgeReceiver arbitrumBridgeReceiver = ArbitrumBridgeReceiver(payable(ChainAddresses.ARBITRUM_BRIDGE_RECEIVER)); + + // Simulate message to receiver + address l2Address = AddressAliasHelper.applyL1ToL2Alias(messageSender); + vm.prank(l2Address); + address(arbitrumBridgeReceiver).call(l2Payload); + + // Advance timestamp and execute proposal + uint256 delay = ITimelock(ChainAddresses.ARBITRUM_LOCAL_TIMELOCK).delay(); + vm.warp(block.timestamp + delay + 10); + uint256 proposalId = arbitrumBridgeReceiver.proposalCount(); + arbitrumBridgeReceiver.executeProposal(proposalId); + + } else if (chain == ChainAddresses.Chain.OPTIMISM || chain == ChainAddresses.Chain.BASE) { + // Common setup for Optimism and Base + address crossDomainMessenger = 0x4200000000000000000000000000000000000007; + vm.prank(crossDomainMessenger); + address crossDomainMessengerImpl = 0xC0d3c0d3c0D3c0D3C0d3C0D3C0D3c0d3c0d30007; + + // Mock message sender + vm.mockCall( + crossDomainMessengerImpl, + abi.encodeWithSelector(IOvmL2CrossDomainMessengerInterface.xDomainMessageSender.selector), + abi.encode(messageSender) + ); + + if (chain == ChainAddresses.Chain.OPTIMISM) { + OptimismBridgeReceiver optimismBridgeReceiver = OptimismBridgeReceiver(payable(ChainAddresses.OPTIMISM_BRIDGE_RECEIVER)); + + address(optimismBridgeReceiver).call(l2Payload); + + uint256 delay = ITimelock(ChainAddresses.OPTIMISM_LOCAL_TIMELOCK).delay(); + vm.warp(block.timestamp + delay + 10); + uint256 proposalId = optimismBridgeReceiver.proposalCount(); + optimismBridgeReceiver.executeProposal(proposalId); + + } else { + // For Base chain + BaseBridgeReceiver baseBridgeReceiver = BaseBridgeReceiver(payable(ChainAddresses.BASE_BRIDGE_RECEIVER)); + + address(baseBridgeReceiver).call(l2Payload); + + uint256 delay = ITimelock(ChainAddresses.BASE_LOCAL_TIMELOCK).delay(); + vm.warp(block.timestamp + delay + 10); + uint256 proposalId = baseBridgeReceiver.proposalCount(); + baseBridgeReceiver.executeProposal(proposalId); + } + + } else if (chain == ChainAddresses.Chain.POLYGON) { + PolygonBridgeReceiver polygonBridgeReceiver = PolygonBridgeReceiver(payable(ChainAddresses.POLYGON_BRIDGE_RECEIVER)); + + address fxChild = 0x8397259c983751DAf40400790063935a11afa28a; + vm.prank(fxChild); + polygonBridgeReceiver.processMessageFromRoot( + 1, + MarketUpdateAddresses.GOVERNOR_BRAVO_TIMELOCK_ADDRESS, + l2Payload + ); + + uint256 delay = ITimelock(ChainAddresses.POLYGON_LOCAL_TIMELOCK).delay(); + vm.warp(block.timestamp + delay + 10); + uint256 proposalId = polygonBridgeReceiver.proposalCount(); + polygonBridgeReceiver.executeProposal(proposalId); + + } else if (chain == ChainAddresses.Chain.SCROLL) { + ScrollBridgeReceiver scrollBridgeReceiver = ScrollBridgeReceiver(payable(ChainAddresses.SCROLL_BRIDGE_RECEIVER)); + + address l2Messenger = 0x781e90f1c8Fc4611c9b7497C3B47F99Ef6969CbC; + vm.prank(l2Messenger); + + // Mock message sender + vm.mockCall( + l2Messenger, + abi.encodeWithSelector(IScrollMessenger.xDomainMessageSender.selector), + abi.encode(messageSender) + ); + + address(scrollBridgeReceiver).call(l2Payload); + + uint256 delay = ITimelock(ChainAddresses.SCROLL_LOCAL_TIMELOCK).delay(); + vm.warp(block.timestamp + delay + 10); + uint256 proposalId = scrollBridgeReceiver.proposalCount(); + scrollBridgeReceiver.executeProposal(proposalId); + } + } +} diff --git a/forge/script/marketupdates/helpers/ChainAddresses.sol b/forge/script/marketupdates/helpers/ChainAddresses.sol new file mode 100644 index 00000000..6cec498d --- /dev/null +++ b/forge/script/marketupdates/helpers/ChainAddresses.sol @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +library ChainAddresses { + + struct ChainAddressesStruct { + address governorTimelockAddress; + address configuratorProxyAddress; + address cometProxyAdminAddress; + } + + enum Chain { + ETHEREUM, + POLYGON, + ARBITRUM, + BASE, + SCROLL, + OPTIMISM + } + + + // Mainnet addresses + address constant public MAINNET_GOVERNOR_TIMELOCK = 0x6d903f6003cca6255D85CcA4D3B5E5146dC33925; // See - https://etherscan.io/address/0x6d903f6003cca6255D85CcA4D3B5E5146dC33925 + address constant public MAINNET_CONFIGURATOR_PROXY = 0x316f9708bB98af7dA9c68C1C3b5e79039cD336E3; // See - https://etherscan.io/address/0x316f9708bB98af7dA9c68C1C3b5e79039cD336E3 + address constant public MAINNET_COMET_PROXY_ADMIN = 0x1EC63B5883C3481134FD50D5DAebc83Ecd2E8779; // See - https://etherscan.io/address/0x1EC63B5883C3481134FD50D5DAebc83Ecd2E8779 + + // Polygon addresses + address constant public POLYGON_LOCAL_TIMELOCK = 0xCC3E7c85Bb0EE4f09380e041fee95a0caeDD4a02; // See - https://polygonscan.com/address/0xCC3E7c85Bb0EE4f09380e041fee95a0caeDD4a02 + address constant public POLYGON_CONFIGURATOR_PROXY = 0x83E0F742cAcBE66349E3701B171eE2487a26e738; // See - https://polygonscan.com/address/0x83E0F742cAcBE66349E3701B171eE2487a26e738 + address constant public POLYGON_COMET_PROXY_ADMIN = 0xd712ACe4ca490D4F3E92992Ecf3DE12251b975F9; // See - https://polygonscan.com/address/0xd712ACe4ca490D4F3E92992Ecf3DE12251b975F9 + address constant public POLYGON_BRIDGE_RECEIVER = 0x18281dfC4d00905DA1aaA6731414EABa843c468A; // See - https://polygonscan.com/address/0x18281dfC4d00905DA1aaA6731414EABa843c468A + + // Arbitrum addresses + address constant public ARBITRUM_LOCAL_TIMELOCK = 0x3fB4d38ea7EC20D91917c09591490Eeda38Cf88A; // See - https://arbiscan.io/address/0x3fB4d38ea7EC20D91917c09591490Eeda38Cf88A + address constant public ARBITRUM_CONFIGURATOR_PROXY = 0xb21b06D71c75973babdE35b49fFDAc3F82Ad3775; // See - https://arbiscan.io/address/0xb21b06D71c75973babdE35b49fFDAc3F82Ad3775 + address constant public ARBITRUM_COMET_PROXY_ADMIN = 0xD10b40fF1D92e2267D099Da3509253D9Da4D715e; // See - https://arbiscan.io/address/0xD10b40fF1D92e2267D099Da3509253D9Da4D715e + address constant public ARBITRUM_BRIDGE_RECEIVER = 0x42480C37B249e33aABaf4c22B20235656bd38068; // See - https://arbiscan.io/address/0x42480C37B249e33aABaf4c22B20235656bd38068 + + // Base addresses + address constant public BASE_LOCAL_TIMELOCK = 0xCC3E7c85Bb0EE4f09380e041fee95a0caeDD4a02; // See - https://basescan.org/address/0xCC3E7c85Bb0EE4f09380e041fee95a0caeDD4a02 + address constant public BASE_CONFIGURATOR_PROXY = 0x45939657d1CA34A8FA39A924B71D28Fe8431e581; // See - https://basescan.org/address/0x45939657d1CA34A8FA39A924B71D28Fe8431e581 + address constant public BASE_COMET_PROXY_ADMIN = 0xbdE8F31D2DdDA895264e27DD990faB3DC87b372d; // See - https://basescan.org/address/0xbdE8F31D2DdDA895264e27DD990faB3DC87b372d + address constant public BASE_BRIDGE_RECEIVER = 0x18281dfC4d00905DA1aaA6731414EABa843c468A; // See - https://basescan.org/address/0x18281dfC4d00905DA1aaA6731414EABa843c468A + + // Scroll addresses + address constant public SCROLL_LOCAL_TIMELOCK = 0xF6013e80E9e6AC211Cc031ad1CE98B3Aa20b73E4; // See - https://scrollscan.com/address/0xF6013e80E9e6AC211Cc031ad1CE98B3Aa20b73E4 + address constant public SCROLL_CONFIGURATOR_PROXY = 0xECAB0bEEa3e5DEa0c35d3E69468EAC20098032D7; // See - https://scrollscan.com/address/0xECAB0bEEa3e5DEa0c35d3E69468EAC20098032D7 + address constant public SCROLL_COMET_PROXY_ADMIN = 0x87A27b91f4130a25E9634d23A5B8E05e342bac50; // See - https://scrollscan.com/address/0x87A27b91f4130a25E9634d23A5B8E05e342bac50 + address constant public SCROLL_BRIDGE_RECEIVER = 0xC6bf5A64896D679Cf89843DbeC6c0f5d3C9b610D; // See - https://scrollscan.com/address/0xC6bf5A64896D679Cf89843DbeC6c0f5d3C9b610D + + // Optimism addresses + address constant public OPTIMISM_LOCAL_TIMELOCK = 0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07; // See - https://optimistic.etherscan.io/address/0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07 + address constant public OPTIMISM_CONFIGURATOR_PROXY = 0x84E93EC6170ED630f5ebD89A1AAE72d4F63f2713; // See - https://optimistic.etherscan.io/address/0x84E93EC6170ED630f5ebD89A1AAE72d4F63f2713 + address constant public OPTIMISM_COMET_PROXY_ADMIN = 0x3C30B5a5A04656565686f800481580Ac4E7ed178; // See - https://optimistic.etherscan.io/address/0x3C30B5a5A04656565686f800481580Ac4E7ed178 + address constant public OPTIMISM_BRIDGE_RECEIVER = 0xC3a73A70d1577CD5B02da0bA91C0Afc8fA434DAF; // See - https://optimistic.etherscan.io/address/0x18281dfC4d00905DA1aaA6731414EABa843c468A + + function getChainAddresses(Chain chain) internal pure returns (ChainAddressesStruct memory) { + if (chain == Chain.ETHEREUM) { + return ChainAddressesStruct({ + governorTimelockAddress: MAINNET_GOVERNOR_TIMELOCK, + configuratorProxyAddress: MAINNET_CONFIGURATOR_PROXY, + cometProxyAdminAddress: MAINNET_COMET_PROXY_ADMIN + }); + } else if (chain == Chain.POLYGON) { + return ChainAddressesStruct({ + governorTimelockAddress: POLYGON_LOCAL_TIMELOCK, + configuratorProxyAddress: POLYGON_CONFIGURATOR_PROXY, + cometProxyAdminAddress: POLYGON_COMET_PROXY_ADMIN + }); + } else if (chain == Chain.ARBITRUM) { + return ChainAddressesStruct({ + governorTimelockAddress: ARBITRUM_LOCAL_TIMELOCK, + configuratorProxyAddress: ARBITRUM_CONFIGURATOR_PROXY, + cometProxyAdminAddress: ARBITRUM_COMET_PROXY_ADMIN + }); + } else if (chain == Chain.BASE) { + return ChainAddressesStruct({ + governorTimelockAddress: BASE_LOCAL_TIMELOCK, + configuratorProxyAddress: BASE_CONFIGURATOR_PROXY, + cometProxyAdminAddress: BASE_COMET_PROXY_ADMIN + }); + } else if (chain == Chain.SCROLL) { + return ChainAddressesStruct({ + governorTimelockAddress: SCROLL_LOCAL_TIMELOCK, + configuratorProxyAddress: SCROLL_CONFIGURATOR_PROXY, + cometProxyAdminAddress: SCROLL_COMET_PROXY_ADMIN + }); + } else if (chain == Chain.OPTIMISM) { + return ChainAddressesStruct({ + governorTimelockAddress: OPTIMISM_LOCAL_TIMELOCK, + configuratorProxyAddress: OPTIMISM_CONFIGURATOR_PROXY, + cometProxyAdminAddress: OPTIMISM_COMET_PROXY_ADMIN + }); + } else { + revert("MarketUpdateAddresses: Chain not supported"); + } + } + + function getLocalTimelockAddress(Chain chain) internal pure returns (address) { + if (chain == Chain.ETHEREUM) { + return MAINNET_GOVERNOR_TIMELOCK; + } else if (chain == Chain.POLYGON) { + return POLYGON_LOCAL_TIMELOCK; + } else if (chain == Chain.ARBITRUM) { + return ARBITRUM_LOCAL_TIMELOCK; + } else if (chain == Chain.BASE) { + return BASE_LOCAL_TIMELOCK; + } else if (chain == Chain.SCROLL) { + return SCROLL_LOCAL_TIMELOCK; + } else if (chain == Chain.OPTIMISM) { + return OPTIMISM_LOCAL_TIMELOCK; + } else { + revert("MarketUpdateAddresses: Chain not supported"); + } + } + +} diff --git a/forge/script/marketupdates/helpers/DeployedAddresses.sol b/forge/script/marketupdates/helpers/DeployedAddresses.sol new file mode 100644 index 00000000..1fd1c580 --- /dev/null +++ b/forge/script/marketupdates/helpers/DeployedAddresses.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.15; + +contract DeployedAddresses { + address public constant computedMarketUpdateTimelockAddress = 0xd528bbD6912d08FAA3AaA41c3Ead5A23Db675c43; + address public constant computedMarketUpdateProposerAddress = 0xE97FBDfDDC9b13AB7339b7E7099ee96405dA880c; + address public constant computedConfiguratorAddress = 0x4618B5c7460911FB419FD6dF4ed274Ed64Ef5b12; + address public constant computedCometProxyAdminAddress = 0x0754f2f56281f77eD3Fb01E95031ab0Ce575CD48; + address public constant computedMarketAdminPermissionCheckerAddress = 0x6f886e3fD5eFd68Af38Cef0a3D4BC267d550D0d4; +} diff --git a/forge/script/marketupdates/helpers/GovernanceHelper.sol b/forge/script/marketupdates/helpers/GovernanceHelper.sol new file mode 100644 index 00000000..a642dd3a --- /dev/null +++ b/forge/script/marketupdates/helpers/GovernanceHelper.sol @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@forge-std/src/Vm.sol"; +import "@forge-std/src/console.sol"; +import "@comet-contracts/IGovernorBravo.sol"; +import "@comet-contracts/IComp.sol"; +import "@comet-contracts/marketupdates/MarketUpdateProposer.sol"; + +import "./MarketUpdateAddresses.sol"; + + +library GovernanceHelper { + uint constant public BLOCKS_PER_DAY = 7168; + + address constant governorBravoProxyAddress = 0xc0Da02939E1441F497fd74F78cE7Decb17B66529; + IGovernorBravo constant governorBravo = IGovernorBravo(governorBravoProxyAddress); + + address constant marketUpdateProposerAddress = 0x4c3B63642bC627735c0BFaB7332b96f3a2B0d476; + MarketUpdateProposer constant marketUpdateProposer = MarketUpdateProposer(marketUpdateProposerAddress); + + // COMP token address + address constant compTokenAddress = 0xc00e94Cb662C3520282E6f5717214004A7f26888; + IComp constant compToken = IComp(compTokenAddress); + + struct ProposalRequest { + address[] targets; + uint256[] values; + string[] signatures; + bytes[] calldatas; + } + + function createDeploymentProposalRequest(MarketUpdateAddresses.MarketUpdateAddressesStruct memory addresses) public pure returns (ProposalRequest memory) { + address cometProxyAdminOldAddress = addresses.cometProxyAdminAddress; + address configuratorProxyAddress = addresses.configuratorProxyAddress; + address configuratorNewAddress = addresses.configuratorImplementationAddress; + address cometProxyAdminNewAddress = addresses.newCometProxyAdminAddress; + address marketAdminPermissionCheckerAddress = addresses.marketAdminPermissionCheckerAddress; + address marketUpdateTimelockAddress = addresses.marketUpdateTimelockAddress; + address marketUpdateProposerAddress = addresses.marketAdminProposerAddress; + + // Dynamically allocate arrays based on the number of markets + uint256 numMarkets = addresses.markets.length; + uint256 totalTargets = 6 + numMarkets; // 6 fixed operations + numMarkets + address[] memory targets = new address[](totalTargets); + uint256[] memory values = new uint256[](totalTargets); + string[] memory signatures = new string[](totalTargets); + bytes[] memory calldatas = new bytes[](totalTargets); + + // First, handle market-specific operations + for (uint256 i = 0; i < numMarkets; i++) { + address cometProxyAddress = addresses.markets[i].cometProxyAddress; + + // Change Proxy Admin for each market + targets[i] = cometProxyAdminOldAddress; + signatures[i] = "changeProxyAdmin(address,address)"; + calldatas[i] = abi.encode(cometProxyAddress, cometProxyAdminNewAddress); + } + + // Now handle the fixed operations (5) + uint256 offset = numMarkets; + + // Change Proxy Admin for configurator proxy + targets[offset] = cometProxyAdminOldAddress; + signatures[offset] = "changeProxyAdmin(address,address)"; + calldatas[offset] = abi.encode(configuratorProxyAddress, cometProxyAdminNewAddress); + + // Upgrade configurator proxy + targets[offset + 1] = cometProxyAdminNewAddress; + signatures[offset + 1] = "upgrade(address,address)"; + calldatas[offset + 1] = abi.encode(configuratorProxyAddress, configuratorNewAddress); + + // Set Market Admin + targets[offset + 2] = marketAdminPermissionCheckerAddress; + signatures[offset + 2] = "setMarketAdmin(address)"; + calldatas[offset + 2] = abi.encode(marketUpdateTimelockAddress); + + // Set Market Admin Permission Checker on the configurator + targets[offset + 3] = configuratorProxyAddress; + signatures[offset + 3] = "setMarketAdminPermissionChecker(address)"; + calldatas[offset + 3] = abi.encode(marketAdminPermissionCheckerAddress); + + // Set Market Admin Permission Checker on the new comet proxy admin + targets[offset + 4] = cometProxyAdminNewAddress; + signatures[offset + 4] = "setMarketAdminPermissionChecker(address)"; + calldatas[offset + 4] = abi.encode(marketAdminPermissionCheckerAddress); + + // Set Market Update Proposer + targets[offset + 5] = marketUpdateTimelockAddress; + signatures[offset + 5] = "setMarketUpdateProposer(address)"; + calldatas[offset + 5] = abi.encode(marketUpdateProposerAddress); + + return ProposalRequest(targets, values, signatures, calldatas); + } + + function createDeploymentProposal(Vm vm, MarketUpdateAddresses.MarketUpdateAddressesStruct memory addresses, address proposalCreator) public returns (uint256) { + IGovernorBravo governorBravo = IGovernorBravo(MarketUpdateAddresses.GOVERNOR_BRAVO_PROXY_ADDRESS); + ProposalRequest memory proposalRequest = createDeploymentProposalRequest(addresses); + string memory description = "Proposal to trigger updates for market admin"; + vm.startBroadcast(proposalCreator); + uint256 proposalId = governorBravo.propose(proposalRequest.targets, proposalRequest.values, proposalRequest.signatures, proposalRequest.calldatas, description); + vm.stopBroadcast(); + return proposalId; + } + + function createProposalAndPass(Vm vm, ProposalRequest memory proposalRequest, string memory description) public { + // Create a proposal + address proposalCreator = getTopDelegates()[0]; + vm.startBroadcast(proposalCreator); + uint256 proposalId = governorBravo.propose(proposalRequest.targets, proposalRequest.values, proposalRequest.signatures, proposalRequest.calldatas, description); + vm.stopBroadcast(); + + // Move proposal to Active state + moveProposalToActive(vm, proposalId); + + // Vote on the proposal + voteOnProposal(vm, proposalId, proposalCreator); + + // Move proposal to Succeeded state + moveProposalToSucceed(vm, proposalId); + + // Queue the proposal + governorBravo.queue(proposalId); + + // Move proposal to Execution state + moveProposalToExecution(vm, proposalId); + } + + function createAndPassMarketUpdateProposal(Vm vm, ProposalRequest memory proposalRequest, string memory description) public { + vm.startPrank(MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS); + marketUpdateProposer.propose(proposalRequest.targets, proposalRequest.values, proposalRequest.signatures, proposalRequest.calldatas, description); + + // Fast forward by 5 days + vm.warp(block.timestamp + 5 days); + + marketUpdateProposer.execute(1); + + vm.stopPrank(); + } + + function createAndPassMarketUpdateProposalL2(Vm vm, ProposalRequest memory proposalRequest, string memory description, address marketUpdateProposer) public { + vm.startPrank(MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS); + MarketUpdateProposer(marketUpdateProposer).propose(proposalRequest.targets, proposalRequest.values, proposalRequest.signatures, proposalRequest.calldatas, description); + + // Fast forward by 5 days + vm.warp(block.timestamp + 5 days); + + MarketUpdateProposer(marketUpdateProposer).execute(1); + + vm.stopPrank(); + } + + function moveProposalToActive(Vm vm, uint proposalId) public { + require(governorBravo.state(proposalId) == IGovernorBravo.ProposalState.Pending, "Proposal is not Pending"); + require(governorBravo.proposals(proposalId).eta == 0, "Proposal has already been queued"); + + // Add a check to see the current state is pending + uint votingDelay = governorBravo.votingDelay(); + + vm.roll(block.number + votingDelay + 7146); + + require(governorBravo.state(proposalId) == IGovernorBravo.ProposalState.Active, "Proposal is not Active"); + + + } + + function moveProposalToSucceed(Vm vm, uint proposalId) public { + require(governorBravo.state(proposalId) == IGovernorBravo.ProposalState.Active, "Proposal is not Active"); + + + require(governorBravo.proposals(proposalId).forVotes > governorBravo.quorumVotes(), "Proposal does not have enough votes"); + // Advance to the end of the voting period + uint256 endBlock = governorBravo.proposals(proposalId).endBlock; + vm.roll(endBlock + 1); + + require(governorBravo.state(proposalId) == IGovernorBravo.ProposalState.Succeeded, "Proposal is not Succeeded"); + } + + function moveProposalToExecution(Vm vm, uint proposalId) public { + uint proposalEta = governorBravo.proposals(proposalId).eta; + require(proposalEta != 0, "Proposal has not been queued"); + + vm.warp(proposalEta + 2 days); + + require(block.timestamp >= proposalEta, "Time has not passed for proposal to be executed"); + governorBravo.execute(proposalId); + require(governorBravo.state(proposalId) == IGovernorBravo.ProposalState.Executed, "Proposal is not Executed"); + + } + + function voteOnProposal(Vm vm, uint256 proposalId, address proposalCreator) public { + address[12] memory voters = getTopDelegates(); + + // Cast votes from multiple accounts + for (uint i = 0; i < voters.length; i++) { + if (voters[i] == proposalCreator) continue; // Skip zero address + console.log("Voting with account: ", voters[i]); + vm.startBroadcast(voters[i]); + console.log("Proposal state during voting: ", uint(governorBravo.state(proposalId))); + governorBravo.castVoteWithReason(proposalId, 1, "yes"); // 1 = "For" vote + vm.stopBroadcast(); + console.log("Done voting with account: ", voters[i]); + } + } + + function getTopDelegates() public pure returns (address[12] memory) { + return [ + 0x0579A616689f7ed748dC07692A3F150D44b0CA09, + 0x9AA835Bc7b8cE13B9B0C9764A52FbF71AC62cCF1, + 0x7E959eAB54932f5cFd10239160a7fd6474171318, + 0x2210dc066aacB03C9676C4F1b36084Af14cCd02E, + 0x88F659b4B6D5614B991c6404b34f821e10390eC0, + 0x070341aA5Ed571f0FB2c4a5641409B1A46b4961b, + 0xdC1F98682F4F8a5c6d54F345F448437b83f5E432, + 0xB933AEe47C438f22DE0747D57fc239FE37878Dd1, + 0x2817Cb83c96a091E833A9A93E02D5464034e24f1, + 0x21b3B193B71680E2fAfe40768C03a0Fd305EFa75, + 0xE364E90d0A5289bF462A5c9f6e1CcAE680215413, + 0x3FB19771947072629C8EEE7995a2eF23B72d4C8A + ]; + } +} diff --git a/forge/script/marketupdates/helpers/MarketAddresses.sol b/forge/script/marketupdates/helpers/MarketAddresses.sol new file mode 100644 index 00000000..220f3797 --- /dev/null +++ b/forge/script/marketupdates/helpers/MarketAddresses.sol @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import "./ChainAddresses.sol"; + +library MarketAddresses { + + struct MarketInfo { + string baseTokenSymbol; + address cometProxyAddress; + } + + + address constant public MAINNET_USDC_MARKET = 0xc3d688B66703497DAA19211EEdff47f25384cdc3; // See - https://etherscan.io/address/0xc3d688B66703497DAA19211EEdff47f25384cdc3 + address constant public MAINNET_USDT_MARKET = 0x3Afdc9BCA9213A35503b077a6072F3D0d5AB0840; // See - https://etherscan.io/address/0x3Afdc9BCA9213A35503b077a6072F3D0d5AB0840 + address constant public MAINNET_ETH_MARKET = 0xA17581A9E3356d9A858b789D68B4d866e593aE94; // See - https://etherscan.io/address/0xA17581A9E3356d9A858b789D68B4d866e593aE94 + address constant public MAINNET_WST_ETH_MARKET = 0x3D0bb1ccaB520A66e607822fC55BC921738fAFE3; // See - https://etherscan.io/address/0x3D0bb1ccaB520A66e607822fC55BC921738fAFE3 + + address constant public POLYGON_USDCe_MARKET = 0xF25212E676D1F7F89Cd72fFEe66158f541246445; // See - https://polygonscan.com/address/0xF25212E676D1F7F89Cd72fFEe66158f541246445 + address constant public POLYGON_USDT_MARKET = 0xaeB318360f27748Acb200CE616E389A6C9409a07; // See - https://polygonscan.com/address/0xaeB318360f27748Acb200CE616E389A6C9409a07 + + address constant public ARBITRUM_USDCe_MARKET = 0xA5EDBDD9646f8dFF606d7448e414884C7d905dCA; // See - https://arbiscan.io/address/0xA5EDBDD9646f8dFF606d7448e414884C7d905dCA + address constant public ARBITRUM_USDC_MARKET = 0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf; // See - https://arbiscan.io/address/0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf + address constant public ARBITRUM_USDT_MARKET = 0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07; // See - https://arbiscan.io/address/0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07 + address constant public ARBITRUM_ETH_MARKET = 0x6f7D514bbD4aFf3BcD1140B7344b32f063dEe486; // See - https://arbiscan.io/address/0x6f7D514bbD4aFf3BcD1140B7344b32f063dEe486 + + address constant public BASE_USDC_MARKET = 0xb125E6687d4313864e53df431d5425969c15Eb2F; // See - https://basescan.org/address/0xb125E6687d4313864e53df431d5425969c15Eb2F + address constant public BASE_USDbC_MARKET = 0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf; // See - https://basescan.org/address/0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf + address constant public BASE_ETH_MARKET = 0x46e6b214b524310239732D51387075E0e70970bf; // See - https://basescan.org/address/0x46e6b214b524310239732D51387075E0e70970bf + + address constant public SCROLL_USDC_MARKET = 0xB2f97c1Bd3bf02f5e74d13f02E3e26F93D77CE44; // See - https://scrollscan.com/address/0xB2f97c1Bd3bf02f5e74d13f02E3e26F93D77CE44 + + address constant public OPTIMISM_USDC_MARKET = 0x2e44e174f7D53F0212823acC11C01A11d58c5bCB; // See - https://optimistic.etherscan.io/address/0x2e44e174f7D53F0212823acC11C01A11d58c5bCB + address constant public OPTIMISM_USDT_MARKET = 0x995E394b8B2437aC8Ce61Ee0bC610D617962B214; // See - https://optimistic.etherscan.io/address/0x995E394b8B2437aC8Ce61Ee0bC610D617962B214 + address constant public OPTIMISM_ETH_MARKET = 0xE36A30D249f7761327fd973001A32010b521b6Fd; // See - https://optimistic.etherscan.io/address/0xE36A30D249f7761327fd973001A32010b521b6Fd + + function getMarketsForChain(ChainAddresses.Chain chain) internal pure returns (MarketInfo[] memory) { + if (chain == ChainAddresses.Chain.ETHEREUM) { + MarketInfo[] memory markets = new MarketInfo[](4); + markets[0] = MarketInfo({ + baseTokenSymbol: "ETH", + cometProxyAddress: MAINNET_ETH_MARKET + }); + markets[1] = MarketInfo({ + baseTokenSymbol: "USDC", + cometProxyAddress: MAINNET_USDC_MARKET + }); + markets[2] = MarketInfo({ + baseTokenSymbol: "USDT", + cometProxyAddress: MAINNET_USDT_MARKET + }); + markets[3] = MarketInfo({ + baseTokenSymbol: "wstETH", + cometProxyAddress: MAINNET_WST_ETH_MARKET + }); + return markets; + } else if (chain == ChainAddresses.Chain.POLYGON) { + MarketInfo[] memory markets = new MarketInfo[](2); + markets[0] = MarketInfo({ + baseTokenSymbol: "USDC.e", + cometProxyAddress: POLYGON_USDCe_MARKET + }); + markets[1] = MarketInfo({ + baseTokenSymbol: "USDT", + cometProxyAddress: POLYGON_USDT_MARKET + }); + return markets; + } else if (chain == ChainAddresses.Chain.ARBITRUM) { + MarketInfo[] memory markets = new MarketInfo[](4); + markets[0] = MarketInfo({ + baseTokenSymbol: "USDC.e", + cometProxyAddress: ARBITRUM_USDCe_MARKET + }); + markets[1] = MarketInfo({ + baseTokenSymbol: "USDC", + cometProxyAddress: ARBITRUM_USDC_MARKET + }); + markets[2] = MarketInfo({ + baseTokenSymbol: "ETH", + cometProxyAddress: ARBITRUM_ETH_MARKET + }); + markets[3] = MarketInfo({ + baseTokenSymbol: "USDT", + cometProxyAddress: ARBITRUM_USDT_MARKET + }); + return markets; + } else if (chain == ChainAddresses.Chain.BASE) { + MarketInfo[] memory markets = new MarketInfo[](3); + markets[0] = MarketInfo({ + baseTokenSymbol: "USDC", + cometProxyAddress: BASE_USDC_MARKET + }); + markets[1] = MarketInfo({ + baseTokenSymbol: "USDbC", + cometProxyAddress: BASE_USDbC_MARKET + }); + markets[2] = MarketInfo({ + baseTokenSymbol: "ETH", + cometProxyAddress: BASE_ETH_MARKET + }); + return markets; + } else if (chain == ChainAddresses.Chain.SCROLL) { + MarketInfo[] memory markets = new MarketInfo[](1); + markets[0] = MarketInfo({ + baseTokenSymbol: "USDC", + cometProxyAddress: SCROLL_USDC_MARKET + }); + return markets; + } else if (chain == ChainAddresses.Chain.OPTIMISM) { + MarketInfo[] memory markets = new MarketInfo[](3); + markets[0] = MarketInfo({ + baseTokenSymbol: "USDC", + cometProxyAddress: OPTIMISM_USDC_MARKET + }); + markets[1] = MarketInfo({ + baseTokenSymbol: "USDT", + cometProxyAddress: OPTIMISM_USDT_MARKET + }); + markets[2] = MarketInfo({ + baseTokenSymbol: "ETH", + cometProxyAddress: OPTIMISM_ETH_MARKET + }); + return markets; + } + + revert("MarketUpdateAddresses: Chain not supported"); + } + +} diff --git a/forge/script/marketupdates/helpers/MarketUpdateAddresses.sol b/forge/script/marketupdates/helpers/MarketUpdateAddresses.sol new file mode 100644 index 00000000..f1a98f06 --- /dev/null +++ b/forge/script/marketupdates/helpers/MarketUpdateAddresses.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import "./MarketUpdateContractsDeployer.sol"; +import "./MarketAddresses.sol"; +import "./ChainAddresses.sol"; + +library MarketUpdateAddresses { + address public constant GOVERNOR_BRAVO_PROXY_ADDRESS = 0xc0Da02939E1441F497fd74F78cE7Decb17B66529; // See - https://etherscan.io/address/0xc0Da02939E1441F497fd74F78cE7Decb17B66529 + address public constant GOVERNOR_BRAVO_TIMELOCK_ADDRESS = 0x6d903f6003cca6255D85CcA4D3B5E5146dC33925; // See - https://etherscan.io/address/0x6d903f6003cca6255D85CcA4D3B5E5146dC33925 + + // Old Addresses + address public constant MARKET_ADMIN_PAUSE_GUARDIAN_ADDRESS = 0x7053e25f7076F4986D632A3C04313C81831e0d55; + address public constant MARKET_UPDATE_PROPOSAL_GUARDIAN_ADDRESS = 0x77B65c68E52C31eb844fb3b4864B91133e2C1308; + + // New Addresses + address public constant MARKET_UPDATE_MULTISIG_ADDRESS = 0x7053e25f7076F4986D632A3C04313C81831e0d55; + + struct MarketUpdateAddressesStruct { + // Old addresses + address governorTimelockAddress; + address configuratorProxyAddress; + address cometProxyAdminAddress; + MarketAddresses.MarketInfo[] markets; + + // New addresses + address marketUpdateMultiSigAddress; + address marketAdminProposerAddress; + address marketUpdateTimelockAddress; + address marketAdminPermissionCheckerAddress; + address configuratorImplementationAddress; + address newCometProxyAdminAddress; + } + + + function getAddressesForChain( + ChainAddresses.Chain chain, + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts, + address marketUpdateMultisig + ) public pure returns (MarketUpdateAddressesStruct memory) { + ChainAddresses.ChainAddressesStruct memory chainAddresses = ChainAddresses.getChainAddresses(chain); + MarketAddresses.MarketInfo[] memory markets = MarketAddresses.getMarketsForChain(chain); + + return MarketUpdateAddressesStruct({ + governorTimelockAddress: chainAddresses.governorTimelockAddress, + configuratorProxyAddress: chainAddresses.configuratorProxyAddress, + cometProxyAdminAddress: chainAddresses.cometProxyAdminAddress, + markets: markets, + marketUpdateMultiSigAddress: marketUpdateMultisig, + marketAdminProposerAddress: deployedContracts.marketUpdateProposer, + marketUpdateTimelockAddress: deployedContracts.marketUpdateTimelock, + marketAdminPermissionCheckerAddress: deployedContracts.marketAdminPermissionChecker, + configuratorImplementationAddress: deployedContracts.newConfiguratorImplementation, + newCometProxyAdminAddress: deployedContracts.newCometProxyAdmin + }); + } +} diff --git a/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol b/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol new file mode 100644 index 00000000..74d14b05 --- /dev/null +++ b/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import "@comet-contracts/Create2DeployerInterface.sol"; +import "@comet-contracts/marketupdates/MarketUpdateTimelock.sol"; +import "@comet-contracts/marketupdates/MarketUpdateProposer.sol"; +import "@comet-contracts/Configurator.sol"; +import "@comet-contracts/CometProxyAdmin.sol"; +import "@comet-contracts/marketupdates/MarketAdminPermissionChecker.sol"; +import "@forge-std/src/console.sol"; +import "./MarketUpdateAddresses.sol"; + + +library MarketUpdateContractsDeployer { + + address constant public create2DeployerAddress = 0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2; + + struct DeployedContracts { + address marketUpdateTimelock; + address marketUpdateProposer; + address newCometProxyAdmin; + address newConfiguratorImplementation; + address marketAdminPermissionChecker; + } + + struct ContractDeploymentParams { + bytes creationCode; + bytes constructorArgs; + bytes expectedRuntimeCode; + string contractName; + } + + function deployContracts( + bytes32 salt, + address marketUpdateMultiSig, // TODO: Check this is properly used + address marketAdminPauseGuardianAddress, // TODO: Check this is properly used + address marketUpdateProposalGuardianAddress, // TODO: Check this is properly used + address governorTimelockAddress + ) public returns (DeployedContracts memory) { + + ICreate2Deployer create2Deployer = ICreate2Deployer(create2DeployerAddress); + + // Prepare deployment parameters for each contract + ContractDeploymentParams memory marketUpdateTimelockParams = ContractDeploymentParams({ + creationCode: type(MarketUpdateTimelock).creationCode, + constructorArgs: abi.encode(governorTimelockAddress, 360000), // TODO: add comment on how 360000 is calculated + expectedRuntimeCode: type(MarketUpdateTimelock).runtimeCode, + contractName: "MarketUpdateTimelock" + }); + + address computedMarketUpdateTimelockAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateTimelockParams); + + ContractDeploymentParams memory marketUpdateProposerParams = ContractDeploymentParams({ + creationCode: type(MarketUpdateProposer).creationCode, + constructorArgs: abi.encode( + governorTimelockAddress, + marketUpdateMultiSig, + marketUpdateProposalGuardianAddress, + computedMarketUpdateTimelockAddress + ), + expectedRuntimeCode: type(MarketUpdateProposer).runtimeCode, + contractName: "MarketUpdateProposer" + }); + + address computedMarketUpdateProposerAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateProposerParams); + + ContractDeploymentParams memory configuratorParams = ContractDeploymentParams({ + creationCode: type(Configurator).creationCode, + constructorArgs: "", + expectedRuntimeCode: type(Configurator).runtimeCode, + contractName: "Configurator" + }); + + address computedConfiguratorAddress = deployContractWithCreate2(create2Deployer, salt, configuratorParams); + + ContractDeploymentParams memory cometProxyAdminParams = ContractDeploymentParams({ + creationCode: type(CometProxyAdmin).creationCode, + constructorArgs: abi.encode(governorTimelockAddress), + expectedRuntimeCode: type(CometProxyAdmin).runtimeCode, + contractName: "CometProxyAdmin" + }); + + address computedCometProxyAdminAddress = deployContractWithCreate2(create2Deployer, salt, cometProxyAdminParams); + + console.log("Owner of cometProxyAdmin: ", CometProxyAdmin(computedCometProxyAdminAddress).owner()); + + ContractDeploymentParams memory marketAdminPermissionCheckerParams = ContractDeploymentParams({ + creationCode: type(MarketAdminPermissionChecker).creationCode, + constructorArgs: abi.encode(governorTimelockAddress, address(0), address(0)), + expectedRuntimeCode: type(MarketAdminPermissionChecker).runtimeCode, + contractName: "MarketAdminPermissionChecker" + }); + + address computedMarketAdminPermissionCheckerAddress = deployContractWithCreate2(create2Deployer, salt, marketAdminPermissionCheckerParams); + + return DeployedContracts({ + marketUpdateTimelock: computedMarketUpdateTimelockAddress, + marketUpdateProposer: computedMarketUpdateProposerAddress, + newCometProxyAdmin: computedCometProxyAdminAddress, + newConfiguratorImplementation: computedConfiguratorAddress, + marketAdminPermissionChecker: computedMarketAdminPermissionCheckerAddress + }); + } + + function deployContractWithCreate2( + ICreate2Deployer create2Deployer, + bytes32 salt, + ContractDeploymentParams memory params + ) internal returns (address) { + bytes memory bytecode = abi.encodePacked(params.creationCode, params.constructorArgs); + address computedAddress = create2Deployer.computeAddress(salt, keccak256(bytecode)); + checkOrDeployAndCompareBytecodes(create2Deployer, salt, bytecode, computedAddress, params.expectedRuntimeCode); + return computedAddress; + } + + function checkOrDeployAndCompareBytecodes( + ICreate2Deployer create2Deployer, + bytes32 salt, + bytes memory actualBytecode, + address computedAddress, + bytes memory expectedBytecode + ) internal { + uint256 contractCodeSize = getContractCodeSizeAtAddress(computedAddress); + + if (contractCodeSize > 0) { + bytes memory deployedBytecode = verifyDeployedBytecode(computedAddress, contractCodeSize); + + require( + keccak256(deployedBytecode) == keccak256(expectedBytecode), + "Deployed bytecode does not match the expected bytecode" + ); + } else { + deployAndCompareBytecodes(create2Deployer, salt, actualBytecode, computedAddress, expectedBytecode); + } + } + + function deployAndCompareBytecodes( + ICreate2Deployer create2Deployer, + bytes32 salt, + bytes memory actualBytecode, + address computedAddress, + bytes memory expectedBytecode + ) internal { + create2Deployer.deploy(0, salt, actualBytecode); + + uint256 size = getContractCodeSizeAtAddress(computedAddress); + require(size > 0, "No contract deployed at this address"); + + bytes memory deployedBytecode = new bytes(size); + assembly { + extcodecopy(computedAddress, add(deployedBytecode, 0x20), 0, size) + } + + require( + keccak256(deployedBytecode) == keccak256(expectedBytecode), + "Deployed bytecode does not match the expected bytecode" + ); + } + + function getContractCodeSizeAtAddress(address contractAddress) internal view returns (uint256) { + uint256 size; + assembly { + size := extcodesize(contractAddress) + } + return size; + } + + function verifyDeployedBytecode(address computedAddress, uint256 contractCodeSize) internal view returns (bytes memory) { + bytes memory deployedBytecode = new bytes(contractCodeSize); + assembly { + extcodecopy(computedAddress, add(deployedBytecode, 0x20), 0, contractCodeSize) + } + return deployedBytecode; + } + +} diff --git a/forge/simulate.md b/forge/simulate.md new file mode 100644 index 00000000..d753eb01 --- /dev/null +++ b/forge/simulate.md @@ -0,0 +1,6 @@ +# Work - only for arbitrum +- [ ] Find the local timelocks and use it +- [ ] Verify - When we create a deployment proposal, bridge receiver should send to local timelock +- [ ] ForDeployment - Add logic related to moving the time in timelock and executing the transaction +- [ ] ForKinkUpdates - Add logic related to moving the time in timelock and executing the transaction +- [ ] Make the test pass for arbitrum diff --git a/forge/test/MarketUpdateArbitrumDeploymentTest.t.sol b/forge/test/MarketUpdateArbitrumDeploymentTest.t.sol new file mode 100644 index 00000000..e800ee7c --- /dev/null +++ b/forge/test/MarketUpdateArbitrumDeploymentTest.t.sol @@ -0,0 +1,79 @@ +pragma solidity 0.8.15; + +import {Test} from "forge-std/Test.sol"; +import "@comet-contracts/Comet.sol"; +import "@comet-contracts/marketupdates/MarketUpdateProposer.sol"; + +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "../script/marketupdates/helpers/MarketUpdateAddresses.sol"; +import "../script/marketupdates/helpers/MarketUpdateContractsDeployer.sol"; +import "../script/marketupdates/helpers/ChainAddresses.sol"; +import "../script/marketupdates/helpers/MarketAddresses.sol"; +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "./MarketUpdateDeploymentBaseTest.sol"; + +contract MarketUpdateArbitrumDeploymentTest is Test, MarketUpdateDeploymentBaseTest { + + MarketUpdateContractsDeployer.DeployedContracts deployedContracts; + + function setUp() public { + vm.createSelectFork("arbitrum"); + deployedContracts = createMarketUpdateDeploymentForL2(vm, ChainAddresses.Chain.ARBITRUM); + } + + function test_ArbUsdcDeployment() public { + console.log("Create Supply Kink Proposal for USDC Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.ARBITRUM, + MarketAddresses.ARBITRUM_USDC_MARKET, + ChainAddresses.ARBITRUM_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "USDC" + ); + } + + function test_ArbUsdceDeployment() public { + console.log("Create Supply Kink Proposal for USDCe Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.ARBITRUM, + MarketAddresses.ARBITRUM_USDCe_MARKET, + ChainAddresses.ARBITRUM_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "USDCe" + ); + } + + function test_ArbUsdtDeployment() public { + console.log("Create Supply Kink Proposal for USDT Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.ARBITRUM, + MarketAddresses.ARBITRUM_USDT_MARKET, + ChainAddresses.ARBITRUM_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "USDT" + ); + } + + function test_ArbEthDeployment() public { + console.log("Create Supply Kink Proposal for Eth Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.ARBITRUM, + MarketAddresses.ARBITRUM_ETH_MARKET, + ChainAddresses.ARBITRUM_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "ETH" + ); + } +} diff --git a/forge/test/MarketUpdateBaseDeploymentTest.t.sol b/forge/test/MarketUpdateBaseDeploymentTest.t.sol new file mode 100644 index 00000000..23881033 --- /dev/null +++ b/forge/test/MarketUpdateBaseDeploymentTest.t.sol @@ -0,0 +1,65 @@ +pragma solidity 0.8.15; + +import {Test} from "forge-std/Test.sol"; +import "@comet-contracts/Comet.sol"; +import "@comet-contracts/marketupdates/MarketUpdateProposer.sol"; + +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "../script/marketupdates/helpers/MarketUpdateAddresses.sol"; +import "../script/marketupdates/helpers/MarketUpdateContractsDeployer.sol"; +import "../script/marketupdates/helpers/ChainAddresses.sol"; +import "../script/marketupdates/helpers/MarketAddresses.sol"; +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "./MarketUpdateDeploymentBaseTest.sol"; + +contract MarketUpdateBaseDeploymentTest is Test, MarketUpdateDeploymentBaseTest { + + MarketUpdateContractsDeployer.DeployedContracts deployedContracts; + + function setUp() public { + vm.createSelectFork("base"); + deployedContracts = createMarketUpdateDeploymentForL2(vm, ChainAddresses.Chain.BASE); + } + + function test_BaseUsdbcDeployment() public { + console.log("Create Supply Kink Proposal for USDC Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.BASE, + MarketAddresses.BASE_USDbC_MARKET, + ChainAddresses.BASE_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "USDbC" + ); + } + + function test_BaseUsdcDeployment() public { + console.log("Create Supply Kink Proposal for USDT Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.BASE, + MarketAddresses.BASE_USDC_MARKET, + ChainAddresses.BASE_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "USDC" + ); + } + + function test_BaseEthDeployment() public { + console.log("Create Supply Kink Proposal for Eth Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.BASE, + MarketAddresses.BASE_ETH_MARKET, + ChainAddresses.BASE_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "ETH" + ); + } +} diff --git a/forge/test/MarketUpdateDeploymentBaseTest.sol b/forge/test/MarketUpdateDeploymentBaseTest.sol new file mode 100644 index 00000000..ad4ffcba --- /dev/null +++ b/forge/test/MarketUpdateDeploymentBaseTest.sol @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import "@forge-std/src/Vm.sol"; +import "@comet-contracts/bridges/arbitrum/ArbitrumBridgeReceiver.sol"; +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "../script/marketupdates/helpers/MarketUpdateAddresses.sol"; +import "../script/marketupdates/helpers/ChainAddresses.sol"; +import "../script/marketupdates/helpers/MarketUpdateContractsDeployer.sol"; +import "../script/marketupdates/helpers/BridgeHelper.sol"; + +abstract contract MarketUpdateDeploymentBaseTest { + + IGovernorBravo public governorBravo = IGovernorBravo(MarketUpdateAddresses.GOVERNOR_BRAVO_PROXY_ADDRESS); + + function createMarketUpdateDeployment(Vm vm) public returns (MarketUpdateContractsDeployer.DeployedContracts memory) { + bytes32 salt = keccak256(abi.encodePacked("Salt-31")); + + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer.deployContracts( + salt, + MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS, + MarketUpdateAddresses.MARKET_ADMIN_PAUSE_GUARDIAN_ADDRESS, + MarketUpdateAddresses.MARKET_UPDATE_PROPOSAL_GUARDIAN_ADDRESS, + MarketUpdateAddresses.GOVERNOR_BRAVO_TIMELOCK_ADDRESS + ); + + + console.log("MarketUpdateTimelock: ", deployedContracts.marketUpdateTimelock); + console.log("MarketUpdateProposer: ", deployedContracts.marketUpdateProposer); + console.log("NewConfiguratorImplementation: ", deployedContracts.newConfiguratorImplementation); + console.log("NewCometProxyAdmin: ", deployedContracts.newCometProxyAdmin); + console.log("MarketAdminPermissionChecker: ", deployedContracts.marketAdminPermissionChecker); + + + address proposalCreator = GovernanceHelper.getTopDelegates()[0]; + + MarketUpdateAddresses.MarketUpdateAddressesStruct memory addresses = MarketUpdateAddresses.getAddressesForChain( + ChainAddresses.Chain.ETHEREUM, + deployedContracts, + MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS + ); + + uint256 proposalId = GovernanceHelper.createDeploymentProposal(vm, addresses, proposalCreator); + + GovernanceHelper.moveProposalToActive(vm, proposalId); + + GovernanceHelper.voteOnProposal(vm, proposalId, proposalCreator); + + GovernanceHelper.moveProposalToSucceed(vm, proposalId); + + governorBravo.queue(proposalId); + + GovernanceHelper.moveProposalToExecution(vm, proposalId); + + console.log("proposal state after execution: ", uint(governorBravo.state(proposalId))); + + return deployedContracts; + } + + function createMarketUpdateDeploymentForL2(Vm vm, ChainAddresses.Chain chain) public returns (MarketUpdateContractsDeployer.DeployedContracts memory) { + bytes32 salt = keccak256(abi.encodePacked("Salt-31")); + + address localTimelock = ChainAddresses.getLocalTimelockAddress(chain); + + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer.deployContracts( + salt, + MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS, + MarketUpdateAddresses.MARKET_ADMIN_PAUSE_GUARDIAN_ADDRESS, + MarketUpdateAddresses.MARKET_UPDATE_PROPOSAL_GUARDIAN_ADDRESS, + localTimelock + ); + + + console.log("MarketUpdateTimelock: ", deployedContracts.marketUpdateTimelock); + console.log("MarketUpdateProposer: ", deployedContracts.marketUpdateProposer); + console.log("NewConfiguratorImplementation: ", deployedContracts.newConfiguratorImplementation); + console.log("NewCometProxyAdmin: ", deployedContracts.newCometProxyAdmin); + console.log("MarketAdminPermissionChecker: ", deployedContracts.marketAdminPermissionChecker); + + + MarketUpdateAddresses.MarketUpdateAddressesStruct memory addresses = MarketUpdateAddresses.getAddressesForChain( + chain, + deployedContracts, + MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS + ); + + GovernanceHelper.ProposalRequest memory proposalRequest = GovernanceHelper.createDeploymentProposalRequest(addresses); + + BridgeHelper.simulateMessageAndExecuteProposal(vm, chain, MarketUpdateAddresses.GOVERNOR_BRAVO_TIMELOCK_ADDRESS, proposalRequest); + + return deployedContracts; + } + + function updateAndVerifySupplyKink( + Vm vm, + address cometProxy, + address configuratorProxy, + address cometProxyAdminNew, + string memory marketName + ) public { + + uint256 oldSupplyKinkBeforeGovernorUpdate = Comet(payable(cometProxy)).supplyKink(); + uint256 newSupplyKinkByGovernorTimelock = 300000000000000000; + + assert(oldSupplyKinkBeforeGovernorUpdate != newSupplyKinkByGovernorTimelock); + + address[] memory targets = new address[](2); + uint256[] memory values = new uint256[](2); + string[] memory signatures = new string[](2); + bytes[] memory calldatas = new bytes[](2); + string memory description = string(abi.encodePacked("Proposal to update Supply Kink for ", marketName, " Market by Governor Timelock")); + + targets[0] = configuratorProxy; + signatures[0] = "setSupplyKink(address,uint64)"; + calldatas[0] = abi.encode(cometProxy, newSupplyKinkByGovernorTimelock); + + targets[1] = cometProxyAdminNew; + signatures[1] = "deployAndUpgradeTo(address,address)"; + calldatas[1] = abi.encode(configuratorProxy, cometProxy); + + GovernanceHelper.ProposalRequest memory proposalRequest = GovernanceHelper.ProposalRequest({ + targets: targets, + values: values, + signatures: signatures, + calldatas: calldatas + }); + + GovernanceHelper.createProposalAndPass(vm, proposalRequest, description); + + // check the new kink value + uint256 newSupplyKinkAfterGovernorUpdate = Comet(payable(cometProxy)).supplyKink(); + assert(newSupplyKinkAfterGovernorUpdate == newSupplyKinkByGovernorTimelock); + + // Setting new Supply Kink using Market Admin + uint256 oldSupplyKinkBeforeMarketAdminUpdate = Comet(payable(cometProxy)).supplyKink(); + uint256 newSupplyKinkByMarketAdmin = 400000000000000000; + + assert(oldSupplyKinkBeforeMarketAdminUpdate != newSupplyKinkByMarketAdmin); + + calldatas[0] = abi.encode(cometProxy, newSupplyKinkByMarketAdmin); + + description = string(abi.encodePacked("Proposal to update Supply Kink for ", marketName, " Market by Market Admin")); + GovernanceHelper.createAndPassMarketUpdateProposal(vm, proposalRequest, description); + + uint256 newSupplyKinkAfterMarketAdminUpdate = Comet(payable(cometProxy)).supplyKink(); + assert(newSupplyKinkAfterMarketAdminUpdate == newSupplyKinkByMarketAdmin); + } + + function updateAndVerifySupplyKinkInL2( + Vm vm, + ChainAddresses.Chain chain, + address cometProxy, + address configuratorProxy, + address cometProxyAdminNew, + address marketUpdateProposer, + string memory marketName + ) public { + + uint256 oldSupplyKinkBeforeGovernorUpdate = Comet(payable(cometProxy)).supplyKink(); + uint256 newSupplyKinkByGovernorTimelock = 300000000000000000; + + assert(oldSupplyKinkBeforeGovernorUpdate != newSupplyKinkByGovernorTimelock); + + address[] memory targets = new address[](2); + uint256[] memory values = new uint256[](2); + string[] memory signatures = new string[](2); + bytes[] memory calldatas = new bytes[](2); + string memory description = string(abi.encodePacked("Proposal to update Supply Kink for ", marketName, " Market by Governor Timelock")); + + targets[0] = configuratorProxy; + signatures[0] = "setSupplyKink(address,uint64)"; + calldatas[0] = abi.encode(cometProxy, newSupplyKinkByGovernorTimelock); + + targets[1] = cometProxyAdminNew; + signatures[1] = "deployAndUpgradeTo(address,address)"; + calldatas[1] = abi.encode(configuratorProxy, cometProxy); + + GovernanceHelper.ProposalRequest memory proposalRequest = GovernanceHelper.ProposalRequest({ + targets: targets, + values: values, + signatures: signatures, + calldatas: calldatas + }); + + BridgeHelper.simulateMessageAndExecuteProposal(vm, chain, MarketUpdateAddresses.GOVERNOR_BRAVO_TIMELOCK_ADDRESS, proposalRequest); + + // check the new kink value + uint256 newSupplyKinkAfterGovernorUpdate = Comet(payable(cometProxy)).supplyKink(); + assert(newSupplyKinkAfterGovernorUpdate == newSupplyKinkByGovernorTimelock); + + // Setting new Supply Kink using Market Admin + uint256 oldSupplyKinkBeforeMarketAdminUpdate = Comet(payable(cometProxy)).supplyKink(); + uint256 newSupplyKinkByMarketAdmin = 400000000000000000; + + assert(oldSupplyKinkBeforeMarketAdminUpdate != newSupplyKinkByMarketAdmin); + + calldatas[0] = abi.encode(cometProxy, newSupplyKinkByMarketAdmin); + + description = string(abi.encodePacked("Proposal to update Supply Kink for ", marketName, " Market by Market Admin")); + GovernanceHelper.createAndPassMarketUpdateProposalL2(vm, proposalRequest, description, marketUpdateProposer); + + uint256 newSupplyKinkAfterMarketAdminUpdate = Comet(payable(cometProxy)).supplyKink(); + assert(newSupplyKinkAfterMarketAdminUpdate == newSupplyKinkByMarketAdmin); + } +} diff --git a/forge/test/MarketUpdateMainnetDeploymentTest.t.sol b/forge/test/MarketUpdateMainnetDeploymentTest.t.sol new file mode 100644 index 00000000..e2a5621f --- /dev/null +++ b/forge/test/MarketUpdateMainnetDeploymentTest.t.sol @@ -0,0 +1,71 @@ +pragma solidity 0.8.15; + +import {Test} from "forge-std/Test.sol"; +import "@comet-contracts/Comet.sol"; +import "@comet-contracts/marketupdates/MarketUpdateProposer.sol"; + +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "../script/marketupdates/helpers/MarketUpdateAddresses.sol"; +import "../script/marketupdates/helpers/MarketUpdateContractsDeployer.sol"; +import "../script/marketupdates/helpers/ChainAddresses.sol"; +import "../script/marketupdates/helpers/MarketAddresses.sol"; +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "./MarketUpdateDeploymentBaseTest.sol"; + +contract MarketUpdateMainnetDeploymentTest is Test, MarketUpdateDeploymentBaseTest { + + MarketUpdateContractsDeployer.DeployedContracts deployedContracts; + + function setUp() public { + vm.createSelectFork("mainnet"); + deployedContracts = createMarketUpdateDeployment(vm); + } + + function test_UsdcDeployment() public { + console.log("Create Supply Kink Proposal for USDC Market and verify after execution"); + + updateAndVerifySupplyKink( + vm, + MarketAddresses.MAINNET_USDC_MARKET, + ChainAddresses.MAINNET_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + "USDC" + ); + } + + function test_UsdtDeployment() public { + console.log("Create Supply Kink Proposal for USDT Market and verify after execution"); + + updateAndVerifySupplyKink( + vm, + MarketAddresses.MAINNET_USDT_MARKET, + ChainAddresses.MAINNET_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + "USDT" + ); + } + + function test_EthDeployment() public { + console.log("Create Supply Kink Proposal for ETH Market and verify after execution"); + + updateAndVerifySupplyKink( + vm, + MarketAddresses.MAINNET_ETH_MARKET, + ChainAddresses.MAINNET_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + "ETH" + ); + } + + function test_WstEthDeployment() public { + console.log("Create Supply Kink Proposal for WST_ETH Market and verify after execution"); + + updateAndVerifySupplyKink( + vm, + MarketAddresses.MAINNET_WST_ETH_MARKET, + ChainAddresses.MAINNET_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + "WST_ETH" + ); + } +} diff --git a/forge/test/MarketUpdateOptimismDeploymentTest.t.sol b/forge/test/MarketUpdateOptimismDeploymentTest.t.sol new file mode 100644 index 00000000..d3d4ffd1 --- /dev/null +++ b/forge/test/MarketUpdateOptimismDeploymentTest.t.sol @@ -0,0 +1,65 @@ +pragma solidity 0.8.15; + +import {Test} from "forge-std/Test.sol"; +import "@comet-contracts/Comet.sol"; +import "@comet-contracts/marketupdates/MarketUpdateProposer.sol"; + +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "../script/marketupdates/helpers/MarketUpdateAddresses.sol"; +import "../script/marketupdates/helpers/MarketUpdateContractsDeployer.sol"; +import "../script/marketupdates/helpers/ChainAddresses.sol"; +import "../script/marketupdates/helpers/MarketAddresses.sol"; +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "./MarketUpdateDeploymentBaseTest.sol"; + +contract MarketUpdateOptimismDeploymentTest is Test, MarketUpdateDeploymentBaseTest { + + MarketUpdateContractsDeployer.DeployedContracts deployedContracts; + + function setUp() public { + vm.createSelectFork("optimism"); + deployedContracts = createMarketUpdateDeploymentForL2(vm, ChainAddresses.Chain.OPTIMISM); + } + + function test_OptUsdcDeployment() public { + console.log("Create Supply Kink Proposal for USDC Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.OPTIMISM, + MarketAddresses.OPTIMISM_USDC_MARKET, + ChainAddresses.OPTIMISM_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "USDC" + ); + } + + function test_OptUsdtDeployment() public { + console.log("Create Supply Kink Proposal for USDT Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.OPTIMISM, + MarketAddresses.OPTIMISM_USDT_MARKET, + ChainAddresses.OPTIMISM_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "USDT" + ); + } + + function test_OptEthDeployment() public { + console.log("Create Supply Kink Proposal for Eth Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.OPTIMISM, + MarketAddresses.OPTIMISM_ETH_MARKET, + ChainAddresses.OPTIMISM_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "ETH" + ); + } +} diff --git a/forge/test/MarketUpdatePolygonDeploymentTest.t.sol b/forge/test/MarketUpdatePolygonDeploymentTest.t.sol new file mode 100644 index 00000000..23a4e605 --- /dev/null +++ b/forge/test/MarketUpdatePolygonDeploymentTest.t.sol @@ -0,0 +1,51 @@ +pragma solidity 0.8.15; + +import {Test} from "forge-std/Test.sol"; +import "@comet-contracts/Comet.sol"; +import "@comet-contracts/marketupdates/MarketUpdateProposer.sol"; + +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "../script/marketupdates/helpers/MarketUpdateAddresses.sol"; +import "../script/marketupdates/helpers/MarketUpdateContractsDeployer.sol"; +import "../script/marketupdates/helpers/ChainAddresses.sol"; +import "../script/marketupdates/helpers/MarketAddresses.sol"; +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "./MarketUpdateDeploymentBaseTest.sol"; + +contract MarketUpdatePolygonDeploymentTest is Test, MarketUpdateDeploymentBaseTest { + + MarketUpdateContractsDeployer.DeployedContracts deployedContracts; + + function setUp() public { + vm.createSelectFork("polygon"); + deployedContracts = createMarketUpdateDeploymentForL2(vm, ChainAddresses.Chain.POLYGON); + } + + function test_PolygonUsdceDeployment() public { + console.log("Create Supply Kink Proposal for USDCe Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.POLYGON, + MarketAddresses.POLYGON_USDCe_MARKET, + ChainAddresses.POLYGON_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "USDCe" + ); + } + + function test_PolygonUsdtDeployment() public { + console.log("Create Supply Kink Proposal for USDT Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.POLYGON, + MarketAddresses.POLYGON_USDT_MARKET, + ChainAddresses.POLYGON_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "USDT" + ); + } +} diff --git a/forge/test/MarketUpdateScrollDeploymentTest.t.sol b/forge/test/MarketUpdateScrollDeploymentTest.t.sol new file mode 100644 index 00000000..abf20998 --- /dev/null +++ b/forge/test/MarketUpdateScrollDeploymentTest.t.sol @@ -0,0 +1,37 @@ +pragma solidity 0.8.15; + +import {Test} from "forge-std/Test.sol"; +import "@comet-contracts/Comet.sol"; +import "@comet-contracts/marketupdates/MarketUpdateProposer.sol"; + +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "../script/marketupdates/helpers/MarketUpdateAddresses.sol"; +import "../script/marketupdates/helpers/MarketUpdateContractsDeployer.sol"; +import "../script/marketupdates/helpers/ChainAddresses.sol"; +import "../script/marketupdates/helpers/MarketAddresses.sol"; +import "../script/marketupdates/helpers/GovernanceHelper.sol"; +import "./MarketUpdateDeploymentBaseTest.sol"; + +contract MarketUpdateScrollDeploymentTest is Test, MarketUpdateDeploymentBaseTest { + + MarketUpdateContractsDeployer.DeployedContracts deployedContracts; + + function setUp() public { + vm.createSelectFork("scroll"); + deployedContracts = createMarketUpdateDeploymentForL2(vm, ChainAddresses.Chain.SCROLL); + } + + function test_ScrollUsdcDeployment() public { + console.log("Create Supply Kink Proposal for USDCe Market and verify after execution"); + + updateAndVerifySupplyKinkInL2( + vm, + ChainAddresses.Chain.SCROLL, + MarketAddresses.SCROLL_USDC_MARKET, + ChainAddresses.SCROLL_CONFIGURATOR_PROXY, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, + "USDC" + ); + } +} diff --git a/foundry.toml b/foundry.toml index a8e6ca4a..55c967f6 100644 --- a/foundry.toml +++ b/foundry.toml @@ -7,3 +7,20 @@ cache_path = 'forge/cache' # disable for CI (used for debugging liquidity issues) no_match_test = "test.*SwapVia" + +evm_version = "shanghai" + +fs_permissions = [{ access = "read-write", path = "./forge/script/helperContracts/DeployedAddresses.sol" }] + +remappings = [ + "@forge-std/=forge/lib/forge-std/", + "@comet-contracts/=contracts/", +] + +[rpc_endpoints] +mainnet = "${MAINNET_RPC_URL}" +polygon = "${POLYGON_RPC_URL}" +arbitrum = "${ARBITRUM_RPC_URL}" +optimism = "${OPTIMISM_RPC_URL}" +scroll = "${SCROLL_RPC_URL}" +base = "${BASE_RPC_URL}" diff --git a/hardhat.config.ts b/hardhat.config.ts index a1b8b821..d9cda975 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -151,6 +151,16 @@ const networkConfigs: NetworkConfig[] = [ chainId: 421613, url: `https://arbitrum-goerli.infura.io/v3/${INFURA_KEY}`, }, + { + network: 'arbitrum-sepolia', + chainId: 421614, + url: `https://arbitrum-sepolia.infura.io/v3/${INFURA_KEY}`, + }, + { + network: 'optimism-sepolia', + chainId: 11155420, + url: `https://optimism-sepolia.infura.io/v3/${INFURA_KEY}`, + }, { network: 'base-goerli', chainId: 84531, @@ -221,6 +231,18 @@ const config: HardhatUserConfig = { }, networks: { + optimismSepolia: { + url: 'https://sepolia.optimism.io', + chainId: 11155420 + }, + arbitrumSepolia: { + url: 'https://arbitrum-sepolia.blockpi.network/v1/rpc/public', + chainId: 421614 + }, + mainnetSepolia: { + url: 'https://ethereum-sepolia.blockpi.network/v1/rpc/public', + chainId: 11155111 + }, hardhat: { chainId: 1337, loggingEnabled: !!process.env['LOGGING'], @@ -266,12 +288,15 @@ const config: HardhatUserConfig = { arbitrumTestnet: ARBISCAN_KEY, arbitrum: ARBISCAN_KEY, 'arbitrum-goerli': ARBISCAN_KEY, + 'arbitrum-sepolia': ARBISCAN_KEY, // Base base: BASESCAN_KEY, 'base-goerli': BASESCAN_KEY, // Linea 'linea-goerli': LINEASCAN_KEY, + // Optimism optimism: OPTIMISMSCAN_KEY, + 'optimism-sepolia': OPTIMISMSCAN_KEY, optimisticEthereum: OPTIMISMSCAN_KEY, // Scroll Testnet 'scroll-goerli': ETHERSCAN_KEY, @@ -297,6 +322,24 @@ const config: HardhatUserConfig = { browserURL: 'https://goerli.arbiscan.io/' } }, + { + // Hardhat's Etherscan plugin calls the network `arbitrumSepolia`, so we need to add an entry for our own network name + network: 'arbitrum-sepolia', + chainId: 421613, + urls: { + apiURL: 'https://api-sepolia.arbiscan.io/api', + browserURL: 'https://sepolia.arbiscan.io/' + } + }, + { + // Hardhat's Etherscan plugin calls the network `optimismSepolia`, so we need to add an entry for our own network name + network: 'optimism-sepolia', + chainId: 11155420, + urls: { + apiURL: 'https://api-sepolia.optimistic.etherescan.io/api', + browserURL: 'https://sepolia.optimistic.etherscan.io/' + } + }, { // Hardhat's Etherscan plugin doesn't have support Base, so we need to add an entry for our own network name network: 'base', @@ -514,6 +557,18 @@ const config: HardhatUserConfig = { deployment: 'usdc', auxiliaryBase: 'goerli' }, + { + name: 'arbitrum-sepolia-usdc', + network: 'arbitrum-sepolia', + deployment: 'usdc', + auxiliaryBase: 'sepolia' + }, + { + name: 'optimism-sepolia-usdc', + network: 'optimism-sepolia', + deployment: 'usdc', + auxiliaryBase: 'sepolia' + }, { name: 'base-usdbc', network: 'base', diff --git a/package.json b/package.json index c5a99c69..7305fd64 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "license": "UNLICENSED", "dependencies": { "@flashbots/ethers-provider-bundle": "^0.5.0", + "@safe-global/protocol-kit": "^4.1.0", "chai": "^4.3.4", "chai-as-promised": "^7.1.1", "deep-object-diff": "^1.1.9", @@ -60,7 +61,7 @@ "@ethersproject/experimental": "^5.6.3", "@nomiclabs/hardhat-ethers": "^2.0.4", "@nomiclabs/hardhat-etherscan": "3.1.7", - "@safe-global/safe-core-sdk": "^3.3.2", + "@safe-global/safe-core-sdk": "^3.3.5", "@safe-global/safe-ethers-lib": "^1.9.2", "@typechain/ethers-v5": "^8.0.2", "@typechain/hardhat": "^3.0.0", diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 00000000..04c49303 --- /dev/null +++ b/remappings.txt @@ -0,0 +1,6 @@ +@forge-std/=forge/lib/forge-std/ +@comet-contracts/=contracts/ +@openzeppelin/=node_modules/@openzeppelin/ +eth-gas-reporter/=node_modules/eth-gas-reporter/ +forge-std/=forge/lib/forge-std/src/ +hardhat/=node_modules/hardhat/ diff --git a/scripts/marketupdates/deploy.ts b/scripts/marketupdates/deploy.ts new file mode 100644 index 00000000..ff58ba96 --- /dev/null +++ b/scripts/marketupdates/deploy.ts @@ -0,0 +1,144 @@ +import {ICreate2Deployer} from './../../build/types'; +import hre, {ethers} from 'hardhat'; +import { SafeFactory, SafeAccountConfig } from '@safe-global/protocol-kit'; + +async function deploySafe(owners:string[], threshold:number, salt:string){ + const [deployer] = await ethers.getSigners(); + console.log('Deploying safe with the account:', deployer.address); + + const network = await ethers.provider.getNetwork(); + console.log('Network:', network); + let rpcUrl: string; + if (network.chainId === 11155420) { + rpcUrl = process.env.OP_SEPOLIA_RPC!; + } else if (network.chainId === 421614) { + rpcUrl = process.env.ARB_SEPOLIA_RPC!; + } else if (network.chainId === 11155111) { + rpcUrl = process.env.ETH_SEPOLIA_RPC!; + } else { + throw new Error('Unsupported network'); + } + + let signer; + if (process.env.PRIVATE_KEY) { + signer = process.env.PRIVATE_KEY; + } else{ + throw new Error('Signer private key not available in env'); + } + + const safeFactory = await SafeFactory.init({ provider: rpcUrl, signer: signer, safeVersion:'1.4.1' }); + + const safeAccountConfig: SafeAccountConfig = { + owners:[deployer.address, ...owners], + threshold: threshold + }; + + console.log('Predicting safe address..'); + const predictedDeployAddress = await safeFactory.predictSafeAddress(safeAccountConfig,salt); + console.log('Predicted deployed address:', predictedDeployAddress); + + const safe = await safeFactory.deploySafe({ safeAccountConfig: safeAccountConfig, saltNonce: salt }); + const safeAddress = await safe.getAddress(); + console.log('Safe deployed at:', safeAddress); + + return {safe, safeAddress}; +} + +async function createBytecode(create2Deployer:ICreate2Deployer, contract:string, salt:string, args?:any[]){ + const contractFactory = await ethers.getContractFactory(contract); + + let creationBytecode; + if (args && args.length > 0) { + creationBytecode = await contractFactory.getDeployTransaction(...args); + } else { + creationBytecode = await contractFactory.getDeployTransaction(); + } + const artifact = hre.artifacts.readArtifact(contract); + const bytecode = (await artifact).bytecode; + const deployedByteCode = (await artifact).deployedBytecode; + + const computedAddress = await create2Deployer.computeAddress(salt, ethers.utils.keccak256(bytecode)); + + return {computedAddress, creationBytecode, deployedByteCode}; +} + +async function checkAndDeploy(create2Deployer: ICreate2Deployer, salt: string, contractName: string, args?: any[]) { + // Create bytecode and compute the deterministic address + const { computedAddress, creationBytecode, deployedByteCode } = await createBytecode(create2Deployer, contractName, salt, args); + + console.log(`Deterministic Address of ${contractName}:`, computedAddress); + + // Check if the contract is already deployed + const deployedCode = await ethers.provider.getCode(computedAddress); + + if (deployedCode !== '0x') { + const contract = await ethers.getContractAt(contractName, computedAddress); + const contractByteCode = await ethers.provider.getCode(contract.address); + console.log(`${contractName} already deployed at address: `, computedAddress); + console.log(`${contractName} ByteCode is Same? : `, contractByteCode.toLowerCase() === deployedByteCode.toLowerCase()); + return {contract, computedAddress}; + } else { + // Deploy using CREATE2 if not already deployed + console.log(`Deploying ${contractName}...`); + await create2Deployer.deploy(0, salt, creationBytecode.data); // value = 0 for no ether transfer + console.log(`Deployed ${contractName} at address (deterministic):`, computedAddress); + return {contract: await ethers.getContractAt(contractName, computedAddress), computedAddress }; + } +} + +async function main() { + const [deployer] = await ethers.getSigners(); + console.log('Deploying contracts with the account:', deployer.address); + const balance = await deployer.getBalance(); + console.log('Account balance:', balance.toString()); + + const salt = ethers.utils.keccak256(ethers.utils.toUtf8Bytes('Salt-15')); + console.log('salt: ', salt); + const owners = ['0x7053e25f7076F4986D632A3C04313C81831e0d55', '0x77B65c68E52C31eb844fb3b4864B91133e2C1308']; // Replace with actual addresses + const threshold = 2; // Require 2 out of 3 approvals + + // Get the Create2 Deployer contract at its known address + const create2DeployerAddress = '0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2'; + const create2Deployer = (await ethers.getContractAt( + 'ICreate2Deployer', + create2DeployerAddress + )) as ICreate2Deployer; + + const governorTimelockAddr = '0x6d903f6003cca6255D85CcA4D3B5E5146dC33925'; + const pauseGuardianAddr = '0x7053e25f7076F4986D632A3C04313C81831e0d55'; + + const {safeAddress: multisigAddress} = await deploySafe(owners,threshold,salt); + + const delay = 2 * 24 * 60 * 60; // This is 2 days in seconds + const marketTimelockArgs = [governorTimelockAddr, delay]; + const {contract:marketUpdateTimelock, computedAddress:marketUpdateTimelockAddress} = await checkAndDeploy(create2Deployer, salt, 'MarketUpdateTimelock', marketTimelockArgs); + + const marketProposerArgs = [governorTimelockAddr,multisigAddress,pauseGuardianAddr,marketUpdateTimelockAddress]; + const {contract:marketUpdateProposer, computedAddress: marketProposerAddress} = await checkAndDeploy(create2Deployer, salt, 'MarketUpdateProposer', marketProposerArgs); + + const {contract:configurator, computedAddress: configuratorAddress} = await checkAndDeploy(create2Deployer, salt, 'Configurator'); + + const {contract:cometProxyAdmin, computedAddress: cometProxyAdminAddress} = await checkAndDeploy(create2Deployer, salt, 'CometProxyAdmin'); + + console.log('Computed Contract Addresses:', { + multisigAddress, + marketUpdateTimelockAddress, + marketProposerAddress, + configuratorAddress, + cometProxyAdminAddress + }); + + console.log('Deployed Contracts Addresses:', { + marketUpdateTimelock: marketUpdateTimelock.address, + marketUpdateProposer: marketUpdateProposer.address, + configurator: configurator.address, + cometProxyAdmin: cometProxyAdmin.address + }); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/marketupdates/deploySafe.ts b/scripts/marketupdates/deploySafe.ts new file mode 100644 index 00000000..106f6817 --- /dev/null +++ b/scripts/marketupdates/deploySafe.ts @@ -0,0 +1,80 @@ +import {SafeAccountConfig, SafeFactory} from '@safe-global/protocol-kit'; +import {ethers} from 'hardhat'; + +async function deploySafe(owners:string[], threshold:number, salt:string){ + const [deployer] = await ethers.getSigners(); + console.log('Deploying safe with the account:', deployer.address); + const balance = await deployer.getBalance(); + console.log("Account balance:", ethers.utils.formatEther(balance)); + const network = await ethers.provider.getNetwork(); + console.log('Network:', network); + let rpcUrl: string; + if (network.chainId === 11155420) { + rpcUrl = process.env.OP_SEPOLIA_RPC!; + } else if (network.chainId === 421614) { + rpcUrl = process.env.ARB_SEPOLIA_RPC!; + } else if (network.chainId === 11155111) { + rpcUrl = process.env.ETH_SEPOLIA_RPC!; + } else { + throw new Error('Unsupported network'); + } + + let signer; + if (process.env.PRIVATE_KEY) { + signer = process.env.PRIVATE_KEY; + } else{ + throw new Error('Signer private key not available in env'); + } + + const safeFactory = await SafeFactory.init({ provider: rpcUrl, signer: signer, safeVersion:'1.4.1' }); + + const safeAccountConfig: SafeAccountConfig = { + owners:[deployer.address, ...owners], + threshold: threshold + }; + + console.log('Predicting safe address..'); + const predictedDeployAddress = await safeFactory.predictSafeAddress(safeAccountConfig,salt); + console.log('Predicted deployed address:', predictedDeployAddress); + + const safe = await safeFactory.deploySafe({ safeAccountConfig: safeAccountConfig, saltNonce: salt }); + const safeAddress = await safe.getAddress(); + console.log('Safe deployed at:', safeAddress); + + return {safe, safeAddress}; +} +async function main() { + + + const owners = ['0x7053e25f7076F4986D632A3C04313C81831e0d55', '0x77B65c68E52C31eb844fb3b4864B91133e2C1308']; // Replace with actual addresses + const threshold = 2; // Require 2 out of 3 approvals + const salt = ethers.utils.keccak256(ethers.utils.toUtf8Bytes('deterministic-safe-8')); + + const {safe} = await deploySafe(owners, threshold, salt); + const safeBalance = await safe.getBalance(); + console.log('Safe balance:', safeBalance.toString()); + + const chainId = await safe.getChainId(); + console.log('Safe chainId:', chainId); + + // loading already deployed safe + + // const predictedSafe: PredictedSafeProps = { + // safeAccountConfig, + // safeDeploymentConfig + // }; + + // const protocolKit = await Safe.init({ + // provider, + // signer, + // safeAddress + // }); + +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/yarn.lock b/yarn.lock index eb9d46f5..1f357a7d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,5806 +1,4910 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@arbitrum/sdk@^3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.2.tgz#c1ded298778c141b6d8d0342a507a4f94af02757" - integrity sha512-QcS5t6GDCLyY+u0WaYPIjBd2U9hmDbzGc8gLMyiUxpP7w4bOWs6ZGBGUw2N6oLOMLI5IEq9ZbRZEC/Ejsy/URg== - dependencies: - "@ethersproject/address" "^5.0.8" - "@ethersproject/bignumber" "^5.1.1" - "@ethersproject/bytes" "^5.0.8" - ethers "^5.1.0" - -"@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== - dependencies: - "@babel/highlight" "^7.18.6" - -"@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/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@chainsafe/as-sha256@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" - integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== - -"@chainsafe/persistent-merkle-tree@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz#4c9ee80cc57cd3be7208d98c40014ad38f36f7ff" - integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - -"@chainsafe/persistent-merkle-tree@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz#2b4a62c9489a5739dedd197250d8d2f5427e9f63" - integrity sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - -"@chainsafe/ssz@^0.10.0": - version "0.10.2" - resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.10.2.tgz#c782929e1bb25fec66ba72e75934b31fd087579e" - integrity sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - "@chainsafe/persistent-merkle-tree" "^0.5.0" - -"@chainsafe/ssz@^0.9.2": - version "0.9.4" - resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.9.4.tgz#696a8db46d6975b600f8309ad3a12f7c0e310497" - integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - "@chainsafe/persistent-merkle-tree" "^0.4.2" - case "^1.6.3" - -"@colors/colors@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" - integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== - -"@compound-finance/hardhat-import@^1.0.3": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@compound-finance/hardhat-import/-/hardhat-import-1.0.4.tgz#75c5a28ac2bdcf25455be9868ff812cb52287a20" - integrity sha512-CJl2BwVVKBMlVAHMm6G5MTqqI+mO5vdYoLiDbhvNOO3Ti+XLmR/vU06BxQxmJb0rijPsM77VuIiPkr15BOM0JQ== - dependencies: - "@ethersproject/address" "^5.5.0" - axios "^0.24.0" - hardhat "^2.0.4" - ts-node "^8.1.0" - typescript "~4.0.3" - -"@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" - -"@eslint/eslintrc@^1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.3.tgz#2b044ab39fdfa75b4688184f9e573ce3c5b0ff95" - integrity sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.4.0" - globals "^13.15.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" - integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" - integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - -"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" - integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.8", "@ethersproject/address@^5.5.0", "@ethersproject/address@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" - integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" - integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" - integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.1.1", "@ethersproject/bignumber@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" - integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - bn.js "^5.2.1" - -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.0.8", "@ethersproject/bytes@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" - integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" - integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - -"@ethersproject/experimental@^5.6.3": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/experimental/-/experimental-5.7.0.tgz#9759639434d37beaedfd8acab6f3af7db246b92d" - integrity sha512-DWvhuw7Dg8JPyhMbh/CNYOwsTLjXRx/HGkacIL5rBocG8jJC0kmixwoK/J3YblO4vtcyBLMa+sV74RJZK2iyHg== - dependencies: - "@ethersproject/web" "^5.7.0" - ethers "^5.7.0" - scrypt-js "3.0.1" - -"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" - integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" - integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" - integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" - integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - js-sha3 "0.8.0" - -"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" - integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== - -"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" - integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" - integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - -"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" - integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/providers@5.7.1": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.1.tgz#b0799b616d5579cd1067a8ebf1fc1ec74c1e122c" - integrity sha512-vZveG/DLyo+wk4Ga1yx6jSEHrLPgmTt+dFv0dv8URpVCRf0jVhalps1jq/emN/oXnMRsC7cQgAF32DcXLL7BPQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2": - version "5.7.2" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" - integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" - integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" - integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" - integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - hash.js "1.1.7" - -"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" - integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - bn.js "^5.2.1" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/solidity@5.7.0", "@ethersproject/solidity@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" - integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" - integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.6.2", "@ethersproject/transactions@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" - integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/units@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" - integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/wallet@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" - integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/json-wallets" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" - integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" - integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@flashbots/ethers-provider-bundle@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@flashbots/ethers-provider-bundle/-/ethers-provider-bundle-0.5.0.tgz#068dd6a078066c50c36ac81b92d4726636768853" - integrity sha512-w7vc6aWDtgaHkDSgACjda0NoKYjOJ4mkr2av+u0NctvsoeNTg5dji65zeyU+98Fx3s6IbK0mfUTSGHAUtyt21A== - dependencies: - ts-node "^9.1.0" - typescript "^4.1.2" - -"@gnosis.pm/safe-deployments@1.19.0": - version "1.19.0" - resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-deployments/-/safe-deployments-1.19.0.tgz#f4ba8cf92cd6fdff4241ac50e410b4a6ff89babe" - integrity sha512-EvHR/LjMwJm0QKXyTscRXqR9vnJwCUDiMnRNKRyXe1akW+udiYXjJTAiGuleFS4DOUSqs6DpAjYlLnXMzUsVMw== - dependencies: - semver "^7.3.7" - -"@humanwhocodes/config-array@^0.10.5": - version "0.10.7" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.7.tgz#6d53769fd0c222767e6452e8ebda825c22e9f0dc" - integrity sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.4" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -"@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" - -"@metamask/eth-sig-util@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" - integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== - dependencies: - ethereumjs-abi "^0.6.8" - ethereumjs-util "^6.2.1" - ethjs-util "^0.1.6" - tweetnacl "^1.0.3" - tweetnacl-util "^0.15.1" - -"@noble/hashes@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" - integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== - -"@noble/hashes@~1.1.1": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.3.tgz#360afc77610e0a61f3417e497dcf36862e4f8111" - integrity sha512-CE0FCR57H2acVI5UOzIGSSIYxZ6v/HOhDR0Ro9VLyhnzLwx0o8W1mmgaqlEUx4049qJDlIBRztv5k+MM8vbO3A== - -"@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0": - version "1.6.3" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" - integrity sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ== - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@nomicfoundation/ethereumjs-block@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz#6f89664f55febbd723195b6d0974773d29ee133d" - integrity sha512-u1Yioemi6Ckj3xspygu/SfFvm8vZEO8/Yx5a1QLzi6nVU0jz3Pg2OmHKJ5w+D9Ogk1vhwRiqEBAqcb0GVhCyHw== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - ethereum-cryptography "0.1.3" - ethers "^5.7.1" - -"@nomicfoundation/ethereumjs-block@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz#fdd5c045e7baa5169abeed0e1202bf94e4481c49" - integrity sha512-bk8uP8VuexLgyIZAHExH1QEovqx0Lzhc9Ntm63nCRKLHXIZkobaFaeCVwTESV7YkPKUk7NiK11s8ryed4CS9yA== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-blockchain@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.1.tgz#80e0bd3535bfeb9baa29836b6f25123dab06a726" - integrity sha512-NhzndlGg829XXbqJEYrF1VeZhAwSPgsK/OB7TVrdzft3y918hW5KNd7gIZ85sn6peDZOdjBsAXIpXZ38oBYE5A== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-ethash" "3.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - abstract-level "^1.0.3" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - level "^8.0.0" - lru-cache "^5.1.1" - memory-level "^1.0.0" - -"@nomicfoundation/ethereumjs-blockchain@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz#1a8c243a46d4d3691631f139bfb3a4a157187b0c" - integrity sha512-pLFEoea6MWd81QQYSReLlLfH7N9v7lH66JC/NMPN848ySPPQA5renWnE7wPByfQFzNrPBuDDRFFULMDmj1C0xw== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-ethash" "^2.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - abstract-level "^1.0.3" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - level "^8.0.0" - lru-cache "^5.1.1" - memory-level "^1.0.0" - -"@nomicfoundation/ethereumjs-common@4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.1.tgz#4702d82df35b07b5407583b54a45bf728e46a2f0" - integrity sha512-OBErlkfp54GpeiE06brBW/TTbtbuBJV5YI5Nz/aB2evTDo+KawyEzPjBlSr84z/8MFfj8wS2wxzQX1o32cev5g== - dependencies: - "@nomicfoundation/ethereumjs-util" "9.0.1" - crc-32 "^1.2.0" - -"@nomicfoundation/ethereumjs-common@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz#f6bcc7753994555e49ab3aa517fc8bcf89c280b9" - integrity sha512-WS7qSshQfxoZOpHG/XqlHEGRG1zmyjYrvmATvc4c62+gZXgre1ymYP8ZNgx/3FyZY0TWe9OjFlKOfLqmgOeYwA== - dependencies: - "@nomicfoundation/ethereumjs-util" "^8.0.0" - crc-32 "^1.2.0" - -"@nomicfoundation/ethereumjs-ethash@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz#65ca494d53e71e8415c9a49ef48bc921c538fc41" - integrity sha512-KDjGIB5igzWOp8Ik5I6QiRH5DH+XgILlplsHR7TEuWANZA759G6krQ6o8bvj+tRUz08YygMQu/sGd9mJ1DYT8w== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - abstract-level "^1.0.3" - bigint-crypto-utils "^3.0.23" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-ethash@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz#11539c32fe0990e1122ff987d1b84cfa34774e81" - integrity sha512-WpDvnRncfDUuXdsAXlI4lXbqUDOA+adYRQaEezIkxqDkc+LDyYDbd/xairmY98GnQzo1zIqsIL6GB5MoMSJDew== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - abstract-level "^1.0.3" - bigint-crypto-utils "^3.0.23" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-evm@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.1.tgz#f35681e203363f69ce2b3d3bf9f44d4e883ca1f1" - integrity sha512-oL8vJcnk0Bx/onl+TgQOQ1t/534GKFaEG17fZmwtPFeH8S5soiBYPCLUrvANOl4sCp9elYxIMzIiTtMtNNN8EQ== - dependencies: - "@ethersproject/providers" "^5.7.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@nomicfoundation/ethereumjs-evm@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz#99cd173c03b59107c156a69c5e215409098a370b" - integrity sha512-hVS6qRo3V1PLKCO210UfcEQHvlG7GqR8iFzp0yyjTg2TmJQizcChKgWo8KFsdMw6AyoLgLhHGHw4HdlP8a4i+Q== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@types/async-eventemitter" "^0.2.1" - async-eventemitter "^0.2.4" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@nomicfoundation/ethereumjs-rlp@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz#0b30c1cf77d125d390408e391c4bb5291ef43c28" - integrity sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ== - -"@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz#d9a9c5f0f10310c8849b6525101de455a53e771d" - integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== - -"@nomicfoundation/ethereumjs-statemanager@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz#8824a97938db4471911e2d2f140f79195def5935" - integrity sha512-B5ApMOnlruVOR7gisBaYwFX+L/AP7i/2oAahatssjPIBVDF6wTX1K7Qpa39E/nzsH8iYuL3krkYeUFIdO3EMUQ== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - ethers "^5.7.1" - js-sdsl "^4.1.4" - -"@nomicfoundation/ethereumjs-statemanager@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz#14a9d4e1c828230368f7ab520c144c34d8721e4b" - integrity sha512-jCtqFjcd2QejtuAMjQzbil/4NHf5aAWxUc+CvS0JclQpl+7M0bxMofR2AJdtz+P3u0ke2euhYREDiE7iSO31vQ== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - functional-red-black-tree "^1.0.1" - -"@nomicfoundation/ethereumjs-trie@6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.1.tgz#662c55f6b50659fd4b22ea9f806a7401cafb7717" - integrity sha512-A64It/IMpDVODzCgxDgAAla8jNjNtsoQZIzZUfIV5AY6Coi4nvn7+VReBn5itlxMiL2yaTlQr9TRWp3CSI6VoA== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - "@types/readable-stream" "^2.3.13" - ethereum-cryptography "0.1.3" - readable-stream "^3.6.0" - -"@nomicfoundation/ethereumjs-trie@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz#dcfbe3be53a94bc061c9767a396c16702bc2f5b7" - integrity sha512-LIj5XdE+s+t6WSuq/ttegJzZ1vliwg6wlb+Y9f4RlBpuK35B9K02bO7xU+E6Rgg9RGptkWd6TVLdedTI4eNc2A== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - ethereum-cryptography "0.1.3" - readable-stream "^3.6.0" - -"@nomicfoundation/ethereumjs-tx@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.1.tgz#7629dc2036b4a33c34e9f0a592b43227ef4f0c7d" - integrity sha512-0HwxUF2u2hrsIM1fsasjXvlbDOq1ZHFV2dd1yGq8CA+MEYhaxZr8OTScpVkkxqMwBcc5y83FyPl0J9MZn3kY0w== - dependencies: - "@chainsafe/ssz" "^0.9.2" - "@ethersproject/providers" "^5.7.2" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-tx@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz#59dc7452b0862b30342966f7052ab9a1f7802f52" - integrity sha512-Gg3Lir2lNUck43Kp/3x6TfBNwcWC9Z1wYue9Nz3v4xjdcv6oDW9QSMJxqsKw9QEGoBBZ+gqwpW7+F05/rs/g1w== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-util@9.0.1": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz#530cda8bae33f8b5020a8f199ed1d0a2ce48ec89" - integrity sha512-TwbhOWQ8QoSCFhV/DDfSmyfFIHjPjFBj957219+V3jTZYZ2rf9PmDtNOeZWAE3p3vlp8xb02XGpd0v6nTUPbsA== - dependencies: - "@chainsafe/ssz" "^0.10.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-util@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz#deb2b15d2c308a731e82977aefc4e61ca0ece6c5" - integrity sha512-2emi0NJ/HmTG+CGY58fa+DQuAoroFeSH9gKu9O6JnwTtlzJtgfTixuoOqLEgyyzZVvwfIpRueuePb8TonL1y+A== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-vm@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz#7d035e0993bcad10716c8b36e61dfb87fa3ca05f" - integrity sha512-rArhyn0jPsS/D+ApFsz3yVJMQ29+pVzNZ0VJgkzAZ+7FqXSRtThl1C1prhmlVr3YNUlfpZ69Ak+RUT4g7VoOuQ== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-blockchain" "7.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-evm" "2.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-statemanager" "2.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@nomicfoundation/ethereumjs-vm@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz#2bb50d332bf41790b01a3767ffec3987585d1de6" - integrity sha512-JMPxvPQ3fzD063Sg3Tp+UdwUkVxMoo1uML6KSzFhMH3hoQi/LMuXBoEHAoW83/vyNS9BxEe6jm6LmT5xdeEJ6w== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-evm" "^1.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@types/async-eventemitter" "^0.2.1" - async-eventemitter "^0.2.4" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - functional-red-black-tree "^1.0.1" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.0.tgz#83a7367342bd053a76d04bbcf4f373fef07cf760" - integrity sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw== - -"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.0.tgz#1225f7da647ae1ad25a87125664704ecc0af6ccc" - integrity sha512-dlHeIg0pTL4dB1l9JDwbi/JG6dHQaU1xpDK+ugYO8eJ1kxx9Dh2isEUtA4d02cQAl22cjOHTvifAk96A+ItEHA== - -"@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.0.tgz#dbc052dcdfd50ae50fd5ae1788b69b4e0fa40040" - integrity sha512-WFCZYMv86WowDA4GiJKnebMQRt3kCcFqHeIomW6NMyqiKqhK1kIZCxSLDYsxqlx396kKLPN1713Q1S8tu68GKg== - -"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.0.tgz#e6b2eea633995b557e74e881d2a43eab4760903d" - integrity sha512-DTw6MNQWWlCgc71Pq7CEhEqkb7fZnS7oly13pujs4cMH1sR0JzNk90Mp1zpSCsCs4oKan2ClhMlLKtNat/XRKQ== - -"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.0.tgz#af81107f5afa794f19988a368647727806e18dc4" - integrity sha512-wUpUnR/3GV5Da88MhrxXh/lhb9kxh9V3Jya2NpBEhKDIRCDmtXMSqPMXHZmOR9DfCwCvG6vLFPr/+YrPCnUN0w== - -"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.0.tgz#6877e1da1a06a9f08446070ab6e0a5347109f868" - integrity sha512-lR0AxK1x/MeKQ/3Pt923kPvwigmGX3OxeU5qNtQ9pj9iucgk4PzhbS3ruUeSpYhUxG50jN4RkIGwUMoev5lguw== - -"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.0.tgz#bb6cd83a0c259eccef4183796b6329a66cf7ebd9" - integrity sha512-A1he/8gy/JeBD3FKvmI6WUJrGrI5uWJNr5Xb9WdV+DK0F8msuOqpEByLlnTdLkXMwW7nSl3awvLezOs9xBHJEg== - -"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.0.tgz#9d4bca1cc9a1333fde985675083b0b7d165f6076" - integrity sha512-7x5SXZ9R9H4SluJZZP8XPN+ju7Mx+XeUMWZw7ZAqkdhP5mK19I4vz3x0zIWygmfE8RT7uQ5xMap0/9NPsO+ykw== - -"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.0.tgz#0db5bfc6aa952bea4098d8d2c8947b4e5c4337ee" - integrity sha512-m7w3xf+hnE774YRXu+2mGV7RiF3QJtUoiYU61FascCkQhX3QMQavh7saH/vzb2jN5D24nT/jwvaHYX/MAM9zUw== - -"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.0.tgz#2e0f39a2924dcd77db6b419828595e984fabcb33" - integrity sha512-xCuybjY0sLJQnJhupiFAXaek2EqF0AP0eBjgzaalPXSNvCEN6ZYHvUzdA50ENDVeSYFXcUsYf3+FsD3XKaeptA== - -"@nomicfoundation/solidity-analyzer@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.0.tgz#e5ddc43ad5c0aab96e5054520d8e16212e125f50" - integrity sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg== - optionalDependencies: - "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.0" - "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.0" - "@nomicfoundation/solidity-analyzer-freebsd-x64" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-arm64-msvc" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" - -"@nomiclabs/hardhat-ethers@^2.0.4": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.0.tgz#f55ace2752d0effcf583e754960e9fa89fbe12cd" - integrity sha512-kKCW7xawuD/lw69Yr1yqUUrF0IKmnLNGf+pTVbJ/ctHaRcPrwKI0EPkO1RNXBHlOOZkv6v4DK2PPvq0lL2ykig== - -"@nomiclabs/hardhat-etherscan@3.1.7": - version "3.1.7" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz#72e3d5bd5d0ceb695e097a7f6f5ff6fcbf062b9a" - integrity sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@ethersproject/address" "^5.0.2" - cbor "^8.1.0" - chalk "^2.4.2" - debug "^4.1.1" - fs-extra "^7.0.1" - lodash "^4.17.11" - semver "^6.3.0" - table "^6.8.0" - undici "^5.14.0" - -"@safe-global/safe-core-sdk-types@^1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk-types/-/safe-core-sdk-types-1.9.0.tgz#dba18f34ab905da6c1c03a3262aeb47cc0bead14" - integrity sha512-3VFhnggdLT9kWhnb35eqxEC9cVpW5Sl4E51TZo0RmH1cSzMwlNDbeGINb38PpUbw/wwXFJbCVFmeXELz2ZlCfw== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/contracts" "^5.7.0" - "@gnosis.pm/safe-deployments" "1.19.0" - web3-core "^1.8.1" - web3-utils "^1.8.1" - -"@safe-global/safe-core-sdk-utils@^1.7.2": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk-utils/-/safe-core-sdk-utils-1.7.2.tgz#37df64d90060b986a54426a065473eb793c97dd7" - integrity sha512-nlS9/vtd6rj+2IK0tgt4xq6vqdGOAa+6MwAeiYCoP1ihcqFD38k6LBn7ZdXWjRF9VBvMXTgclkjvzp+PkLKtAw== - dependencies: - "@safe-global/safe-core-sdk-types" "^1.9.0" - semver "^7.3.8" - web3-utils "^1.8.1" - -"@safe-global/safe-core-sdk@^3.3.2": - version "3.3.2" - resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk/-/safe-core-sdk-3.3.2.tgz#571e38eec152668bf2c04771f62f1b123161ec7c" - integrity sha512-IhAxGyYnnG+Zl2zWe1520l00l+FT1QTeMDQlTtnhKCeISs2krXZSEKuolj/sHltXzrswuntaGElAYJyruWEG/A== - dependencies: - "@ethersproject/solidity" "^5.7.0" - "@safe-global/safe-core-sdk-types" "^1.9.0" - "@safe-global/safe-core-sdk-utils" "^1.7.2" - "@safe-global/safe-deployments" "^1.20.2" - ethereumjs-util "^7.1.5" - semver "^7.3.8" - web3-utils "^1.8.1" - -"@safe-global/safe-deployments@^1.20.2": - version "1.21.1" - resolved "https://registry.yarnpkg.com/@safe-global/safe-deployments/-/safe-deployments-1.21.1.tgz#28849ab9441855eb10c50f3ae835f34ec69dede4" - integrity sha512-W5+EGdidRupGvMCHBaV3iNvcfqwzjOZcYWlMndCTo/JSHfe1az79AqOyKVSKK5AyEDt5iUlH8tTjmk8vTuQDwA== - dependencies: - semver "^7.3.7" - -"@safe-global/safe-ethers-lib@^1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@safe-global/safe-ethers-lib/-/safe-ethers-lib-1.9.2.tgz#e99e565d832e5b588c661b59936caa78aa1e3952" - integrity sha512-x8Lq6ViRHW9UC+SAF+VOZ8Lt7jXMhbNS/+WYhSdAKhM+SHwkaaDi03pyZgm4FK0C3Zah7vryU3dSDR/CwEtqhQ== - dependencies: - "@safe-global/safe-core-sdk-types" "^1.9.0" - "@safe-global/safe-core-sdk-utils" "^1.7.2" - ethers "5.7.2" - -"@scure/base@~1.1.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" - integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== - -"@scure/bip32@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.0.tgz#dea45875e7fbc720c2b4560325f1cf5d2246d95b" - integrity sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q== - dependencies: - "@noble/hashes" "~1.1.1" - "@noble/secp256k1" "~1.6.0" - "@scure/base" "~1.1.0" - -"@scure/bip39@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" - integrity sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w== - dependencies: - "@noble/hashes" "~1.1.1" - "@scure/base" "~1.1.0" - -"@sentry/core@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" - integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/hub@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" - integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== - dependencies: - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/minimal@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" - integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/types" "5.30.0" - tslib "^1.9.3" - -"@sentry/node@^5.18.1": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" - integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== - dependencies: - "@sentry/core" "5.30.0" - "@sentry/hub" "5.30.0" - "@sentry/tracing" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - cookie "^0.4.1" - https-proxy-agent "^5.0.0" - lru_map "^0.3.3" - tslib "^1.9.3" - -"@sentry/tracing@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" - integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/types@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" - integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== - -"@sentry/utils@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" - integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== - dependencies: - "@sentry/types" "5.30.0" - tslib "^1.9.3" - -"@solidity-parser/parser@^0.14.0", "@solidity-parser/parser@^0.14.1": - version "0.14.3" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.3.tgz#0d627427b35a40d8521aaa933cc3df7d07bfa36f" - integrity sha512-29g2SZ29HtsqA58pLCtopI1P/cPy5/UAzlcAXO6T/CNJimG6yA8kx4NaseMyJULiC+TEs02Y9/yeHzClqoA0hw== - 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== - -"@typechain/ethers-v5@^8.0.2": - version "8.0.5" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-8.0.5.tgz#d469420e9a73deb7fa076cde9edb45d713dd1b8c" - integrity sha512-ntpj4cS3v4WlDu+hSKSyj9A3o1tKtWC30RX1gobeYymZColeJiUemC1Kgfa0MWGmInm5CKxoHVhEvYVgPOZn1A== - dependencies: - lodash "^4.17.15" - ts-essentials "^7.0.1" - -"@typechain/hardhat@^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-3.1.0.tgz#88bd9e9d55e30fbece6fbb34c03ecd40a8b2013a" - integrity sha512-C6Be6l+vTpao19PvMH2CB/lhL1TRLkhdPkvQCF/zqkY1e+0iqY2Bb9Jd3PTt6I8QvMm89ZDerrCJC9927ZHmlg== - dependencies: - fs-extra "^9.1.0" - -"@types/async-eventemitter@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz#f8e6280e87e8c60b2b938624b0a3530fb3e24712" - integrity sha512-M2P4Ng26QbAeITiH7w1d7OxtldgfAe0wobpyJzVK/XOb0cUGKU2R4pfAhqcJBXAe2ife5ZOhSv4wk7p+ffURtg== - -"@types/bn.js@^4.11.3": - version "4.11.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" - -"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== - dependencies: - "@types/node" "*" - -"@types/chai-as-promised@^7.1.3", "@types/chai-as-promised@^7.1.4": - version "7.1.5" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" - integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== - dependencies: - "@types/chai" "*" - -"@types/chai@*", "@types/chai@^4.2.22": - version "4.3.3" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.3.tgz#3c90752792660c4b562ad73b3fbd68bf3bc7ae07" - integrity sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g== - -"@types/concat-stream@^1.6.0": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" - integrity sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA== - dependencies: - "@types/node" "*" - -"@types/form-data@0.0.33": - version "0.0.33" - resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" - integrity sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw== - dependencies: - "@types/node" "*" - -"@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== - -"@types/lru-cache@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" - integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== - -"@types/mocha@^9.0.0": - version "9.1.1" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" - integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== - -"@types/node@*": - version "18.8.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.8.5.tgz#6a31f820c1077c3f8ce44f9e203e68a176e8f59e" - integrity sha512-Bq7G3AErwe5A/Zki5fdD3O6+0zDChhg671NfPjtIcbtzDNZTv4NPKMRFr7gtYPG7y+B8uTiNK4Ngd9T0FTar6Q== - -"@types/node@^10.0.3": - version "10.17.60" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" - integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== - -"@types/node@^12.12.6": - version "12.20.55" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" - integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== - -"@types/node@^16.11.7": - version "16.11.65" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.65.tgz#59500b86af757d6fcabd3dec32fecb6e357d7a45" - integrity sha512-Vfz7wGMOr4jbQGiQHVJm8VjeQwM9Ya7mHe9LtQ264/Epf5n1KiZShOFqk++nBzw6a/ubgYdB9Od7P+MH/LjoWw== - -"@types/node@^8.0.0": - version "8.10.66" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" - integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== - -"@types/pbkdf2@^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" - integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== - dependencies: - "@types/node" "*" - -"@types/prettier@^2.1.1": - version "2.7.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" - integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow== - -"@types/qs@^6.2.31": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== - -"@types/readable-stream@^2.3.13": - version "2.3.15" - resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" - integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== - dependencies: - "@types/node" "*" - safe-buffer "~5.1.1" - -"@types/secp256k1@^4.0.1": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" - integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== - dependencies: - "@types/node" "*" - -"@typescript-eslint/eslint-plugin@^5.18.0": - version "5.40.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.0.tgz#0159bb71410eec563968288a17bd4478cdb685bd" - integrity sha512-FIBZgS3DVJgqPwJzvZTuH4HNsZhHMa9SjxTKAZTlMsPw/UzpEjcf9f4dfgDJEHjK+HboUJo123Eshl6niwEm/Q== - dependencies: - "@typescript-eslint/scope-manager" "5.40.0" - "@typescript-eslint/type-utils" "5.40.0" - "@typescript-eslint/utils" "5.40.0" - debug "^4.3.4" - ignore "^5.2.0" - regexpp "^3.2.0" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/parser@^5.18.0": - version "5.40.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.40.0.tgz#432bddc1fe9154945660f67c1ba6d44de5014840" - integrity sha512-Ah5gqyX2ySkiuYeOIDg7ap51/b63QgWZA7w6AHtFrag7aH0lRQPbLzUjk0c9o5/KZ6JRkTTDKShL4AUrQa6/hw== - dependencies: - "@typescript-eslint/scope-manager" "5.40.0" - "@typescript-eslint/types" "5.40.0" - "@typescript-eslint/typescript-estree" "5.40.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.40.0": - version "5.40.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.40.0.tgz#d6ea782c8e3a2371ba3ea31458dcbdc934668fc4" - integrity sha512-d3nPmjUeZtEWRvyReMI4I1MwPGC63E8pDoHy0BnrYjnJgilBD3hv7XOiETKLY/zTwI7kCnBDf2vWTRUVpYw0Uw== - dependencies: - "@typescript-eslint/types" "5.40.0" - "@typescript-eslint/visitor-keys" "5.40.0" - -"@typescript-eslint/type-utils@5.40.0": - version "5.40.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.40.0.tgz#4964099d0158355e72d67a370249d7fc03331126" - integrity sha512-nfuSdKEZY2TpnPz5covjJqav+g5qeBqwSHKBvz7Vm1SAfy93SwKk/JeSTymruDGItTwNijSsno5LhOHRS1pcfw== - dependencies: - "@typescript-eslint/typescript-estree" "5.40.0" - "@typescript-eslint/utils" "5.40.0" - debug "^4.3.4" - tsutils "^3.21.0" - -"@typescript-eslint/types@5.40.0": - version "5.40.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.40.0.tgz#8de07e118a10b8f63c99e174a3860f75608c822e" - integrity sha512-V1KdQRTXsYpf1Y1fXCeZ+uhjW48Niiw0VGt4V8yzuaDTU8Z1Xl7yQDyQNqyAFcVhpYXIVCEuxSIWTsLDpHgTbw== - -"@typescript-eslint/typescript-estree@5.40.0": - version "5.40.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.0.tgz#e305e6a5d65226efa5471ee0f12e0ffaab6d3075" - integrity sha512-b0GYlDj8TLTOqwX7EGbw2gL5EXS2CPEWhF9nGJiGmEcmlpNBjyHsTwbqpyIEPVpl6br4UcBOYlcI2FJVtJkYhg== - dependencies: - "@typescript-eslint/types" "5.40.0" - "@typescript-eslint/visitor-keys" "5.40.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.40.0": - version "5.40.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.40.0.tgz#647f56a875fd09d33c6abd70913c3dd50759b772" - integrity sha512-MO0y3T5BQ5+tkkuYZJBjePewsY+cQnfkYeRqS6tPh28niiIwPnQ1t59CSRcs1ZwJJNOdWw7rv9pF8aP58IMihA== - dependencies: - "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.40.0" - "@typescript-eslint/types" "5.40.0" - "@typescript-eslint/typescript-estree" "5.40.0" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.40.0": - version "5.40.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.0.tgz#dd2d38097f68e0d2e1e06cb9f73c0173aca54b68" - integrity sha512-ijJ+6yig+x9XplEpG2K6FUdJeQGGj/15U3S56W9IqXKJqleuD7zJ2AX/miLezwxpd7ZxDAqO87zWufKg+RPZyQ== - dependencies: - "@typescript-eslint/types" "5.40.0" - eslint-visitor-keys "^3.3.0" - -"@ungap/promise-all-settled@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" - integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -abbrev@1.0.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -abortcontroller-polyfill@^1.7.3: - version "1.7.5" - resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" - integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== - -abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" - integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== - dependencies: - buffer "^6.0.3" - catering "^2.1.0" - is-buffer "^2.0.5" - level-supports "^4.0.0" - level-transcoder "^1.0.1" - module-error "^1.0.1" - queue-microtask "^1.2.3" - -acorn-jsx@^5.0.0, acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -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@^6.0.7: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - -acorn@^8.4.1, acorn@^8.8.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== - -adm-zip@^0.4.16: - version "0.4.16" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" - integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== - -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== - -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^8.0.1: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== - -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-colors@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - -ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - -ansi-escapes@^4.3.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" - integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -antlr4@4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" - integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== - -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== - -anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -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@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-back@^3.0.1, array-back@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" - integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== - -array-back@^4.0.1, array-back@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" - integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array-uniq@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== - -asap@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - -asn1@~0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" - integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -ast-parents@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" - integrity sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA== - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - -async-eventemitter@^0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" - integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== - dependencies: - async "^2.4.0" - -async@1.x: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== - -async@^2.4.0: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== - -aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== - -axios@^0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" - integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== - dependencies: - follow-redirects "^1.14.4" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base-x@^3.0.2: - version "3.0.9" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" - integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== - dependencies: - safe-buffer "^5.0.1" - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== - dependencies: - tweetnacl "^0.14.3" - -bech32@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" - integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== - -bigint-crypto-utils@^3.0.23: - version "3.1.7" - resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.1.7.tgz#c4c1b537c7c1ab7aadfaecf3edfd45416bf2c651" - integrity sha512-zpCQpIE2Oy5WIQpjC9iYZf8Uh9QqoS51ZCooAcNvzv1AQ3VWdT52D0ksr1+/faeK8HVIej1bxXcP75YcqH3KPA== - dependencies: - bigint-mod-arith "^3.1.0" - -bigint-mod-arith@^3.1.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bigint-mod-arith/-/bigint-mod-arith-3.1.2.tgz#658e416bc593a463d97b59766226d0a3021a76b1" - integrity sha512-nx8J8bBeiRR+NlsROFH9jHswW5HO8mgfOSqW0AmjicMMvaONDa8AO+5ViKDUUNytBPWiwfvZP4/Bj4Y3lUfvgQ== - -bignumber.js@^9.0.0: - version "9.1.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" - integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -blakejs@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" - integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== - -bn.js@4.11.6: - version "4.11.6" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== - -bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - -browser-level@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browser-level/-/browser-level-1.0.1.tgz#36e8c3183d0fe1c405239792faaab5f315871011" - integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ== - dependencies: - abstract-level "^1.0.2" - catering "^2.1.1" - module-error "^1.0.2" - run-parallel-limit "^1.1.0" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -browserify-aes@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -bs58@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== - dependencies: - base-x "^3.0.2" - -bs58check@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== - dependencies: - bs58 "^4.0.0" - create-hash "^1.1.0" - safe-buffer "^5.1.2" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== - -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - -bufferutil@^4.0.1: - version "4.0.7" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" - integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== - dependencies: - node-gyp-build "^4.3.0" - -busboy@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" - integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== - dependencies: - streamsearch "^1.1.0" - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^6.0.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -case@^1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" - integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== - -caseless@^0.12.0, caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== - -catering@^2.1.0, catering@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" - integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== - -cbor@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" - integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== - dependencies: - nofilter "^3.1.0" - -chai-as-promised@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" - integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== - dependencies: - check-error "^1.0.2" - -chai@^4.3.4: - version "4.3.6" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" - integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - loupe "^2.3.1" - pathval "^1.1.1" - type-detect "^4.0.5" - -chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^2.0.0, chalk@^2.1.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== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.1.2.tgz#d957f370038b75ac572471e83be4c5ca9f8e8c45" - integrity sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ== - -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -charenc@0.0.2, "charenc@>= 0.0.1": - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== - -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== - -chokidar@3.5.3, chokidar@^3.4.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -classic-level@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.2.0.tgz#2d52bdec8e7a27f534e67fdeb890abef3e643c27" - integrity sha512-qw5B31ANxSluWz9xBzklRWTUAJ1SXIdaVKTVS7HcTGKOAmExx65Wo5BUICW+YGORe2FOUaDghoI9ZDxj82QcFg== - dependencies: - abstract-level "^1.0.2" - catering "^2.1.0" - module-error "^1.0.1" - napi-macros "~2.0.0" - node-gyp-build "^4.3.0" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== - dependencies: - restore-cursor "^2.0.0" - -cli-table3@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" - integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== - dependencies: - object-assign "^4.1.0" - string-width "^2.1.1" - optionalDependencies: - colors "^1.1.2" - -cli-table3@^0.6.0: - version "0.6.3" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" - integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== - dependencies: - string-width "^4.2.0" - optionalDependencies: - "@colors/colors" "1.5.0" - -cli-width@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" - integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== - -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colors@1.4.0, colors@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -command-exists@^1.2.8: - version "1.2.9" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" - integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== - -command-line-args@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" - integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== - dependencies: - array-back "^3.1.0" - find-replace "^3.0.0" - lodash.camelcase "^4.3.0" - typical "^4.0.0" - -command-line-usage@^6.1.0: - version "6.1.3" - resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" - integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== - dependencies: - array-back "^4.0.2" - chalk "^2.4.2" - table-layout "^1.0.2" - typical "^5.2.0" - -commander@2.18.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" - integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== - -commander@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" - integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -concat-stream@^1.6.0, concat-stream@^1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -cookie@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cosmiconfig@^5.0.7: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -crc-32@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" - integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -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-fetch@^3.1.4: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== - dependencies: - node-fetch "2.6.7" - -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypt@0.0.2, "crypt@>= 0.0.1": - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== - dependencies: - assert-plus "^1.0.0" - -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -debug@4.3.3: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -debug@^2.2.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== - dependencies: - type-detect "^4.0.0" - -deep-eql@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.1.tgz#b1154ea8c95012d9f23f37f4eecfd2ee8e5b9323" - integrity sha512-rc6HkZswtl+KMi/IODZ8k7C/P37clC2Rf1HYI11GqdbgvggIyHjsU5MdjlTlaP6eu24c0sR3mcW2SqsVZ1sXUw== - dependencies: - type-detect "^4.0.0" - -deep-extend@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@^0.1.3, deep-is@~0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -deep-object-diff@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.9.tgz#6df7ef035ad6a0caa44479c536ed7b02570f4595" - integrity sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA== - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -diff-sequences@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" - integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== - -diff@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - -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== - -diff@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" - integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dotenv@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" - integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -enquirer@^2.3.0: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - -env-paths@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es5-ext@^0.10.35, es5-ext@^0.10.50: - version "0.10.62" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" - integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== - dependencies: - es6-iterator "^2.0.3" - es6-symbol "^3.1.3" - next-tick "^1.1.0" - -es6-iterator@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-promise@^4.2.8: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-symbol@^3.1.1, es6-symbol@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escodegen@1.8.x: - version "1.8.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - integrity sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A== - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^1.3.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint@^5.6.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.11" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" - table "^5.2.3" - text-table "^0.2.0" - -eslint@^8.12.0: - version "8.25.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.25.0.tgz#00eb962f50962165d0c4ee3327708315eaa8058b" - integrity sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A== - dependencies: - "@eslint/eslintrc" "^1.3.3" - "@humanwhocodes/config-array" "^0.10.5" - "@humanwhocodes/module-importer" "^1.0.1" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.1" - globals "^13.15.0" - globby "^11.1.0" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-sdsl "^4.1.4" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - -espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== - dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" - -espree@^9.4.0: - version "9.4.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a" - integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw== - dependencies: - acorn "^8.8.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" - -esprima@2.7.x, esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A== - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.0.1, esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.1.0, esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA== - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -eth-gas-reporter@^0.2.25: - version "0.2.25" - resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.25.tgz#546dfa946c1acee93cb1a94c2a1162292d6ff566" - integrity sha512-1fRgyE4xUB8SoqLgN3eDfpDfwEfRxh2Sz1b7wzFbyQA+9TekMmvSjjoRu9SKcSVyK+vLkLIsVbJDsTWjw195OQ== - dependencies: - "@ethersproject/abi" "^5.0.0-beta.146" - "@solidity-parser/parser" "^0.14.0" - cli-table3 "^0.5.0" - colors "1.4.0" - ethereum-cryptography "^1.0.3" - ethers "^4.0.40" - fs-readdir-recursive "^1.1.0" - lodash "^4.17.14" - markdown-table "^1.1.3" - mocha "^7.1.1" - req-cwd "^2.0.0" - request "^2.88.0" - request-promise-native "^1.0.5" - sha1 "^1.1.1" - sync-request "^6.0.0" - -ethereum-bloom-filters@^1.0.6: - version "1.0.10" - resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" - integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== - dependencies: - js-sha3 "^0.8.0" - -ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" - integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== - dependencies: - "@types/pbkdf2" "^3.0.0" - "@types/secp256k1" "^4.0.1" - blakejs "^1.1.0" - browserify-aes "^1.2.0" - bs58check "^2.1.2" - create-hash "^1.2.0" - create-hmac "^1.1.7" - hash.js "^1.1.7" - keccak "^3.0.0" - pbkdf2 "^3.0.17" - randombytes "^2.1.0" - safe-buffer "^5.1.2" - scrypt-js "^3.0.0" - secp256k1 "^4.0.1" - setimmediate "^1.0.5" - -ethereum-cryptography@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz#74f2ac0f0f5fe79f012c889b3b8446a9a6264e6d" - integrity sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ== - dependencies: - "@noble/hashes" "1.1.2" - "@noble/secp256k1" "1.6.3" - "@scure/bip32" "1.1.0" - "@scure/bip39" "1.1.0" - -ethereumjs-abi@^0.6.8: - version "0.6.8" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" - integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" - integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== - dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.3" - -ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: - version "7.1.5" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" - integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethers@5.7.2, ethers@^5.1.0, ethers@^5.7.1, ethers@^5.7.2: - version "5.7.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" - integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.2" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - -ethers@^4.0.40: - version "4.0.49" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.49.tgz#0eb0e9161a0c8b4761be547396bbe2fb121a8894" - integrity sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg== - dependencies: - aes-js "3.0.0" - bn.js "^4.11.9" - elliptic "6.5.4" - hash.js "1.1.3" - js-sha3 "0.5.7" - scrypt-js "2.0.4" - setimmediate "1.0.4" - uuid "2.0.1" - xmlhttprequest "1.8.0" - -ethers@^5.7.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.1.tgz#48c83a44900b5f006eb2f65d3ba6277047fd4f33" - integrity sha512-5krze4dRLITX7FpU8J4WscXqADiKmyeNlylmmDLbS95DaZpBhDe2YSwRQwKXWNyXcox7a3gBgm/MkGXV1O1S/Q== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.1" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - -ethjs-unit@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== - dependencies: - bn.js "4.11.6" - number-to-bn "1.7.0" - -ethjs-util@0.1.6, ethjs-util@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - -eventemitter3@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== - -evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -ext@^1.1.2: - version "1.7.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" - integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== - dependencies: - type "^2.7.2" - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== - -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-glob@^3.2.7, fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-replace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" - integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== - dependencies: - array-back "^3.0.1" - -find-up@5.0.0, find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== - dependencies: - locate-path "^2.0.0" - -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== - -follow-redirects@^1.12.1, follow-redirects@^1.14.4: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== - -form-data@^2.2.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" - integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -fp-ts@1.19.3: - version "1.19.3" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" - integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== - -fp-ts@^1.0.0: - version "1.19.5" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" - integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== - -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" - -fs-extra@^7.0.0, fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-readdir-recursive@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" - integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== - -get-intrinsic@^1.0.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-intrinsic@^1.1.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" - integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-port@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - integrity sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg== - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== - dependencies: - assert-plus "^1.0.0" - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^5.0.15: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA== - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.2, glob@^7.1.3, glob@^7.1.6: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.7.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.15.0: - version "13.17.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" - integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, 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== - -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -handlebars@^4.0.1: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.0" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - -"hardhat-chai-matchers@https://github.com/jflatow/hardhat/releases/download/viaIR/nomicfoundation-hardhat-chai-matchers-v1.0.4.tgz": - version "1.0.4" - resolved "https://github.com/jflatow/hardhat/releases/download/viaIR/nomicfoundation-hardhat-chai-matchers-v1.0.4.tgz#785d92b3ad4a66a888153ac0dcc55b319d5c9b65" - dependencies: - "@ethersproject/abi" "^5.1.2" - "@types/chai-as-promised" "^7.1.3" - chai-as-promised "^7.1.1" - chalk "^2.4.2" - deep-eql "^4.0.1" - ordinal "^1.0.3" - -hardhat-change-network@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/hardhat-change-network/-/hardhat-change-network-0.0.7.tgz#9f9b7943ff966515658b70bf5e44bc2f073af402" - integrity sha512-Usp9fJan9SOJnOlVcv/jMJDchseE7bIDA5ZsBnracgVk4MiBwkvMqpmLWn5G1aDBvnUCthvS2gO3odfahgkV0Q== - -hardhat-contract-sizer@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/hardhat-contract-sizer/-/hardhat-contract-sizer-2.10.0.tgz#72646f43bfe50e9a5702c9720c9bc3e77d93a2c9" - integrity sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA== - dependencies: - chalk "^4.0.0" - cli-table3 "^0.6.0" - strip-ansi "^6.0.0" - -hardhat-cover@compound-finance/hardhat-cover: - version "1.0.0" - resolved "https://codeload.github.com/compound-finance/hardhat-cover/tar.gz/c9064e8bf04d3ae34773adbfee70cade741078ec" - -hardhat-gas-reporter@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz#9a2afb354bc3b6346aab55b1c02ca556d0e16450" - integrity sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg== - dependencies: - array-uniq "1.0.3" - eth-gas-reporter "^0.2.25" - sha1 "^1.1.1" - -hardhat@^2.0.4: - version "2.12.0" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.0.tgz#51e59f1ff4991bcb66d1a380ea807e6c15fcac34" - integrity sha512-mNJFbVG479HwOzxiaLxobyvED2M1aEAuPPYhEo1+88yicMDSTrU2JIS7vV+V0GSNQKaDoiHCmV6bcKjiljT/dQ== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-evm" "^1.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@nomicfoundation/ethereumjs-vm" "^6.0.0" - "@nomicfoundation/solidity-analyzer" "^0.1.0" - "@sentry/node" "^5.18.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" - abort-controller "^3.0.0" - adm-zip "^0.4.16" - aggregate-error "^3.0.0" - ansi-escapes "^4.3.0" - chalk "^2.4.2" - chokidar "^3.4.0" - ci-info "^2.0.0" - debug "^4.1.1" - enquirer "^2.3.0" - env-paths "^2.2.0" - ethereum-cryptography "^1.0.3" - ethereumjs-abi "^0.6.8" - find-up "^2.1.0" - fp-ts "1.19.3" - fs-extra "^7.0.1" - glob "7.2.0" - immutable "^4.0.0-rc.12" - io-ts "1.10.4" - keccak "^3.0.2" - lodash "^4.17.11" - mnemonist "^0.38.0" - mocha "^10.0.0" - p-map "^4.0.0" - qs "^6.7.0" - raw-body "^2.4.1" - resolve "1.17.0" - semver "^6.3.0" - solc "0.7.3" - source-map-support "^0.5.13" - stacktrace-parser "^0.1.10" - tsort "0.0.1" - undici "^5.4.0" - uuid "^8.3.2" - ws "^7.4.6" - -hardhat@^2.12.2: - version "2.14.0" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.14.0.tgz#b60c74861494aeb1b50803cf04cc47865a42b87a" - integrity sha512-73jsInY4zZahMSVFurSK+5TNCJTXMv+vemvGia0Ac34Mm19fYp6vEPVGF3sucbumszsYxiTT2TbS8Ii2dsDSoQ== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-blockchain" "7.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-evm" "2.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-statemanager" "2.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - "@nomicfoundation/ethereumjs-vm" "7.0.1" - "@nomicfoundation/solidity-analyzer" "^0.1.0" - "@sentry/node" "^5.18.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" - abort-controller "^3.0.0" - adm-zip "^0.4.16" - aggregate-error "^3.0.0" - ansi-escapes "^4.3.0" - chalk "^2.4.2" - chokidar "^3.4.0" - ci-info "^2.0.0" - debug "^4.1.1" - enquirer "^2.3.0" - env-paths "^2.2.0" - ethereum-cryptography "^1.0.3" - ethereumjs-abi "^0.6.8" - find-up "^2.1.0" - fp-ts "1.19.3" - fs-extra "^7.0.1" - glob "7.2.0" - immutable "^4.0.0-rc.12" - io-ts "1.10.4" - keccak "^3.0.2" - lodash "^4.17.11" - mnemonist "^0.38.0" - mocha "^10.0.0" - p-map "^4.0.0" - qs "^6.7.0" - raw-body "^2.4.1" - resolve "1.17.0" - semver "^6.3.0" - solc "0.7.3" - source-map-support "^0.5.13" - stacktrace-parser "^0.1.10" - tsort "0.0.1" - undici "^5.14.0" - uuid "^8.3.2" - ws "^7.4.6" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.0" - -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -http-basic@^8.1.1: - version "8.1.3" - resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" - integrity sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw== - dependencies: - caseless "^0.12.0" - concat-stream "^1.6.2" - http-response-object "^3.0.1" - parse-cache-control "^1.0.1" - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg== - -http-response-object@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" - integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== - dependencies: - "@types/node" "^10.0.3" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - -iconv-lite@0.4.24, iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -immutable@^4.0.0-rc.12: - version "4.1.0" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef" - integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ== - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inquirer@^6.2.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" - integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.12" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - -io-ts@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" - integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== - dependencies: - fp-ts "^1.0.0" - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-buffer@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-buffer@~1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-callable@^1.1.3: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-hex-prefixed@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-typed-array@^1.1.10, is-typed-array@^1.1.3: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== - -jest-diff@^27.4.2: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" - integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== - dependencies: - chalk "^4.0.0" - diff-sequences "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - -jest-get-type@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" - integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== - -js-sdsl@^4.1.4: - version "4.1.5" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.5.tgz#1ff1645e6b4d1b028cd3f862db88c9d887f26e2a" - integrity sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q== - -js-sha3@0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g== - -js-sha3@0.8.0, js-sha3@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@4.1.0, js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-schema@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== - -jsonfile@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -jsprim@^1.2.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" - integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - -keccak@^3.0.0, keccak@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" - integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - readable-stream "^3.6.0" - -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== - optionalDependencies: - graceful-fs "^4.1.9" - -level-supports@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" - integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== - -level-transcoder@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" - integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== - dependencies: - buffer "^6.0.3" - module-error "^1.0.1" - -level@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" - integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ== - dependencies: - browser-level "^1.0.1" - classic-level "^1.2.0" - -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.truncate@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" - integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== - -lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -loupe@^2.3.1: - version "2.3.4" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" - integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== - dependencies: - get-func-name "^2.0.0" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -lru_map@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" - integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== - -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== - -markdown-table@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" - integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== - -mcl-wasm@^0.7.1: - version "0.7.9" - resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" - integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -md5@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" - integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== - dependencies: - charenc "0.0.2" - crypt "0.0.2" - is-buffer "~1.1.6" - -memory-level@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" - integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og== - dependencies: - abstract-level "^1.0.0" - functional-red-black-tree "^1.0.1" - module-error "^1.0.1" - -memorystream@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - -"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" - integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.5, 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== - -mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@~0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -mnemonist@^0.38.0: - version "0.38.5" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" - integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== - dependencies: - obliterator "^2.0.0" - -mocha-junit-reporter@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-2.1.0.tgz#7997348c2e757686c54e42b3756930b55a4518a4" - integrity sha512-Zhz1J+XqJUaAOuSFtHgi2+b+W3rP1SZtaU3HHNNp1iEKMSeoC1/EQUVkGknkLNOBxJhXJ4xLgOr8TbYAZOkUIw== - dependencies: - debug "^2.2.0" - md5 "^2.1.0" - mkdirp "~0.5.1" - strip-ansi "^6.0.1" - xml "^1.0.0" - -mocha-multi-reporters@hayesgm/mocha-multi-reporters#hayesgm/reporter-options-to-option: - version "1.5.1" - resolved "https://codeload.github.com/hayesgm/mocha-multi-reporters/tar.gz/0df9421cd7211e83f097846d16de6706988ad445" - dependencies: - debug "^4.1.1" - lodash "^4.17.15" - -mocha@^10.0.0, mocha@^7.1.1, mocha@^9.1.3: - version "9.2.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" - integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== - dependencies: - "@ungap/promise-all-settled" "1.1.2" - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.3" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - growl "1.10.5" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "4.2.1" - ms "2.1.3" - nanoid "3.3.1" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - which "2.0.2" - workerpool "6.2.0" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - -module-error@^1.0.1, module-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" - integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== - -nanoid@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" - integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== - -napi-macros@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" - integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -neo-async@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -next-tick@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" - integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -nock@^13.2.2: - version "13.2.9" - resolved "https://registry.yarnpkg.com/nock/-/nock-13.2.9.tgz#4faf6c28175d36044da4cfa68e33e5a15086ad4c" - integrity sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA== - dependencies: - debug "^4.1.0" - json-stringify-safe "^5.0.1" - lodash "^4.17.21" - propagate "^2.0.0" - -node-addon-api@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" - integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== - -node-fetch@2, node-fetch@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - -node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" - integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg== - -nofilter@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" - integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== - -nopt@3.x: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== - dependencies: - abbrev "1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -number-to-bn@1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== - dependencies: - bn.js "4.11.6" - strip-hex-prefix "1.0.0" - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -obliterator@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" - integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== - -oboe@2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" - integrity sha512-zRFWiF+FoicxEs3jNI/WYUrVEgA7DeET/InK0XQuudGHRg8iIob3cNPrJTKaz4004uaA9Pbe+Dwa8iluhjLZWA== - dependencies: - http-https "^1.0.0" - -once@1.x, once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== - dependencies: - mimic-fn "^1.0.0" - -optionator@^0.8.1, optionator@^0.8.2: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -ordinal@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ordinal/-/ordinal-1.0.3.tgz#1a3c7726a61728112f50944ad7c35c06ae3a0d4d" - integrity sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ== - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== - dependencies: - p-limit "^1.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-cache-control@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" - integrity sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg== - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== - -pbkdf2@^3.0.17: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - -prettier@^1.14.3: - version "1.19.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== - -prettier@^2.1.2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" - integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== - -pretty-format@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" - integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== - dependencies: - ansi-regex "^5.0.1" - ansi-styles "^5.0.0" - react-is "^17.0.1" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -promise@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.2.0.tgz#a1f6280ab67457fbfc8aad2b198c9497e9e5c806" - integrity sha512-+CMAlLHqwRYwBMXKCP+o8ns7DN+xHDUiI+0nArsiJ9y+kJVPLFxEaSw6Ha9s9H0tftxg2Yzl25wqj9G7m5wLZg== - dependencies: - asap "~2.0.6" - -propagate@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" - integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== - -psl@^1.1.28: - version "1.9.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@^6.4.0, qs@^6.7.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -qs@~6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" - integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== - -queue-microtask@^1.2.2, queue-microtask@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -raw-body@^2.4.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -react-is@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== - -readable-stream@^2.2.2: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.6.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== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -reduce-flatten@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" - integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== - -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -req-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" - integrity sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ== - dependencies: - req-from "^2.0.0" - -req-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/req-from/-/req-from-2.0.0.tgz#d74188e47f93796f4aa71df6ee35ae689f3e0e70" - integrity sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA== - dependencies: - resolve-from "^3.0.0" - -request-promise-core@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" - integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== - dependencies: - lodash "^4.17.19" - -request-promise-native@^1.0.5: - version "1.0.9" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" - integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== - dependencies: - request-promise-core "1.1.4" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - -request@^2.88.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-from-string@^2.0.0, require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve@1.1.x: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg== - -resolve@1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@^2.2.8: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rlp@^2.2.3, rlp@^2.2.4: - version "2.2.7" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" - integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== - dependencies: - bn.js "^5.2.0" - -run-async@^2.2.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - -run-parallel-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" - integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw== - dependencies: - queue-microtask "^1.2.2" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -rustbn.js@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" - integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== - -rxjs@^6.4.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sc-istanbul@^0.4.5: - version "0.4.6" - resolved "https://registry.yarnpkg.com/sc-istanbul/-/sc-istanbul-0.4.6.tgz#cf6784355ff2076f92d70d59047d71c13703e839" - integrity sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g== - dependencies: - abbrev "1.0.x" - async "1.x" - escodegen "1.8.x" - esprima "2.7.x" - glob "^5.0.15" - handlebars "^4.0.1" - js-yaml "3.x" - mkdirp "0.5.x" - nopt "3.x" - once "1.x" - resolve "1.1.x" - supports-color "^3.1.0" - which "^1.1.1" - wordwrap "^1.0.0" - -scrypt-js@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" - integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== - -scrypt-js@3.0.1, scrypt-js@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" - integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== - -secp256k1@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" - integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== - dependencies: - elliptic "^6.5.4" - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - -semver@^5.5.0, semver@^5.5.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.7, semver@^7.3.8: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" - -serialize-javascript@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -setimmediate@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - integrity sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog== - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -sha1@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848" - integrity sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA== - dependencies: - charenc ">= 0.0.1" - crypt ">= 0.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.2: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -solc@0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" - integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== - dependencies: - command-exists "^1.2.8" - commander "3.0.2" - follow-redirects "^1.12.1" - fs-extra "^0.30.0" - js-sha3 "0.8.0" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - tmp "0.0.33" - -solhint@^3.3.6: - version "3.3.7" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.3.7.tgz#b5da4fedf7a0fee954cb613b6c55a5a2b0063aa7" - integrity sha512-NjjjVmXI3ehKkb3aNtRJWw55SUVJ8HMKKodwe0HnejA+k0d2kmhw7jvpa+MCTbcEgt8IWSwx0Hu6aCo/iYOZzQ== - dependencies: - "@solidity-parser/parser" "^0.14.1" - ajv "^6.6.1" - antlr4 "4.7.1" - ast-parents "0.0.1" - chalk "^2.4.2" - commander "2.18.0" - cosmiconfig "^5.0.7" - eslint "^5.6.0" - fast-diff "^1.1.2" - glob "^7.1.3" - ignore "^4.0.6" - js-yaml "^3.12.0" - lodash "^4.17.11" - semver "^6.3.0" - optionalDependencies: - prettier "^1.14.3" - -source-map-support@^0.5.13, source-map-support@^0.5.17: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0, source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA== - dependencies: - amdefine ">=0.0.4" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -sshpk@^1.7.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" - integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -stacktrace-parser@^0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" - integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== - dependencies: - type-fest "^0.7.1" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -stealthy-require@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g== - -streamsearch@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" - integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== - -string-format@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" - integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== - -string-width@^2.1.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-hex-prefix@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== - dependencies: - is-hex-prefixed "1.0.0" - -strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strip-json-comments@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -supports-color@8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-color@^3.1.0: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A== - dependencies: - has-flag "^1.0.0" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -sync-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.1.0.tgz#e96217565b5e50bbffe179868ba75532fb597e68" - integrity sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw== - dependencies: - http-response-object "^3.0.1" - sync-rpc "^1.2.1" - then-request "^6.0.0" - -sync-rpc@^1.2.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.6.tgz#b2e8b2550a12ccbc71df8644810529deb68665a7" - integrity sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw== - dependencies: - get-port "^3.1.0" - -table-layout@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" - integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== - dependencies: - array-back "^4.0.1" - deep-extend "~0.6.0" - typical "^5.2.0" - wordwrapjs "^4.0.0" - -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -table@^6.8.0: - version "6.8.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" - integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== - dependencies: - ajv "^8.0.1" - lodash.truncate "^4.4.2" - slice-ansi "^4.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -then-request@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.2.tgz#ec18dd8b5ca43aaee5cb92f7e4c1630e950d4f0c" - integrity sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA== - dependencies: - "@types/concat-stream" "^1.6.0" - "@types/form-data" "0.0.33" - "@types/node" "^8.0.0" - "@types/qs" "^6.2.31" - caseless "~0.12.0" - concat-stream "^1.6.0" - form-data "^2.2.0" - http-basic "^8.1.1" - http-response-object "^3.0.1" - promise "^8.0.0" - qs "^6.4.0" - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - -tmp@0.0.33, tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tough-cookie@^2.3.3, tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -ts-command-line-args@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.3.1.tgz#b6188e42efc6cf7a8898e438a873fbb15505ddd6" - integrity sha512-FR3y7pLl/fuUNSmnPhfLArGqRrpojQgIEEOVzYx9DhTmfIN7C9RWSfpkJEF4J+Gk7aVx5pak8I7vWZsaN4N84g== - dependencies: - chalk "^4.1.0" - command-line-args "^5.1.1" - command-line-usage "^6.1.0" - string-format "^2.0.0" - -ts-essentials@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" - integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== - -ts-node@^10.4.0: - 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" - -ts-node@^8.1.0: - version "8.10.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" - integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA== - dependencies: - arg "^4.1.0" - diff "^4.0.1" - make-error "^1.1.1" - source-map-support "^0.5.17" - yn "3.1.1" - -ts-node@^9.1.0: - version "9.1.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" - integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== - dependencies: - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - source-map-support "^0.5.17" - yn "3.1.1" - -tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tsort@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" - integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== - dependencies: - safe-buffer "^5.0.1" - -tweetnacl-util@^0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" - integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== - -tweetnacl@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" - integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" - integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== - -typechain@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-6.1.0.tgz#462a35f555accf870689d1ba5698749108d0ce81" - integrity sha512-GGfkK0p3fUgz8kYxjSS4nKcWXE0Lo+teHTetghousIK5njbNoYNDlwn91QIyD181L3fVqlTvBE0a/q3AZmjNfw== - dependencies: - "@types/prettier" "^2.1.1" - debug "^4.1.1" - fs-extra "^7.0.0" - glob "^7.1.6" - js-sha3 "^0.8.0" - lodash "^4.17.15" - mkdirp "^1.0.4" - prettier "^2.1.2" - ts-command-line-args "^2.2.0" - ts-essentials "^7.0.1" - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== - -typescript@^4.1.2, typescript@^4.4.4: - version "4.8.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" - integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== - -typescript@~4.0.3: - version "4.0.8" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.8.tgz#5739105541db80a971fdbd0d56511d1a6f17d37f" - integrity sha512-oz1765PN+imfz1MlZzSZPtC/tqcwsCyIYA8L47EkRnRW97ztRk83SzMiWLrnChC0vqoYxSU1fcFUDA5gV/ZiPg== - -typical@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" - integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== - -typical@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" - integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== - -uglify-js@^3.1.4: - version "3.17.3" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.3.tgz#f0feedf019c4510f164099e8d7e72ff2d7304377" - integrity sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg== - -undici@^5.14.0, undici@^5.21.2: - version "5.22.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.22.0.tgz#5e205d82a5aecc003fc4388ccd3d2c6e8674a0ad" - integrity sha512-fR9RXCc+6Dxav4P9VV/sp5w3eFiSdOjJYsbtWfd4s5L5C4ogyuVpdKIVHeW0vV1MloM65/f7W45nR9ZxwVdyiA== - dependencies: - busboy "^1.6.0" - -undici@^5.4.0: - version "5.11.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.11.0.tgz#1db25f285821828fc09d3804b9e2e934ae86fc13" - integrity sha512-oWjWJHzFet0Ow4YZBkyiJwiK5vWqEYoH7BINzJAJOLedZ++JpAlCbUktW2GQ2DS2FpKmxD/JMtWUUWl1BtghGw== - dependencies: - busboy "^1.6.0" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -unpipe@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -utf-8-validate@^5.0.2: - version "5.0.10" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" - integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== - dependencies: - node-gyp-build "^4.3.0" - -utf8@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -util@^0.12.5: - version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -uuid@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" - integrity sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg== - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -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== - -vendoza@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vendoza/-/vendoza-0.0.4.tgz#636b7eed3240765482fbbf1b7c8c815386592220" - integrity sha512-rz+A0pRbAHhf7+1DsDcZjtrXO+71xgW9E5A9S6ixSW5kL+0B2/pCkhuxI/NcdKnJVQQ8opL6VfFdeqcOHb2x+A== - dependencies: - chalk "4.1.2" - diff "^5.0.0" - node-fetch "2" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -web3-core-helpers@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.9.0.tgz#a1ca4ac7b9cec822886643312d2e98b0e4d8f1bc" - integrity sha512-NeJzylAp9Yj9xAt2uTT+kyug3X0DLnfBdnAcGZuY6HhoNPDIfQRA9CkJjLngVRlGTLZGjNp9x9eR+RyZQgUlXg== - dependencies: - web3-eth-iban "1.9.0" - web3-utils "1.9.0" - -web3-core-method@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.9.0.tgz#81da8aa21503b470537c9f075f30adfad194a2d8" - integrity sha512-sswbNsY2xRBBhGeaLt9c/eDc+0yDDhi6keUBAkgIRa9ueSx/VKzUY9HMqiV6bXDcGT2fJyejq74FfEB4lc/+/w== - dependencies: - "@ethersproject/transactions" "^5.6.2" - web3-core-helpers "1.9.0" - web3-core-promievent "1.9.0" - web3-core-subscriptions "1.9.0" - web3-utils "1.9.0" - -web3-core-promievent@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.9.0.tgz#2598a4d91b4edd3607366529f52bc96dee9f6d83" - integrity sha512-PHG1Mn23IGwMZhnPDN8dETKypqsFbHfiyRqP+XsVMPmTHkVfzDQTCBU/c2r6hUktBDoGKut5xZQpGfhFk71KbQ== - dependencies: - eventemitter3 "4.0.4" - -web3-core-requestmanager@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.9.0.tgz#9d7d0e7f890cf7a24e9c568b9772c64d57fc4fcd" - integrity sha512-hcJ5PCtTIJpj+8qWxoseqlCovDo94JJjTX7dZOLXgwp8ah7E3WRYozhGyZocerx+KebKyg1mCQIhkDpMwjfo9Q== - dependencies: - util "^0.12.5" - web3-core-helpers "1.9.0" - web3-providers-http "1.9.0" - web3-providers-ipc "1.9.0" - web3-providers-ws "1.9.0" - -web3-core-subscriptions@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.9.0.tgz#dc67b478875dab1875844df3307a986dd7d468dd" - integrity sha512-MaIo29yz7hTV8X8bioclPDbHFOVuHmnbMv+D3PDH12ceJFJAXGyW8GL5KU1DYyWIj4TD1HM4WknyVA/YWBiiLA== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.9.0" - -web3-core@^1.8.1: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.9.0.tgz#9cfafb2f8c01931429108af75205610406a5a1ab" - integrity sha512-DZ+TPmq/ZLlx4LSVzFgrHCP/QFpKDbGWO4HoquZSdu24cjk5SZ+FEU1SZB2OaK3/bgBh+25mRbmv8y56ysUu1w== - dependencies: - "@types/bn.js" "^5.1.1" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.9.0" - web3-core-method "1.9.0" - web3-core-requestmanager "1.9.0" - web3-utils "1.9.0" - -web3-eth-iban@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.9.0.tgz#a8f838e42c20d49ff58aaa9f67ece47a968e40b1" - integrity sha512-jPAm77PuEs1kE/UrrBFJdPD2PN42pwfXA0gFuuw35bZezhskYML9W4QCxcqnUtceyEA4FUn7K2qTMuCk+23fog== - dependencies: - bn.js "^5.2.1" - web3-utils "1.9.0" - -web3-providers-http@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.9.0.tgz#93cd3eb42fff974c9f7634ede1a9795d6435c3fe" - integrity sha512-5+dMNDAE0rRFz6SJpfnBqlVi2J5bB/Ivr2SanMt2YUrkxW5t8betZbzVwRkTbwtUvkqgj3xeUQzqpOttiv+IqQ== - dependencies: - abortcontroller-polyfill "^1.7.3" - cross-fetch "^3.1.4" - es6-promise "^4.2.8" - web3-core-helpers "1.9.0" - -web3-providers-ipc@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.9.0.tgz#db486cb0dde9062ac6055478861e3d37535924d2" - integrity sha512-cPXU93Du40HCylvjaa5x62DbnGqH+86HpK/+kMcFIzF6sDUBhKpag2tSbYhGbj7GMpfkmDTUiiMLdWnFV6+uBA== - dependencies: - oboe "2.1.5" - web3-core-helpers "1.9.0" - -web3-providers-ws@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.9.0.tgz#568330766e8abbb6eb43e1153a72fb24398fcb7e" - integrity sha512-JRVsnQZ7j2k1a2yzBNHe39xqk1ijOv01dfIBFw52VeEkSRzvrOcsPIM/ttSyBuJqt70ntMxXY0ekCrqfleKH/w== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.9.0" - websocket "^1.0.32" - -web3-utils@1.9.0, web3-utils@^1.8.1: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.9.0.tgz#7c5775a47586cefb4ad488831be8f6627be9283d" - integrity sha512-p++69rCNNfu2jM9n5+VD/g26l+qkEOQ1m6cfRQCbH8ZRrtquTmrirJMgTmyOoax5a5XRYOuws14aypCOs51pdQ== - dependencies: - bn.js "^5.2.1" - ethereum-bloom-filters "^1.0.6" - ethereumjs-util "^7.1.0" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "3.0.0" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -websocket@^1.0.32: - version "1.0.34" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" - integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.50" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-typed-array@^1.1.2: - version "1.1.9" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" - -which@2.0.2, which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -which@^1.1.1, which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== - -wordwrapjs@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" - integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== - dependencies: - reduce-flatten "^2.0.0" - typical "^5.2.0" - -workerpool@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" - integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - -ws@7.4.6: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== - -ws@^7.4.6: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== - -xml@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" - integrity sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw== - -xmlhttprequest@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@20.2.4: - version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" - integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== - -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-unparser@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - -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" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + +"@arbitrum/sdk@^3.1.2": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.7.0.tgz#2a6035a596469e43bdb3721298cdae9c0bccb9d7" + integrity sha512-7Omaqd8xfhCatxyyFZC3k7S9HE8pTVuk9tg+snqk8ojDVqO8kiD3YrYS9STJqbKxLBQ1TRktbRaUOAiH3+Y0zg== + dependencies: + "@ethersproject/address" "^5.0.8" + "@ethersproject/bignumber" "^5.1.1" + "@ethersproject/bytes" "^5.0.8" + async-mutex "^0.4.0" + ethers "^5.1.0" + +"@babel/code-frame@^7.0.0": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + dependencies: + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@compound-finance/hardhat-import@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@compound-finance/hardhat-import/-/hardhat-import-1.0.4.tgz#75c5a28ac2bdcf25455be9868ff812cb52287a20" + integrity sha512-CJl2BwVVKBMlVAHMm6G5MTqqI+mO5vdYoLiDbhvNOO3Ti+XLmR/vU06BxQxmJb0rijPsM77VuIiPkr15BOM0JQ== + dependencies: + "@ethersproject/address" "^5.5.0" + axios "^0.24.0" + hardhat "^2.0.4" + ts-node "^8.1.0" + typescript "~4.0.3" + +"@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" + +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" + integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== + +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.57.0": + version "8.57.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== + +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + +"@ethereumjs/util@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" + integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + ethereum-cryptography "^2.0.0" + micro-ftch "^0.3.1" + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.8", "@ethersproject/address@^5.5.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.1.1", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.0.8", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/experimental@^5.6.3": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/experimental/-/experimental-5.7.0.tgz#9759639434d37beaedfd8acab6f3af7db246b92d" + integrity sha512-DWvhuw7Dg8JPyhMbh/CNYOwsTLjXRx/HGkacIL5rBocG8jJC0kmixwoK/J3YblO4vtcyBLMa+sV74RJZK2iyHg== + dependencies: + "@ethersproject/web" "^5.7.0" + ethers "^5.7.0" + scrypt-js "3.0.1" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0", "@ethersproject/solidity@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.6.2", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@fastify/busboy@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" + integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== + +"@flashbots/ethers-provider-bundle@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@flashbots/ethers-provider-bundle/-/ethers-provider-bundle-0.5.0.tgz#068dd6a078066c50c36ac81b92d4726636768853" + integrity sha512-w7vc6aWDtgaHkDSgACjda0NoKYjOJ4mkr2av+u0NctvsoeNTg5dji65zeyU+98Fx3s6IbK0mfUTSGHAUtyt21A== + dependencies: + ts-node "^9.1.0" + typescript "^4.1.2" + +"@humanwhocodes/config-array@^0.11.14": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== + dependencies: + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@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" + +"@metamask/eth-sig-util@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" + integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^6.2.1" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/curves@1.4.2", "@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + +"@noble/hashes@^1.3.3", "@noble/hashes@^1.4.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" + integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA== + +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nomicfoundation/edr-darwin-arm64@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.5.2.tgz#72f7a826c9f0f2c91308edca562de3b9484ac079" + integrity sha512-Gm4wOPKhbDjGTIRyFA2QUAPfCXA1AHxYOKt3yLSGJkQkdy9a5WW+qtqKeEKHc/+4wpJSLtsGQfpzyIzggFfo/A== + +"@nomicfoundation/edr-darwin-x64@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.5.2.tgz#6d0fedb219d664631c6feddc596ab8c3bbc36fa8" + integrity sha512-ClyABq2dFCsrYEED3/UIO0c7p4H1/4vvlswFlqUyBpOkJccr75qIYvahOSJRM62WgUFRhbSS0OJXFRwc/PwmVg== + +"@nomicfoundation/edr-linux-arm64-gnu@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.5.2.tgz#60e4d52d963141bc2bb4a02639dc590a7fbdda2f" + integrity sha512-HWMTVk1iOabfvU2RvrKLDgtFjJZTC42CpHiw2h6rfpsgRqMahvIlx2jdjWYzFNy1jZKPTN1AStQ/91MRrg5KnA== + +"@nomicfoundation/edr-linux-arm64-musl@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.5.2.tgz#6676a09eab57c435a16ffc144658c896acca9baa" + integrity sha512-CwsQ10xFx/QAD5y3/g5alm9+jFVuhc7uYMhrZAu9UVF+KtVjeCvafj0PaVsZ8qyijjqVuVsJ8hD1x5ob7SMcGg== + +"@nomicfoundation/edr-linux-x64-gnu@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.5.2.tgz#f558d9697ce961410e7a7468f9ab8c8a601b9df6" + integrity sha512-CWVCEdhWJ3fmUpzWHCRnC0/VLBDbqtqTGTR6yyY1Ep3S3BOrHEAvt7h5gx85r2vLcztisu2vlDq51auie4IU1A== + +"@nomicfoundation/edr-linux-x64-musl@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.5.2.tgz#c9c9cbb2997499f75c1d022be724b0551d44569f" + integrity sha512-+aJDfwhkddy2pP5u1ISg3IZVAm0dO836tRlDTFWtvvSMQ5hRGqPcWwlsbobhDQsIxhPJyT7phL0orCg5W3WMeA== + +"@nomicfoundation/edr-win32-x64-msvc@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.5.2.tgz#f16db88bf4fe09a996af0a25096e09deecb72bfa" + integrity sha512-CcvvuA3sAv7liFNPsIR/68YlH6rrybKzYttLlMr80d4GKJjwJ5OKb3YgE6FdZZnOfP19HEHhsLcE0DPLtY3r0w== + +"@nomicfoundation/edr@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.5.2.tgz#e8c7b3d3dd4a312432ab3930dec60f76dc5c4926" + integrity sha512-hW/iLvUQZNTVjFyX/I40rtKvvDOqUEyIi96T28YaLfmPL+3LW2lxmYLUXEJ6MI14HzqxDqrLyhf6IbjAa2r3Dw== + dependencies: + "@nomicfoundation/edr-darwin-arm64" "0.5.2" + "@nomicfoundation/edr-darwin-x64" "0.5.2" + "@nomicfoundation/edr-linux-arm64-gnu" "0.5.2" + "@nomicfoundation/edr-linux-arm64-musl" "0.5.2" + "@nomicfoundation/edr-linux-x64-gnu" "0.5.2" + "@nomicfoundation/edr-linux-x64-musl" "0.5.2" + "@nomicfoundation/edr-win32-x64-msvc" "0.5.2" + +"@nomicfoundation/ethereumjs-common@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz#9901f513af2d4802da87c66d6f255b510bef5acb" + integrity sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg== + dependencies: + "@nomicfoundation/ethereumjs-util" "9.0.4" + +"@nomicfoundation/ethereumjs-rlp@5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz#66c95256fc3c909f6fb18f6a586475fc9762fa30" + integrity sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw== + +"@nomicfoundation/ethereumjs-tx@5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz#b0ceb58c98cc34367d40a30d255d6315b2f456da" + integrity sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.4" + "@nomicfoundation/ethereumjs-rlp" "5.0.4" + "@nomicfoundation/ethereumjs-util" "9.0.4" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-util@9.0.4": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz#84c5274e82018b154244c877b76bc049a4ed7b38" + integrity sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "5.0.4" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz#3a9c3b20d51360b20affb8f753e756d553d49557" + integrity sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw== + +"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz#74dcfabeb4ca373d95bd0d13692f44fcef133c28" + integrity sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw== + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz#4af5849a89e5a8f511acc04f28eb5d4460ba2b6a" + integrity sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA== + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz#54036808a9a327b2ff84446c130a6687ee702a8e" + integrity sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA== + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz#466cda0d6e43691986c944b909fc6dbb8cfc594e" + integrity sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g== + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz#2b35826987a6e94444140ac92310baa088ee7f94" + integrity sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg== + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz#e6363d13b8709ca66f330562337dbc01ce8bbbd9" + integrity sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA== + +"@nomicfoundation/solidity-analyzer@^0.1.0": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz#8bcea7d300157bf3a770a851d9f5c5e2db34ac55" + integrity sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA== + optionalDependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.2" + "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.2" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.2" + +"@nomiclabs/hardhat-ethers@^2.0.4": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" + integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== + +"@nomiclabs/hardhat-etherscan@3.1.7": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz#72e3d5bd5d0ceb695e097a7f6f5ff6fcbf062b9a" + integrity sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + cbor "^8.1.0" + chalk "^2.4.2" + debug "^4.1.1" + fs-extra "^7.0.1" + lodash "^4.17.11" + semver "^6.3.0" + table "^6.8.0" + undici "^5.14.0" + +"@safe-global/protocol-kit@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@safe-global/protocol-kit/-/protocol-kit-4.1.0.tgz#8ab41e179c559840f0cd6b6ae296438dabe1793f" + integrity sha512-WAGXEn6UvKGlEYNqcWUasLZ4240sVWBg8T2SsfHoTs8Im0x2i48CNNZ5Mw9x+oKqhWs/Q9frNG6JcycN19LDRw== + dependencies: + "@noble/hashes" "^1.3.3" + "@safe-global/safe-core-sdk-types" "^5.1.0" + "@safe-global/safe-deployments" "^1.37.3" + "@safe-global/safe-modules-deployments" "^2.2.1" + abitype "^1.0.2" + ethereumjs-util "^7.1.5" + ethers "^6.13.1" + semver "^7.6.2" + +"@safe-global/safe-core-sdk-types@^1.9.2": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk-types/-/safe-core-sdk-types-1.10.1.tgz#94331b982671d2f2b8cc23114c58baf63d460c81" + integrity sha512-BKvuYTLOlY16Rq6qCXglmnL6KxInDuXMFqZMaCzwDKiEh+uoHu3xCumG5tVtWOkCgBF4XEZXMqwZUiLcon7IsA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/contracts" "^5.7.0" + "@safe-global/safe-deployments" "^1.20.2" + web3-core "^1.8.1" + web3-utils "^1.8.1" + +"@safe-global/safe-core-sdk-types@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk-types/-/safe-core-sdk-types-5.1.0.tgz#af8d877b9af231242d023c7182f78ff4223bc3f4" + integrity sha512-UzXR4zWmVzux25FcIm4H049QhZZpVpIBL5HE+V0p5gHpArZROL+t24fZmsKUf403CtBxIJM5zZSVQL0nFJi+IQ== + dependencies: + abitype "^1.0.2" + +"@safe-global/safe-core-sdk-utils@^1.7.4": + version "1.7.4" + resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk-utils/-/safe-core-sdk-utils-1.7.4.tgz#810d36cf9629129a28eb1b9c6e690b163834b572" + integrity sha512-ITocwSWlFUA1K9VMP/eJiMfgbP/I9qDxAaFz7ukj5N5NZD3ihVQZkmqML6hjse5UhrfjCnfIEcLkNZhtB2XC2Q== + dependencies: + "@safe-global/safe-core-sdk-types" "^1.9.2" + semver "^7.3.8" + web3-utils "^1.8.1" + +"@safe-global/safe-core-sdk@^3.3.5": + version "3.3.5" + resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk/-/safe-core-sdk-3.3.5.tgz#30884639d368a9f50aa5fc96f78de87261ebdab3" + integrity sha512-ul+WmpxZOXgDIXrZ6MIHptThYbm0CVV3/rypMQEn4tZLkudh/yXK7EuWBFnx9prR3MePuku51Zcz9fu1vi7sfQ== + dependencies: + "@ethersproject/solidity" "^5.7.0" + "@safe-global/safe-core-sdk-types" "^1.9.2" + "@safe-global/safe-core-sdk-utils" "^1.7.4" + "@safe-global/safe-deployments" "^1.25.0" + ethereumjs-util "^7.1.5" + semver "^7.3.8" + web3-utils "^1.8.1" + zksync-web3 "^0.14.3" + +"@safe-global/safe-deployments@^1.20.2", "@safe-global/safe-deployments@^1.25.0", "@safe-global/safe-deployments@^1.37.3": + version "1.37.5" + resolved "https://registry.yarnpkg.com/@safe-global/safe-deployments/-/safe-deployments-1.37.5.tgz#aa9c929e5017898e5f5dd0825baa067c132f8cb1" + integrity sha512-/HdBFQlCQ08kDFDuUCgmb6vxJVsDYvM+Iyj6vfsPCsq9SEdELd5mfA8DQU56kpNVg0WHM3BSznc7yphW3mx9BQ== + dependencies: + semver "^7.6.2" + +"@safe-global/safe-ethers-lib@^1.9.2": + version "1.9.4" + resolved "https://registry.yarnpkg.com/@safe-global/safe-ethers-lib/-/safe-ethers-lib-1.9.4.tgz#049989a302c6f2010c574cf3a834b0cfb9cf67c5" + integrity sha512-WhzcmNun0s0VxeVQKRqaapV0vEpdm76zZBR2Du+S+58u1r57OjZkOSL2Gru0tdwkt3FIZZtE3OhDu09M70pVkA== + dependencies: + "@safe-global/safe-core-sdk-types" "^1.9.2" + "@safe-global/safe-core-sdk-utils" "^1.7.4" + ethers "5.7.2" + +"@safe-global/safe-modules-deployments@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@safe-global/safe-modules-deployments/-/safe-modules-deployments-2.2.1.tgz#a8b88f2afc6ec04fed09968fe1e4990ed975c86e" + integrity sha512-H0XpusyXVcsTuRsQSq0FoBKqRfhZH87/1DrFEmXXPXmI3fJkvxq3KpTaTTqzcqoIe/J+erwVZQUYNfL68EcvAQ== + +"@scure/base@~1.1.0", "@scure/base@~1.1.6": + version "1.1.8" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.8.tgz#8f23646c352f020c83bca750a82789e246d42b50" + integrity sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg== + +"@scure/bip32@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" + integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== + dependencies: + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" + "@scure/base" "~1.1.0" + +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@scure/bip39@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== + dependencies: + "@noble/hashes" "~1.2.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== + dependencies: + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@solidity-parser/parser@^0.14.0": + 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" + +"@solidity-parser/parser@^0.16.0": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.2.tgz#42cb1e3d88b3e8029b0c9befff00b634cd92d2fa" + integrity sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@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.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@typechain/ethers-v5@^8.0.2": + version "8.0.5" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-8.0.5.tgz#d469420e9a73deb7fa076cde9edb45d713dd1b8c" + integrity sha512-ntpj4cS3v4WlDu+hSKSyj9A3o1tKtWC30RX1gobeYymZColeJiUemC1Kgfa0MWGmInm5CKxoHVhEvYVgPOZn1A== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + +"@typechain/hardhat@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-3.1.0.tgz#88bd9e9d55e30fbece6fbb34c03ecd40a8b2013a" + integrity sha512-C6Be6l+vTpao19PvMH2CB/lhL1TRLkhdPkvQCF/zqkY1e+0iqY2Bb9Jd3PTt6I8QvMm89ZDerrCJC9927ZHmlg== + dependencies: + fs-extra "^9.1.0" + +"@types/bn.js@^4.11.3": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" + integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== + dependencies: + "@types/node" "*" + +"@types/chai-as-promised@^7.1.3", "@types/chai-as-promised@^7.1.4": + version "7.1.8" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz#f2b3d82d53c59626b5d6bbc087667ccb4b677fe9" + integrity sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw== + dependencies: + "@types/chai" "*" + +"@types/chai@*", "@types/chai@^4.2.22": + version "4.3.19" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.19.tgz#14519f437361d41e84102ed3fbc922ddace3e228" + integrity sha512-2hHHvQBVE2FiSK4eN0Br6snX9MtolHaTo/batnLjlGRhoQzlCL61iVpxoqO7SfFyOw+P/pwv+0zNHzKoGWz9Cw== + +"@types/concat-stream@^1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" + integrity sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA== + dependencies: + "@types/node" "*" + +"@types/form-data@0.0.33": + version "0.0.33" + resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" + integrity sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw== + dependencies: + "@types/node" "*" + +"@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/mocha@^9.0.0": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== + +"@types/node@*": + version "22.5.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.4.tgz#83f7d1f65bc2ed223bdbf57c7884f1d5a4fa84e8" + integrity sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg== + dependencies: + undici-types "~6.19.2" + +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== + +"@types/node@^10.0.3": + version "10.17.60" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" + integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== + +"@types/node@^12.12.6": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + +"@types/node@^16.11.7": + version "16.18.108" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.108.tgz#b794e2b2a85b4c12935ea7d0f18641be68b352f9" + integrity sha512-fj42LD82fSv6yN9C6Q4dzS+hujHj+pTv0IpRR3kI20fnYeS0ytBpjFO9OjmDowSPPt4lNKN46JLaKbCyP+BW2A== + +"@types/node@^8.0.0": + version "8.10.66" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" + integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== + +"@types/pbkdf2@^3.0.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc" + integrity sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew== + dependencies: + "@types/node" "*" + +"@types/prettier@^2.1.1": + version "2.7.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" + integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== + +"@types/qs@^6.2.31": + version "6.9.15" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" + integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== + +"@types/secp256k1@^4.0.1": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.6.tgz#d60ba2349a51c2cbc5e816dcd831a42029d376bf" + integrity sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ== + dependencies: + "@types/node" "*" + +"@types/semver@^7.3.12": + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + +"@typescript-eslint/eslint-plugin@^5.18.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.18.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== + dependencies: + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== + dependencies: + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== + +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== + dependencies: + "@typescript-eslint/types" "5.62.0" + eslint-visitor-keys "^3.3.0" + +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== + +abitype@^1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.6.tgz#76410903e1d88e34f1362746e2d407513c38565b" + integrity sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A== + +abortcontroller-polyfill@^1.7.5: + version "1.7.5" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" + integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.4, ajv@^6.12.6: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== + +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +antlr4@^4.11.0: + version "4.13.2" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.2.tgz#0d084ad0e32620482a9c3a0e2470c02e72e4006d" + integrity sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg== + +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== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +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@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1, array-back@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-uniq@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== + +asap@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +ast-parents@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" + integrity sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-mutex@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.4.1.tgz#bccf55b96f2baf8df90ed798cb5544a1f6ee4c2c" + integrity sha512-WfoBo4E/TbCX1G95XTjbWTE3X2XLG0m1Xbv2cwOtuPdyH9CZvnaA5nCt1ucjaKEgW2A5IF71hxrRhr83Je5xjA== + dependencies: + tslib "^2.4.0" + +async@1.x: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +axios@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== + dependencies: + follow-redirects "^1.14.4" + +axios@^1.5.1: + version "1.7.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" + integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2: + version "3.0.10" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" + integrity sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ== + dependencies: + safe-buffer "^5.0.1" + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bignumber.js@^9.0.0: + version "9.1.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" + integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== + +bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +bufferutil@^4.0.1: + version "4.0.8" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.8.tgz#1de6a71092d65d7766c4d8a522b261a6e787e8ea" + integrity sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw== + dependencies: + node-gyp-build "^4.3.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.2, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^6.0.0, camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caseless@^0.12.0, caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +cbor@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" + integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== + dependencies: + nofilter "^3.1.0" + +chai-as-promised@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.2.tgz#70cd73b74afd519754161386421fb71832c6d041" + integrity sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw== + dependencies: + check-error "^1.0.2" + +chai@^4.3.4: + version "4.5.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" + integrity sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" + pathval "^1.1.1" + type-detect "^4.1.0" + +chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.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== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^5.0.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + +charenc@0.0.2, "charenc@>= 0.0.1": + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== + +check-error@^1.0.2, check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== + dependencies: + get-func-name "^2.0.2" + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + +cli-table3@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + +cli-table3@^0.6.0: + version "0.6.5" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colors@1.4.0, colors@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +combined-stream@^1.0.6, combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== + dependencies: + array-back "^4.0.2" + chalk "^2.4.2" + table-layout "^1.0.2" + typical "^5.2.0" + +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +commander@^8.1.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@^1.6.0, concat-stream@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cosmiconfig@^8.0.0: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +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-fetch@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" + integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== + dependencies: + node-fetch "^2.6.12" + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypt@0.0.2, "crypt@>= 0.0.1": + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== + +d@1, d@^1.0.1, d@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" + integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== + dependencies: + es5-ext "^0.10.64" + type "^2.7.2" + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +debug@4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +debug@^2.2.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^4.0.1, deep-eql@^4.1.3: + version "4.1.4" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.4.tgz#d0d3912865911bb8fac5afb4e3acfa6a28dc72b7" + integrity sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg== + dependencies: + type-detect "^4.0.0" + +deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deep-object-diff@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.9.tgz#6df7ef035ad6a0caa44479c536ed7b02570f4595" + integrity sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA== + +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +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== + +diff@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +elliptic@^6.5.2, elliptic@^6.5.4: + version "6.5.7" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" + integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +enquirer@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== + dependencies: + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es5-ext@^0.10.35, es5-ext@^0.10.62, es5-ext@^0.10.63, es5-ext@^0.10.64, es5-ext@~0.10.14: + version "0.10.64" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" + integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + esniff "^2.0.1" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-promise@^4.2.8: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.4" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" + integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== + dependencies: + d "^1.0.2" + ext "^1.7.0" + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escodegen@1.8.x: + version "1.8.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + integrity sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A== + dependencies: + esprima "^2.7.1" + estraverse "^1.9.1" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.2.0" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.12.0: + version "8.57.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.0" + "@humanwhocodes/config-array" "^0.11.14" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esprima@2.7.x, esprima@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + integrity sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA== + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +eth-gas-reporter@^0.2.25: + version "0.2.27" + resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz#928de8548a674ed64c7ba0bf5795e63079150d4e" + integrity sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw== + dependencies: + "@solidity-parser/parser" "^0.14.0" + axios "^1.5.1" + cli-table3 "^0.5.0" + colors "1.4.0" + ethereum-cryptography "^1.0.3" + ethers "^5.7.2" + fs-readdir-recursive "^1.1.0" + lodash "^4.17.14" + markdown-table "^1.1.3" + mocha "^10.2.0" + req-cwd "^2.0.0" + sha1 "^1.1.1" + sync-request "^6.0.0" + +ethereum-bloom-filters@^1.0.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.2.0.tgz#8294f074c1a6cbd32c39d2cc77ce86ff14797dab" + integrity sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA== + dependencies: + "@noble/hashes" "^1.4.0" + +ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-cryptography@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" + integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== + dependencies: + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/bip32" "1.1.5" + "@scure/bip39" "1.1.1" + +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" + integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== + dependencies: + "@noble/curves" "1.4.2" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" + +ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethereumjs-util@^7.1.5: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethers@5.7.2, ethers@^5.1.0, ethers@^5.7.0, ethers@^5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +ethers@^6.13.1: + version "6.13.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.2.tgz#4b67d4b49e69b59893931a032560999e5e4419fe" + integrity sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.17.1" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +ethjs-util@0.1.6, ethjs-util@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + +eventemitter3@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + +evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +ext@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.2.7, fast-glob@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-uri@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" + integrity sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw== + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + +find-up@5.0.0, find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + +follow-redirects@^1.12.1, follow-redirects@^1.14.4, follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +form-data@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fs-extra@^7.0.0, fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-readdir-recursive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-port@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" + integrity sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA== + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3, glob@^7.1.6: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: + 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== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +handlebars@^4.0.1: + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.2" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + +"hardhat-chai-matchers@https://github.com/jflatow/hardhat/releases/download/viaIR/nomicfoundation-hardhat-chai-matchers-v1.0.4.tgz": + version "1.0.4" + resolved "https://github.com/jflatow/hardhat/releases/download/viaIR/nomicfoundation-hardhat-chai-matchers-v1.0.4.tgz#785d92b3ad4a66a888153ac0dcc55b319d5c9b65" + dependencies: + "@ethersproject/abi" "^5.1.2" + "@types/chai-as-promised" "^7.1.3" + chai-as-promised "^7.1.1" + chalk "^2.4.2" + deep-eql "^4.0.1" + ordinal "^1.0.3" + +hardhat-change-network@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/hardhat-change-network/-/hardhat-change-network-0.0.7.tgz#9f9b7943ff966515658b70bf5e44bc2f073af402" + integrity sha512-Usp9fJan9SOJnOlVcv/jMJDchseE7bIDA5ZsBnracgVk4MiBwkvMqpmLWn5G1aDBvnUCthvS2gO3odfahgkV0Q== + +hardhat-contract-sizer@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/hardhat-contract-sizer/-/hardhat-contract-sizer-2.10.0.tgz#72646f43bfe50e9a5702c9720c9bc3e77d93a2c9" + integrity sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA== + dependencies: + chalk "^4.0.0" + cli-table3 "^0.6.0" + strip-ansi "^6.0.0" + +hardhat-cover@compound-finance/hardhat-cover: + version "1.0.0" + resolved "https://codeload.github.com/compound-finance/hardhat-cover/tar.gz/c9064e8bf04d3ae34773adbfee70cade741078ec" + +hardhat-gas-reporter@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz#ebe5bda5334b5def312747580cd923c2b09aef1b" + integrity sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA== + dependencies: + array-uniq "1.0.3" + eth-gas-reporter "^0.2.25" + sha1 "^1.1.1" + +hardhat@^2.0.4, hardhat@^2.12.2: + version "2.22.10" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.10.tgz#826ab56e47af98406e6dd105ba6d2dbb148013d9" + integrity sha512-JRUDdiystjniAvBGFmJRsiIZSOP2/6s++8xRDe3TzLeQXlWWHsXBrd9wd3JWFyKXvgMqMeLL5Sz/oNxXKYw9vg== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/edr" "^0.5.2" + "@nomicfoundation/ethereumjs-common" "4.0.4" + "@nomicfoundation/ethereumjs-tx" "5.0.4" + "@nomicfoundation/ethereumjs-util" "9.0.4" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + boxen "^5.1.2" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.8.26" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +http-basic@^8.1.1: + version "8.1.3" + resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" + integrity sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw== + dependencies: + caseless "^0.12.0" + concat-stream "^1.6.2" + http-response-object "^3.0.1" + parse-cache-control "^1.0.1" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-https@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg== + +http-response-object@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" + integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== + dependencies: + "@types/node" "^10.0.3" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^5.2.0, ignore@^5.2.4: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +immutable@^4.0.0-rc.12: + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + +import-fresh@^3.2.1, import-fresh@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-buffer@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-callable@^1.1.3: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-typed-array@^1.1.3: + version "1.1.13" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== + dependencies: + which-typed-array "^1.1.14" + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +jest-diff@^27.4.2: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== + +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@3.x: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@4.1.0, js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +keccak@^3.0.0, keccak@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" + integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +loupe@^2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== + dependencies: + get-func-name "^2.0.1" + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + +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== + +markdown-table@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" + integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +md5@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" + integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== + dependencies: + charenc "0.0.2" + crypt "0.0.2" + is-buffer "~1.1.6" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micro-ftch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" + integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== + +micromatch@^4.0.4: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" + integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.5, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mkdirp@0.5.x: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mkdirp@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" + integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha-junit-reporter@^2.0.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz#739f5595d0f051d07af9d74e32c416e13a41cde5" + integrity sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw== + dependencies: + debug "^4.3.4" + md5 "^2.3.0" + mkdirp "^3.0.0" + strip-ansi "^6.0.1" + xml "^1.0.1" + +mocha-multi-reporters@hayesgm/mocha-multi-reporters#hayesgm/reporter-options-to-option: + version "1.5.1" + resolved "https://codeload.github.com/hayesgm/mocha-multi-reporters/tar.gz/0df9421cd7211e83f097846d16de6706988ad445" + dependencies: + debug "^4.1.1" + lodash "^4.17.15" + +mocha@^10.0.0, mocha@^10.2.0, mocha@^9.1.3: + version "9.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" + integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.3" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "4.2.1" + ms "2.1.3" + nanoid "3.3.1" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + workerpool "6.2.0" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== + +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +nock@^13.2.2: + version "13.5.5" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.5.tgz#cd1caaca281d42be17d51946367a3d53a6af3e78" + integrity sha512-XKYnqUrCwXC8DGG1xX4YH5yNIrlh9c065uaMZZHUoeUUINTOyt+x/G+ezYk0Ft6ExSREVIs+qBJDK503viTfFA== + dependencies: + debug "^4.1.0" + json-stringify-safe "^5.0.1" + propagate "^2.0.0" + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-fetch@2, node-fetch@^2.6.12: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.8.2" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa" + integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw== + +nofilter@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" + integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== + +nopt@3.x: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== + dependencies: + abbrev "1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + +obliterator@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" + integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== + +oboe@2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" + integrity sha512-zRFWiF+FoicxEs3jNI/WYUrVEgA7DeET/InK0XQuudGHRg8iIob3cNPrJTKaz4004uaA9Pbe+Dwa8iluhjLZWA== + dependencies: + http-https "^1.0.0" + +once@1.x, once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +ordinal@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ordinal/-/ordinal-1.0.3.tgz#1a3c7726a61728112f50944ad7c35c06ae3a0d4d" + integrity sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ== + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-cache-control@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" + integrity sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg== + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.17: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +picocolors@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59" + integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + +prettier@^2.1.2, prettier@^2.8.3: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + +pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +promise@^8.0.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" + integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== + dependencies: + asap "~2.0.6" + +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +qs@^6.4.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +raw-body@^2.4.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +readable-stream@^2.2.2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.6.0: + 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" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + +req-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" + integrity sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ== + dependencies: + req-from "^2.0.0" + +req-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/req-from/-/req-from-2.0.0.tgz#d74188e47f93796f4aa71df6ee35ae689f3e0e70" + integrity sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA== + dependencies: + resolve-from "^3.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@1.1.x: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg== + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.2.3, rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sc-istanbul@^0.4.5: + version "0.4.6" + resolved "https://registry.yarnpkg.com/sc-istanbul/-/sc-istanbul-0.4.6.tgz#cf6784355ff2076f92d70d59047d71c13703e839" + integrity sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g== + dependencies: + abbrev "1.0.x" + async "1.x" + escodegen "1.8.x" + esprima "2.7.x" + glob "^5.0.15" + handlebars "^4.0.1" + js-yaml "3.x" + mkdirp "0.5.x" + nopt "3.x" + once "1.x" + resolve "1.1.x" + supports-color "^3.1.0" + which "^1.1.1" + wordwrap "^1.0.0" + +scrypt-js@3.0.1, scrypt-js@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +semver@^5.5.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.3.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.7, semver@^7.3.8, semver@^7.5.2, semver@^7.6.2: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sha1@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848" + integrity sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA== + dependencies: + charenc ">= 0.0.1" + crypt ">= 0.0.1" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +solc@0.8.26: + version "0.8.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" + integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== + dependencies: + command-exists "^1.2.8" + commander "^8.1.0" + follow-redirects "^1.12.1" + js-sha3 "0.8.0" + memorystream "^0.3.1" + semver "^5.5.0" + tmp "0.0.33" + +solhint@^3.3.6: + version "3.6.2" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.6.2.tgz#2b2acbec8fdc37b2c68206a71ba89c7f519943fe" + integrity sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ== + dependencies: + "@solidity-parser/parser" "^0.16.0" + ajv "^6.12.6" + antlr4 "^4.11.0" + ast-parents "^0.0.1" + chalk "^4.1.2" + commander "^10.0.0" + cosmiconfig "^8.0.0" + fast-diff "^1.2.0" + glob "^8.0.3" + ignore "^5.2.4" + js-yaml "^4.1.0" + lodash "^4.17.21" + pluralize "^8.0.0" + semver "^7.5.2" + strip-ansi "^6.0.1" + table "^6.8.1" + text-table "^0.2.0" + optionalDependencies: + prettier "^2.8.3" + +source-map-support@^0.5.13, source-map-support@^0.5.17: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + integrity sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA== + dependencies: + amdefine ">=0.0.4" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + +string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^3.1.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A== + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +sync-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.1.0.tgz#e96217565b5e50bbffe179868ba75532fb597e68" + integrity sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw== + dependencies: + http-response-object "^3.0.1" + sync-rpc "^1.2.1" + then-request "^6.0.0" + +sync-rpc@^1.2.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.6.tgz#b2e8b2550a12ccbc71df8644810529deb68665a7" + integrity sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw== + dependencies: + get-port "^3.1.0" + +table-layout@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + +table@^6.8.0, table@^6.8.1: + version "6.8.2" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58" + integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +then-request@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.2.tgz#ec18dd8b5ca43aaee5cb92f7e4c1630e950d4f0c" + integrity sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA== + dependencies: + "@types/concat-stream" "^1.6.0" + "@types/form-data" "0.0.33" + "@types/node" "^8.0.0" + "@types/qs" "^6.2.31" + caseless "~0.12.0" + concat-stream "^1.6.0" + form-data "^2.2.0" + http-basic "^8.1.1" + http-response-object "^3.0.1" + promise "^8.0.0" + qs "^6.4.0" + +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +ts-command-line-args@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" + integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + +ts-node@^10.4.0: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + 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" + +ts-node@^8.1.0: + version "8.10.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" + integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA== + dependencies: + arg "^4.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + +ts-node@^9.1.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" + integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== + dependencies: + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +tslib@^1.8.1, tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + +type-detect@^4.0.0, type-detect@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" + integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" + integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== + +typechain@^6.0.2: + version "6.1.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-6.1.0.tgz#462a35f555accf870689d1ba5698749108d0ce81" + integrity sha512-GGfkK0p3fUgz8kYxjSS4nKcWXE0Lo+teHTetghousIK5njbNoYNDlwn91QIyD181L3fVqlTvBE0a/q3AZmjNfw== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.1.1" + fs-extra "^7.0.0" + glob "^7.1.6" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.1.2" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + +typescript@^4.1.2, typescript@^4.4.4: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +typescript@~4.0.3: + version "4.0.8" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.8.tgz#5739105541db80a971fdbd0d56511d1a6f17d37f" + integrity sha512-oz1765PN+imfz1MlZzSZPtC/tqcwsCyIYA8L47EkRnRW97ztRk83SzMiWLrnChC0vqoYxSU1fcFUDA5gV/ZiPg== + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + +uglify-js@^3.1.4: + version "3.19.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" + integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +undici@^5.14.0, undici@^5.21.2: + version "5.28.4" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" + integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g== + dependencies: + "@fastify/busboy" "^2.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +unpipe@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +utf-8-validate@^5.0.2: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + +utf8@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util@^0.12.5: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +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== + +vendoza@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/vendoza/-/vendoza-0.0.4.tgz#636b7eed3240765482fbbf1b7c8c815386592220" + integrity sha512-rz+A0pRbAHhf7+1DsDcZjtrXO+71xgW9E5A9S6ixSW5kL+0B2/pCkhuxI/NcdKnJVQQ8opL6VfFdeqcOHb2x+A== + dependencies: + chalk "4.1.2" + diff "^5.0.0" + node-fetch "2" + +web3-core-helpers@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.10.4.tgz#bd2b4140df2016d5dd3bb2b925fc29ad8678677c" + integrity sha512-r+L5ylA17JlD1vwS8rjhWr0qg7zVoVMDvWhajWA5r5+USdh91jRUYosp19Kd1m2vE034v7Dfqe1xYRoH2zvG0g== + dependencies: + web3-eth-iban "1.10.4" + web3-utils "1.10.4" + +web3-core-method@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.10.4.tgz#566b52f006d3cbb13b21b72b8d2108999bf5d6bf" + integrity sha512-uZTb7flr+Xl6LaDsyTeE2L1TylokCJwTDrIVfIfnrGmnwLc6bmTWCCrm71sSrQ0hqs6vp/MKbQYIYqUN0J8WyA== + dependencies: + "@ethersproject/transactions" "^5.6.2" + web3-core-helpers "1.10.4" + web3-core-promievent "1.10.4" + web3-core-subscriptions "1.10.4" + web3-utils "1.10.4" + +web3-core-promievent@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.10.4.tgz#629b970b7934430b03c5033c79f3bb3893027e22" + integrity sha512-2de5WnJQ72YcIhYwV/jHLc4/cWJnznuoGTJGD29ncFQHAfwW/MItHFSVKPPA5v8AhJe+r6y4Y12EKvZKjQVBvQ== + dependencies: + eventemitter3 "4.0.4" + +web3-core-requestmanager@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.10.4.tgz#eb1f147e6b9df84e3a37e602162f8925bdb4bb9a" + integrity sha512-vqP6pKH8RrhT/2MoaU+DY/OsYK9h7HmEBNCdoMj+4ZwujQtw/Mq2JifjwsJ7gits7Q+HWJwx8q6WmQoVZAWugg== + dependencies: + util "^0.12.5" + web3-core-helpers "1.10.4" + web3-providers-http "1.10.4" + web3-providers-ipc "1.10.4" + web3-providers-ws "1.10.4" + +web3-core-subscriptions@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.10.4.tgz#2f4dcb404237e92802a563265d11a33934dc38e6" + integrity sha512-o0lSQo/N/f7/L76C0HV63+S54loXiE9fUPfHFcTtpJRQNDBVsSDdWRdePbWwR206XlsBqD5VHApck1//jEafTw== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.10.4" + +web3-core@^1.8.1: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.10.4.tgz#639de68b8b9871d2dc8892e0dd4e380cb1361a98" + integrity sha512-B6elffYm81MYZDTrat7aEhnhdtVE3lDBUZft16Z8awYMZYJDbnykEbJVS+l3mnA7AQTnSDr/1MjWofGDLBJPww== + dependencies: + "@types/bn.js" "^5.1.1" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.10.4" + web3-core-method "1.10.4" + web3-core-requestmanager "1.10.4" + web3-utils "1.10.4" + +web3-eth-iban@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.10.4.tgz#bc61b4a1930d19b1df8762c606d669902558e54d" + integrity sha512-0gE5iNmOkmtBmbKH2aTodeompnNE8jEyvwFJ6s/AF6jkw9ky9Op9cqfzS56AYAbrqEFuClsqB/AoRves7LDELw== + dependencies: + bn.js "^5.2.1" + web3-utils "1.10.4" + +web3-providers-http@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.10.4.tgz#ca7aa58aeaf8123500c24ffe0595896319f830e8" + integrity sha512-m2P5Idc8hdiO0l60O6DSCPw0kw64Zgi0pMjbEFRmxKIck2Py57RQMu4bxvkxJwkF06SlGaEQF8rFZBmuX7aagQ== + dependencies: + abortcontroller-polyfill "^1.7.5" + cross-fetch "^4.0.0" + es6-promise "^4.2.8" + web3-core-helpers "1.10.4" + +web3-providers-ipc@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.10.4.tgz#2e03437909e4e7771d646ff05518efae44b783c3" + integrity sha512-YRF/bpQk9z3WwjT+A6FI/GmWRCASgd+gC0si7f9zbBWLXjwzYAKG73bQBaFRAHex1hl4CVcM5WUMaQXf3Opeuw== + dependencies: + oboe "2.1.5" + web3-core-helpers "1.10.4" + +web3-providers-ws@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.10.4.tgz#55d0c3ba36c6a79d105f02e20a707eb3978e7f82" + integrity sha512-j3FBMifyuFFmUIPVQR4pj+t5ILhAexAui0opgcpu9R5LxQrLRUZxHSnU+YO25UycSOa/NAX8A+qkqZNpcFAlxA== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.10.4" + websocket "^1.0.32" + +web3-utils@1.10.4, web3-utils@^1.8.1: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.4.tgz#0daee7d6841641655d8b3726baf33b08eda1cbec" + integrity sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A== + dependencies: + "@ethereumjs/util" "^8.1.0" + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereum-cryptography "^2.1.2" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +websocket@^1.0.32: + version "1.0.35" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.35.tgz#374197207d7d4cc4c36cbf8a1bb886ee52a07885" + integrity sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.63" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-typed-array@^1.1.14, which-typed-array@^1.1.2: + version "1.1.15" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + +which@2.0.2, which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +which@^1.1.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + +word-wrap@^1.2.5, word-wrap@~1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== + +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + +workerpool@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" + integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +ws@^7.4.6: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + +xml@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" + integrity sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +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" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zksync-web3@^0.14.3: + version "0.14.4" + resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.4.tgz#0b70a7e1a9d45cc57c0971736079185746d46b1f" + integrity sha512-kYehMD/S6Uhe1g434UnaMN+sBr9nQm23Ywn0EUP5BfQCsbjcr3ORuS68PosZw8xUTu3pac7G6YMSnNHk+fwzvg== From 10e927546831da0dd8e384e2ad429eb9194e9b4b Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 8 Oct 2024 11:01:10 -0400 Subject: [PATCH 09/28] Address audit feedback and tests related to ownable update --- contracts/CometProxyAdmin.sol | 4 +- .../marketupdates/MarketUpdateProposer.sol | 75 ++++++++++++------- .../marketupdates/MarketUpdateTimelock.sol | 39 +++++++++- test/configurator-test.ts | 3 +- test/helpers.ts | 3 +- test/marketupdates/existing-flow-test.ts | 2 +- .../market-update-comet-proxy-admin-test.ts | 10 +-- .../market-update-deployment-test.ts | 10 +-- .../market-update-permission-checker-test.ts | 8 +- .../market-update-proposer-test.ts | 11 ++- test/marketupdates/market-updates-helper.ts | 5 +- 11 files changed, 113 insertions(+), 57 deletions(-) diff --git a/contracts/CometProxyAdmin.sol b/contracts/CometProxyAdmin.sol index 09ddbaf2..f3bc7742 100644 --- a/contracts/CometProxyAdmin.sol +++ b/contracts/CometProxyAdmin.sol @@ -66,14 +66,14 @@ contract CometProxyAdmin is ProxyAdmin { /** * @dev Custom upgrade function that allows owner and marketAdmin to call it */ - function _upgrade(TransparentUpgradeableProxy proxy, address implementation) private ownerOrMarketAdmin { + function _upgrade(TransparentUpgradeableProxy proxy, address implementation) private { proxy.upgradeTo(implementation); } /** * @dev Custom upgradeAndCall function that allows owner and marketAdmin to call it */ - function _upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) private ownerOrMarketAdmin { + function _upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) private { proxy.upgradeToAndCall(implementation, data); } } diff --git a/contracts/marketupdates/MarketUpdateProposer.sol b/contracts/marketupdates/MarketUpdateProposer.sol index 9b9e58dd..d879ff39 100644 --- a/contracts/marketupdates/MarketUpdateProposer.sol +++ b/contracts/marketupdates/MarketUpdateProposer.sol @@ -41,8 +41,6 @@ contract MarketUpdateProposer { /// @notice The ordered list of calldata to be passed to each call bytes[] calldatas; - string description; - /// @notice Flag marking whether the proposal has been canceled bool canceled; @@ -68,7 +66,10 @@ contract MarketUpdateProposer { uint public proposalCount; /// @notice The initial proposal ID, set when the contract is deployed - uint public initialProposalId; + uint public constant INITIAL_PROPOSAL_ID = 0; + + /// @notice The maximum number of actions that can be included in a proposal + uint public constant PROPOSAL_MAX_OPERATIONS = 20; // 20 actions /// @notice An event emitted when a new proposal is created event MarketUpdateProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, string description); @@ -82,7 +83,7 @@ contract MarketUpdateProposer { error InvalidAddress(); constructor(address governor_, address marketAdmin_, address proposalGuardian_, ITimelock timelock_) public { - if (address(governor_) == address(0) || address(marketAdmin_) == address(0) || address(timelock_) == address(0)) revert InvalidAddress(); + if (governor_ == address(0) || marketAdmin_ == address(0) || address(timelock_) == address(0)) revert InvalidAddress(); governor = governor_; marketAdmin = marketAdmin_; proposalGuardian = proposalGuardian_; @@ -136,17 +137,30 @@ contract MarketUpdateProposer { emit SetMarketAdmin(oldMarketAdmin, newMarketAdmin); } + /** + * @notice Function used to propose a new proposal for market updates + * @dev Can only be called by the market admin. Reverts with Unauthorized if the caller is not the market admin + * The function requires the provided arrays to have the same length and at least one action + * Emits a MarketUpdateProposalCreated event with the proposal details + * @param targets Target addresses for proposal calls + * @param values Eth values for proposal calls + * @param signatures Function signatures for proposal calls + * @param calldatas Calldatas for proposal calls + * @param description String description of the proposal + * @return Proposal id of new proposal + */ function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) public returns (uint) { if (msg.sender != marketAdmin) revert Unauthorized(); require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, "MarketUpdateProposer::propose: proposal function information arity mismatch"); require(targets.length != 0, "MarketUpdateProposer::propose: must provide actions"); - + require(targets.length <= PROPOSAL_MAX_OPERATIONS, "MarketUpdateProposer::propose: too many actions"); + proposalCount++; uint newProposalID = proposalCount; MarketUpdateProposal storage newProposal = proposals[newProposalID]; require(newProposal.id == 0, "MarketUpdateProposer::propose: ProposalID collision"); - uint eta = add256(block.timestamp, timelock.delay()); + uint eta = block.timestamp + timelock.delay(); newProposal.id = newProposalID; newProposal.proposer = msg.sender; newProposal.eta = eta; @@ -154,12 +168,9 @@ contract MarketUpdateProposer { newProposal.values = values; newProposal.signatures = signatures; newProposal.calldatas = calldatas; - newProposal.description = description; newProposal.canceled = false; newProposal.executed = false; - proposals[newProposal.id] = newProposal; - emit MarketUpdateProposalCreated(newProposal.id, msg.sender, targets, values, signatures, calldatas, description); for (uint i = 0; i < newProposal.targets.length; i++) { @@ -167,7 +178,6 @@ contract MarketUpdateProposer { } return newProposal.id; - } function queueOrRevertInternal(address target, uint value, string memory signature, bytes memory data, uint eta) internal { @@ -208,38 +218,50 @@ contract MarketUpdateProposer { emit MarketUpdateProposalCancelled(proposalId); } + /** + * @notice Gets the state of a proposal + * @param proposalId The id of the proposal + * @return Proposal state + */ function state(uint proposalId) public view returns (ProposalState) { - require(proposalCount >= proposalId && proposalId > initialProposalId, "MarketUpdateProposer::state: invalid proposal id"); + require(proposalCount >= proposalId && proposalId > INITIAL_PROPOSAL_ID, "MarketUpdateProposer::state: invalid proposal id"); MarketUpdateProposal storage proposal = proposals[proposalId]; if (proposal.canceled) { return ProposalState.Canceled; } else if (proposal.executed) { return ProposalState.Executed; - } else if (block.timestamp >= add256(proposal.eta, timelock.GRACE_PERIOD())) { + } else if (block.timestamp >= (proposal.eta + timelock.GRACE_PERIOD())) { return ProposalState.Expired; } else { return ProposalState.Queued; } } - function add256(uint256 a, uint256 b) internal pure returns (uint) { - uint c = a + b; - require(c >= a, "addition overflow"); - return c; - } + /** + * @notice Get details of a proposal by its id + * @param proposalId The id of the proposal + * @return id The id of the proposal + * @return proposer The address of the proposer + * @return eta The estimated time at which the proposal can be executed + * @return targets targets of the proposal actions + * @return values ETH values of the proposal actions + * @return signatures signatures of the proposal actions + * @return calldatas calldatas of the proposal actions + * @return canceled boolean indicating whether the proposal has been canceled + * @return executed boolean indicating whether the proposal has been executed + */ function getProposal(uint proposalId) public view returns ( - uint id, - address proposer, + uint, + address, uint eta, - address[] memory targets, - uint[] memory values, - string[] memory signatures, - bytes[] memory calldatas, - string memory description, - bool canceled, - bool executed + address[] memory, + uint[] memory, + string[] memory, + bytes[] memory, + bool, + bool ) { MarketUpdateProposal storage proposal = proposals[proposalId]; @@ -251,7 +273,6 @@ contract MarketUpdateProposer { proposal.values, proposal.signatures, proposal.calldatas, - proposal.description, proposal.canceled, proposal.executed ); diff --git a/contracts/marketupdates/MarketUpdateTimelock.sol b/contracts/marketupdates/MarketUpdateTimelock.sol index e3f83a93..e66431ca 100644 --- a/contracts/marketupdates/MarketUpdateTimelock.sol +++ b/contracts/marketupdates/MarketUpdateTimelock.sol @@ -39,7 +39,10 @@ contract MarketUpdateTimelock { fallback() external payable { } - + /** + * @notice Sets a new delay for executing transactions + * @param delay_ The new delay in seconds + */ function setDelay(uint delay_) public { require(msg.sender == governor, "MarketUpdateTimelock::setDelay: Call must come from the Main Governor Timelock."); require(delay_ >= MINIMUM_DELAY, "MarketUpdateTimelock::setDelay: Delay must exceed minimum delay."); @@ -49,6 +52,10 @@ contract MarketUpdateTimelock { emit SetDelay(delay); } + /** + * @notice Transfers governor role to a new address + * @param newGovernor The address of the new governor + */ function setGovernor(address newGovernor) public { require(msg.sender == governor, "MarketUpdateTimelock::setGovernor: Call must come from governor."); address oldGovernor = governor; @@ -56,6 +63,10 @@ contract MarketUpdateTimelock { emit SetGovernor(oldGovernor, newGovernor); } + /** + * @notice Sets a new market update proposer + * @param newMarketUpdateProposer The address of the new proposer + */ function setMarketUpdateProposer(address newMarketUpdateProposer) external { require(msg.sender == governor, "MarketUpdateTimelock::setMarketUpdateProposer: Call must come from governor."); address oldMarketUpdateProposer = marketUpdateProposer; @@ -63,6 +74,15 @@ contract MarketUpdateTimelock { emit SetMarketUpdateProposer(oldMarketUpdateProposer, newMarketUpdateProposer); } + /** + * @notice Queues a transaction for execution + * @param target The address of the target contract + * @param value The ETH value to send with the transaction + * @param signature The function signature to call + * @param data The calldata for the function call + * @param eta The time when the transaction can be executed + * @return The hash of the queued transaction + */ function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) { require(msg.sender == marketUpdateProposer, "MarketUpdateTimelock::queueTransaction: Call must come from marketUpdateProposer."); require(eta >= getBlockTimestamp() + delay, "MarketUpdateTimelock::queueTransaction: Estimated execution block must satisfy delay."); @@ -74,6 +94,14 @@ contract MarketUpdateTimelock { return txHash; } + /** + * @notice Cancels a previously queued transaction + * @param target The address of the target contract + * @param value The ETH value sent with the transaction + * @param signature The function signature + * @param data The calldata for the function + * @param eta The time when the transaction was scheduled to execute + */ function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public { require(msg.sender == marketUpdateProposer, "MarketUpdateTimelock::cancelTransaction: Call must come from marketUpdateProposer."); bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); @@ -82,6 +110,15 @@ contract MarketUpdateTimelock { emit CancelTransaction(txHash, target, value, signature, data, eta); } + /** + * @notice Executes a queued transaction + * @param target The address of the target contract + * @param value The ETH value to send with the transaction + * @param signature The function signature to call + * @param data The calldata for the function call + * @param eta The time when the transaction was scheduled to execute + * @return The return data from the executed transaction + */ function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) { require(msg.sender == marketUpdateProposer, "MarketUpdateTimelock::executeTransaction: Call must come from marketUpdateProposer."); bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); diff --git a/test/configurator-test.ts b/test/configurator-test.ts index 2d8849b7..847154ce 100644 --- a/test/configurator-test.ts +++ b/test/configurator-test.ts @@ -100,7 +100,7 @@ describe('configurator', function () { }); it('reverts if deploy is called from non-governor', async () => { - const { configuratorProxy, proxyAdmin, cometProxy, users: [alice] } = await makeConfigurator(); + const { configuratorProxy, proxyAdmin, cometProxy, users: [alice], governor } = await makeConfigurator(); const MarketAdminPermissionCheckerFactory = (await ethers.getContractFactory( 'MarketAdminPermissionChecker' @@ -108,6 +108,7 @@ describe('configurator', function () { const marketAdminPermissionCheckerContract = await MarketAdminPermissionCheckerFactory.deploy( + governor.address, ethers.constants.AddressZero, ethers.constants.AddressZero ); diff --git a/test/helpers.ts b/test/helpers.ts index 42e29714..18bbaeec 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -431,7 +431,7 @@ export async function makeConfigurator(opts: ProtocolOpts = {}): Promise { @@ -30,7 +30,7 @@ describe('CometProxyAdmin', function() { await expect( proxyAdmin.connect(bob).transferOwnership(alice.address) - ).to.be.revertedWith('Ownable: caller is not the owner'); + ).to.be.revertedWithCustomError(proxyAdmin,'OwnableUnauthorizedAccount'); }); it('market admin cannot transferOwnership of CometProxyAdmin', async () => { @@ -56,7 +56,7 @@ describe('CometProxyAdmin', function() { proxyAdmin .connect(marketUpdateTimelockSigner) .transferOwnership(alice.address) - ).to.be.revertedWith('Ownable: caller is not the owner'); + ).to.be.revertedWithCustomError(proxyAdmin,'OwnableUnauthorizedAccount'); }); diff --git a/test/marketupdates/market-update-deployment-test.ts b/test/marketupdates/market-update-deployment-test.ts index e761fe5c..0602ce70 100644 --- a/test/marketupdates/market-update-deployment-test.ts +++ b/test/marketupdates/market-update-deployment-test.ts @@ -158,7 +158,7 @@ describe('MarketUpdateDeployment', function() { )) as CometProxyAdmin__factory; const proxyAdminNew = await ProxyAdmin.connect( marketUpdateMultiSig - ).deploy(); + ).deploy(marketUpdateMultiSig.address); // 5) Set MainGovernorTimelock as the owner of new CometProxyAdmin by calling transferOwnership await proxyAdminNew @@ -182,15 +182,11 @@ describe('MarketUpdateDeployment', function() { const marketAdminPermissionCheckerContract = await MarketAdminPermissionCheckerFactory.deploy( + governorTimelock.address, ethers.constants.AddressZero, ethers.constants.AddressZero ); - // 8) Transfer the ownership of MarketAdminPermissionChecker to Governor Timelock - await marketAdminPermissionCheckerContract.transferOwnership( - governorTimelock.address - ); - // ------- Update Existing Contracts ----------- console.log('Updating the existing contracts'); @@ -382,7 +378,7 @@ describe('MarketUpdateDeployment', function() { // Deploy ProxyAdmin const ProxyAdmin = (await ethers.getContractFactory('CometProxyAdminOld')) as CometProxyAdminOld__factory; - const proxyAdmin = await ProxyAdmin.connect(governorTimelockSigner).deploy(); + const proxyAdmin = await ProxyAdmin.connect(governorTimelockSigner).deploy(governorTimelockSigner.address); // Deploy Comet proxy const CometProxy = (await ethers.getContractFactory('TransparentUpgradeableProxy')) as TransparentUpgradeableProxy__factory; diff --git a/test/marketupdates/market-update-permission-checker-test.ts b/test/marketupdates/market-update-permission-checker-test.ts index 6d0acb4e..eaa55a46 100644 --- a/test/marketupdates/market-update-permission-checker-test.ts +++ b/test/marketupdates/market-update-permission-checker-test.ts @@ -39,13 +39,13 @@ describe('MarketUpdatePermissionChecker', () => { marketAdminPermissionCheckerContract .connect(marketUpdateMultiSig) .setMarketAdmin(newMarketAdminWallet.address) - ).to.be.revertedWith('Ownable: caller is not the owner'); + ).to.be.revertedWithCustomError(marketAdminPermissionCheckerContract,'OwnableUnauthorizedAccount'); await expect( marketAdminPermissionCheckerContract .connect(marketUpdateTimelockSigner) .setMarketAdmin(newMarketAdminWallet.address) - ).to.be.revertedWith('Ownable: caller is not the owner'); + ).to.be.revertedWithCustomError(marketAdminPermissionCheckerContract,'OwnableUnauthorizedAccount'); }); it('only the owner can set the market admin pause guardian', async () => { @@ -84,13 +84,13 @@ describe('MarketUpdatePermissionChecker', () => { marketAdminPermissionCheckerContract .connect(marketUpdateMultiSig) .setMarketAdminPauseGuardian(marketUpdateTimelockSigner.address) - ).to.be.revertedWith('Ownable: caller is not the owner'); + ).to.be.revertedWithCustomError(marketAdminPermissionCheckerContract,'OwnableUnauthorizedAccount'); await expect( marketAdminPermissionCheckerContract .connect(marketUpdateTimelockSigner) .setMarketAdminPauseGuardian(marketUpdateTimelockSigner.address) - ).to.be.revertedWith('Ownable: caller is not the owner'); + ).to.be.revertedWithCustomError(marketAdminPermissionCheckerContract,'OwnableUnauthorizedAccount'); }); diff --git a/test/marketupdates/market-update-proposer-test.ts b/test/marketupdates/market-update-proposer-test.ts index 7fb753a4..16b9ca00 100644 --- a/test/marketupdates/market-update-proposer-test.ts +++ b/test/marketupdates/market-update-proposer-test.ts @@ -167,12 +167,11 @@ describe('MarketUpdateProposer', function() { // Checks the proposal const proposal = await marketUpdateProposerContract.getProposal(proposalId); - expect(proposal.id).to.equal(proposalId); - expect(proposal.proposer).to.equal(marketUpdateMultiSig.address); - expect(proposal.targets[0]).to.equal(configuratorProxy.address); - expect(proposal.signatures[0]).to.equal('setSupplyKink(address,uint64)'); - expect(proposal.calldatas[0]).to.equal(setSupplyKinkCalldata); - expect(proposal.description).to.equal(proposalDescription); + expect(proposal[0]).to.equal(proposalId); + expect(proposal[1]).to.equal(marketUpdateMultiSig.address); + expect(proposal[3][0]).to.equal(configuratorProxy.address); + expect(proposal[5][0]).to.equal('setSupplyKink(address,uint64)'); + expect(proposal[6][0]).to.equal(setSupplyKinkCalldata); }); it('can cancel the proposal', async () => { diff --git a/test/marketupdates/market-updates-helper.ts b/test/marketupdates/market-updates-helper.ts index c44a0d28..b2b4a951 100644 --- a/test/marketupdates/market-updates-helper.ts +++ b/test/marketupdates/market-updates-helper.ts @@ -13,7 +13,7 @@ export async function makeMarketAdmin() { const signers = await ethers.getSigners(); - const marketUpdateMultiSig = signers[10]; + const marketUpdateMultiSig = signers[8]; const marketUpdateProposalGuardianSigner = signers[11]; const marketAdminPauseGuardianSigner = signers[9]; @@ -76,10 +76,11 @@ export async function makeMarketAdmin() { const marketAdminPermissionCheckerContract = await MarketAdminPermissionCheckerFactory.deploy( + governorTimelockSigner.address, marketUpdateTimelockContract.address, marketAdminPauseGuardianSigner.address ); - await marketAdminPermissionCheckerContract.transferOwnership(governorTimelockSigner.address); + // await marketAdminPermissionCheckerContract.transferOwnership(governorTimelockSigner.address); await marketUpdateTimelockContract .connect(governorTimelockSigner) From ad06d636b31808825272c16633068dd6ec6fc7e0 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 8 Oct 2024 12:05:11 -0400 Subject: [PATCH 10/28] Address audit feedback --- contracts/marketupdates/MarketUpdateProposer.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/marketupdates/MarketUpdateProposer.sol b/contracts/marketupdates/MarketUpdateProposer.sol index d879ff39..7f7061c9 100644 --- a/contracts/marketupdates/MarketUpdateProposer.sol +++ b/contracts/marketupdates/MarketUpdateProposer.sol @@ -255,7 +255,7 @@ contract MarketUpdateProposer { returns ( uint, address, - uint eta, + uint, address[] memory, uint[] memory, string[] memory, From ebb2d9645f55470b76a5bee8235449cf2c28b9b8 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 8 Oct 2024 16:40:32 -0400 Subject: [PATCH 11/28] Fix mainnet tests --- .../marketupdates/helpers/GovernanceHelper.sol | 9 +++------ forge/test/MarketUpdateDeploymentBaseTest.sol | 5 +++-- forge/test/MarketUpdateMainnetDeploymentTest.t.sol | 12 ++++++++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/forge/script/marketupdates/helpers/GovernanceHelper.sol b/forge/script/marketupdates/helpers/GovernanceHelper.sol index a642dd3a..4f25feb0 100644 --- a/forge/script/marketupdates/helpers/GovernanceHelper.sol +++ b/forge/script/marketupdates/helpers/GovernanceHelper.sol @@ -16,9 +16,6 @@ library GovernanceHelper { address constant governorBravoProxyAddress = 0xc0Da02939E1441F497fd74F78cE7Decb17B66529; IGovernorBravo constant governorBravo = IGovernorBravo(governorBravoProxyAddress); - address constant marketUpdateProposerAddress = 0x4c3B63642bC627735c0BFaB7332b96f3a2B0d476; - MarketUpdateProposer constant marketUpdateProposer = MarketUpdateProposer(marketUpdateProposerAddress); - // COMP token address address constant compTokenAddress = 0xc00e94Cb662C3520282E6f5717214004A7f26888; IComp constant compToken = IComp(compTokenAddress); @@ -126,14 +123,14 @@ library GovernanceHelper { moveProposalToExecution(vm, proposalId); } - function createAndPassMarketUpdateProposal(Vm vm, ProposalRequest memory proposalRequest, string memory description) public { + function createAndPassMarketUpdateProposal(Vm vm, ProposalRequest memory proposalRequest, string memory description, address marketUpdateProposer) public { vm.startPrank(MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS); - marketUpdateProposer.propose(proposalRequest.targets, proposalRequest.values, proposalRequest.signatures, proposalRequest.calldatas, description); + MarketUpdateProposer(marketUpdateProposer).propose(proposalRequest.targets, proposalRequest.values, proposalRequest.signatures, proposalRequest.calldatas, description); // Fast forward by 5 days vm.warp(block.timestamp + 5 days); - marketUpdateProposer.execute(1); + MarketUpdateProposer(marketUpdateProposer).execute(1); vm.stopPrank(); } diff --git a/forge/test/MarketUpdateDeploymentBaseTest.sol b/forge/test/MarketUpdateDeploymentBaseTest.sol index ad4ffcba..f24e1b15 100644 --- a/forge/test/MarketUpdateDeploymentBaseTest.sol +++ b/forge/test/MarketUpdateDeploymentBaseTest.sol @@ -95,7 +95,8 @@ abstract contract MarketUpdateDeploymentBaseTest { Vm vm, address cometProxy, address configuratorProxy, - address cometProxyAdminNew, + address cometProxyAdminNew, + address marketUpdateProposer, string memory marketName ) public { @@ -140,7 +141,7 @@ abstract contract MarketUpdateDeploymentBaseTest { calldatas[0] = abi.encode(cometProxy, newSupplyKinkByMarketAdmin); description = string(abi.encodePacked("Proposal to update Supply Kink for ", marketName, " Market by Market Admin")); - GovernanceHelper.createAndPassMarketUpdateProposal(vm, proposalRequest, description); + GovernanceHelper.createAndPassMarketUpdateProposal(vm, proposalRequest, description, marketUpdateProposer); uint256 newSupplyKinkAfterMarketAdminUpdate = Comet(payable(cometProxy)).supplyKink(); assert(newSupplyKinkAfterMarketAdminUpdate == newSupplyKinkByMarketAdmin); diff --git a/forge/test/MarketUpdateMainnetDeploymentTest.t.sol b/forge/test/MarketUpdateMainnetDeploymentTest.t.sol index e2a5621f..fc5251e1 100644 --- a/forge/test/MarketUpdateMainnetDeploymentTest.t.sol +++ b/forge/test/MarketUpdateMainnetDeploymentTest.t.sol @@ -28,7 +28,8 @@ contract MarketUpdateMainnetDeploymentTest is Test, MarketUpdateDeploymentBaseTe vm, MarketAddresses.MAINNET_USDC_MARKET, ChainAddresses.MAINNET_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, "USDC" ); } @@ -40,7 +41,8 @@ contract MarketUpdateMainnetDeploymentTest is Test, MarketUpdateDeploymentBaseTe vm, MarketAddresses.MAINNET_USDT_MARKET, ChainAddresses.MAINNET_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, "USDT" ); } @@ -52,7 +54,8 @@ contract MarketUpdateMainnetDeploymentTest is Test, MarketUpdateDeploymentBaseTe vm, MarketAddresses.MAINNET_ETH_MARKET, ChainAddresses.MAINNET_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, "ETH" ); } @@ -64,7 +67,8 @@ contract MarketUpdateMainnetDeploymentTest is Test, MarketUpdateDeploymentBaseTe vm, MarketAddresses.MAINNET_WST_ETH_MARKET, ChainAddresses.MAINNET_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, + deployedContracts.newCometProxyAdmin, + deployedContracts.marketUpdateProposer, "WST_ETH" ); } From dd6537dade9a1d8523949cfdc1c64606536d877c Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 15 Oct 2024 17:27:02 -0400 Subject: [PATCH 12/28] Add scroll migration --- .gitignore | 2 + Makefile | 111 ++++++++++ .../1728316375_gov_marketupdates.ts | 193 ++++++++++++++++++ .../marketupdates/DeployContracts.s.sol | 187 ++++++++++++++++- .../marketupdates/helpers/ChainAddresses.sol | 68 +++++- .../helpers/MarketUpdateContractsDeployer.sol | 25 ++- forge/simulate.md | 139 ++++++++++++- forge/test/MarketUpdateDeploymentBaseTest.sol | 3 + foundry.toml | 4 + hardhat.config.ts | 11 +- plugins/scenario/utils/hreForBase.ts | 10 +- scripts/marketupdates/deploySafe.ts | 80 ++++++-- src/deploy/index.ts | 4 +- 13 files changed, 780 insertions(+), 57 deletions(-) create mode 100644 Makefile create mode 100644 deployments/optimism/usdc/migrations/1728316375_gov_marketupdates.ts diff --git a/.gitignore b/.gitignore index 53901c04..7455400f 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ scenario-results.json deployments/localhost/dai/roots.json forge/Makefile .envrc + +broadcast/ \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..5acd1e01 --- /dev/null +++ b/Makefile @@ -0,0 +1,111 @@ +# Makefile for verifying contracts + + +# Declare constants at the top +GOVERNOR_TIMELOCK_ADDRESS = 0xDeployedGovernorTimelock +MARKET_UPDATE_MULTISIG = 0xDeployedMarketUpdateMultisig +PROPOSAL_GUARDIAN_ADDRESS = 0xDeployedProposalGuardian +MARKET_ADMIN_TIMELOCK_ADDRESS = 0xDeployedComputedTimelock +MARKET_UPDATE_PROPOSER = 0xDeployedComputedProposer +CONFIGURATOR = 0xDeployedComputedConfigurator +COMET_PROXY_ADMIN = 0xDeployedComputedProxyAdmin +MARKET_ADMIN_PERMISSION_CHECKER = 0xDeployedComputedMarketAdminPermissionChecker +CHAIN_ID = ChainIdOfTheNetwork +ETHERSCAN_API_KEY = "YourEtherscanApiKey" +SOLIDITY_COMPILER_VERSION = "0.8.15" +SENDER = "0xYourSenderAddress" +EVM_VERSION = "london" +RPC_URL = "RPCUrlOfTheNetwork" +OWNERS = '["0xOwner1", "0xOwner2", "0xOwner3"]' +THRESHOLD = 2 + +# Define targets for each contract +verify-all: verify-MarketUpdateTimelock verify-MarketUpdateProposer verify-Configurator verify-CometProxyAdmin verify-MarketAdminPermissionChecker + +# Deploying Safe +deploy-safe: + @echo "Deploying Safe..." + OWNERS=$(OWNERS) THRESHOLD=$(THRESHOLD) CHAIN_ID=$(CHAIN_ID) yarn hardhat run scripts/marketupdates/deploySafe.ts + +# Deploying the contracts +deploy-contracts: + @echo "Deploying contracts..." + CHAIN_ID=$(CHAIN_ID) forge script forge/script/marketupdates/DeployContracts.s.sol:DeployContracts \ + --rpc-url $(RPC_URL) \ + --optimize \ + --optimizer-runs 200 \ + --use $(SOLIDITY_COMPILER_VERSION) \ + --evm-version $(EVM_VERSION) \ + --broadcast \ + --via-ir \ + -vvvv \ + --sender $(SENDER) + +# Verifying MarketUpdateTimelock +verify-MarketUpdateTimelock: + @echo "Verifying MarketUpdateTimelock..." + forge verify-contract \ + --chain-id $(CHAIN_ID) \ + --compiler-version $(SOLIDITY_COMPILER_VERSION) \ + --optimizer-runs 200 \ + --constructor-args $(shell cast abi-encode "constructor(address,uint256)" $(SENDER) 360000) \ + --etherscan-api-key $(ETHERSCAN_API_KEY) \ + --watch \ + --via-ir \ + ${MARKET_ADMIN_TIMELOCK_ADDRESS} \ + contracts/marketupdates/MarketUpdateTimelock.sol:MarketUpdateTimelock + +# Verifying MarketUpdateProposer +verify-MarketUpdateProposer: + @echo "Verifying MarketUpdateProposer..." + forge verify-contract \ + --chain-id $(CHAIN_ID) \ + --compiler-version $(SOLIDITY_COMPILER_VERSION) \ + --optimizer-runs 200 \ + --constructor-args $(shell cast abi-encode "constructor(address,address,address,address)" $(SENDER) $(MARKET_UPDATE_MULTISIG) $(PROPOSAL_GUARDIAN_ADDRESS) $(MARKET_ADMIN_TIMELOCK_ADDRESS)) \ + --etherscan-api-key $(ETHERSCAN_API_KEY) \ + --watch \ + --via-ir \ + ${MARKET_UPDATE_PROPOSER} \ + contracts/marketupdates/MarketUpdateProposer.sol:MarketUpdateProposer + +# Verifying CometProxyAdmin +verify-CometProxyAdmin: + @echo "Verifying CometProxyAdmin..." + forge verify-contract \ + --chain-id $(CHAIN_ID) \ + --compiler-version $(SOLIDITY_COMPILER_VERSION) \ + --optimizer-runs 200 \ + --constructor-args $(shell cast abi-encode "constructor(address)" $(SENDER)) \ + --etherscan-api-key $(ETHERSCAN_API_KEY) \ + --watch \ + --via-ir \ + ${COMET_PROXY_ADMIN} \ + contracts/CometProxyAdmin.sol:CometProxyAdmin + +# Verifying Configurator +verify-Configurator: + @echo "Verifying Configurator..." + forge verify-contract \ + --chain-id $(CHAIN_ID) \ + --compiler-version $(SOLIDITY_COMPILER_VERSION) \ + --optimizer-runs 200 \ + --etherscan-api-key $(ETHERSCAN_API_KEY) \ + --watch \ + --via-ir \ + ${CONFIGURATOR} \ + contracts/Configurator.sol:Configurator + +# Verifying MarketAdminPermissionChecker +verify-MarketAdminPermissionChecker: + @echo "Verifying MarketAdminPermissionChecker..." + forge verify-contract \ + --chain-id $(CHAIN_ID) \ + --compiler-version $(SOLIDITY_COMPILER_VERSION) \ + --optimizer-runs 200 \ + --constructor-args $(shell cast abi-encode "constructor(address,address,address)" $(SENDER) $(MARKET_UPDATE_MULTISIG) 0x0000000000000000000000000000000000000000) \ + --etherscan-api-key $(ETHERSCAN_API_KEY) \ + --watch \ + --via-ir \ + ${MARKET_ADMIN_PERMISSION_CHECKER} \ + contracts/marketupdates/MarketAdminPermissionChecker.sol:MarketAdminPermissionChecker diff --git a/deployments/optimism/usdc/migrations/1728316375_gov_marketupdates.ts b/deployments/optimism/usdc/migrations/1728316375_gov_marketupdates.ts new file mode 100644 index 00000000..7b7c19d5 --- /dev/null +++ b/deployments/optimism/usdc/migrations/1728316375_gov_marketupdates.ts @@ -0,0 +1,193 @@ +import { exp, proposal } from '../../../../src/deploy'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; + +interface Vars { + deployedContracts: any; +}; + +const governorTimelockAddress = '0x6d903f6003cca6255D85CcA4D3B5E5146dC33925'; +const marketUpdateMultiSig = '0x7053e25f7076F4986D632A3C04313C81831e0d55'; +const marketUpdateProposalGuardian = + '0x77B65c68E52C31eb844fb3b4864B91133e2C1308'; +const delay = 360000; + + +export default migration('1728316375_gov_marketupdates', { + prepare: async (deploymentManager: DeploymentManager) => { + const ethers = deploymentManager.hre.ethers; + + const marketUpdateTimelock = await deploymentManager.deploy( + 'marketUpdateTimelock', + 'marketupdates/MarketUpdateTimelock.sol', + [governorTimelockAddress, delay], + true + ); + + const marketUpdateProposer = await deploymentManager.deploy( + 'marketUpdateProposer', + 'marketupdates/MarketUpdateProposer.sol', + [ + governorTimelockAddress, + marketUpdateMultiSig, + marketUpdateProposalGuardian, + marketUpdateTimelock.address, + ], + true + ); + + const configurator = await deploymentManager.deploy( + 'configuratorNew', + 'Configurator.sol', + [], + true + ); + + const cometProxyAdmin = await deploymentManager.deploy( + 'cometProxyAdminNew', + 'CometProxyAdmin.sol', + [governorTimelockAddress], + true + ); + + const marketAdminPermissionChecker = await deploymentManager.deploy( + 'marketAdminPermissionChecker', + 'marketupdates/MarketAdminPermissionChecker.sol', + [ + governorTimelockAddress, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ] + ); + const deployedContracts = { + marketUpdateTimelock, + marketUpdateProposer, + configurator, + cometProxyAdmin, + marketAdminPermissionChecker, + }; + + return { deployedContracts }; + }, + + enact: async ( + deploymentManager: DeploymentManager, + govDeploymentManager: DeploymentManager, + vars: Vars + ) => { + const trace = deploymentManager.tracer(); + const ethers = deploymentManager.hre.ethers; + const { utils } = ethers; + + // Assuming that we have the addresses of the contracts we need to interact with + const addresses: any = {}; + + const { bridgeReceiver, comet, cometAdmin, configurator, rewards } = + await deploymentManager.getContracts(); + + const { scrollMessenger, scrollL1USDCGateway, governor, USDC } = + await govDeploymentManager.getContracts(); + + const cometProxyAdminOldAddress = addresses.cometProxyAdminAddress; + const configuratorProxyAddress = addresses.configuratorProxyAddress; + const configuratorNewAddress = addresses.configuratorImplementationAddress; + const cometProxyAdminNewAddress = addresses.newCometProxyAdminAddress; + const marketAdminPermissionCheckerAddress = + addresses.marketAdminPermissionCheckerAddress; + const marketUpdateTimelockAddress = addresses.marketUpdateTimelockAddress; + const marketUpdateProposerAddress = addresses.marketAdminProposerAddress; + const cometProxyAddress = addresses.markets[0].cometProxyAddress; + + const changeProxyAdminForCometProxyCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [cometProxyAddress, cometProxyAdminNewAddress] + ); + + const changeProxyAdminForConfiguratorProxyCalldata = + utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyAddress, cometProxyAdminNewAddress] + ); + + const upgradeConfiguratorProxyCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyAddress, configuratorNewAddress] + ); + + const setMarketAdminCalldata = utils.defaultAbiCoder.encode( + ['address'], + [marketUpdateTimelockAddress] + ); + + const setMarketAdminPermissionCheckerForConfiguratorProxyCalldata = + utils.defaultAbiCoder.encode( + ['address'], + [marketAdminPermissionCheckerAddress] + ); + + const setMarketAdminPermissionCheckerForCometProxyCalldata = + utils.defaultAbiCoder.encode( + ['address'], + [marketAdminPermissionCheckerAddress] + ); + + const setMarketUpdateProposerCalldata = utils.defaultAbiCoder.encode( + ['address'], + [marketUpdateProposerAddress] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [ + cometProxyAdminOldAddress, + cometProxyAdminOldAddress, + cometProxyAdminNewAddress, + marketAdminPermissionCheckerAddress, + configuratorProxyAddress, + cometProxyAdminNewAddress, + marketUpdateTimelockAddress, + ], + [0, 0, 0, 0, 0, 0, 0], + [ + 'changeProxyAdmin(address,address)', + 'changeProxyAdmin(address,address)', + 'upgrade(address,address)', + 'setMarketAdmin(address)', + 'setMarketAdminPermissionChecker(address)', + 'setMarketAdminPermissionChecker(address)', + 'setMarketUpdateProposer(address)', + ], + [ + changeProxyAdminForCometProxyCalldata, + changeProxyAdminForConfiguratorProxyCalldata, + upgradeConfiguratorProxyCalldata, + setMarketAdminCalldata, + setMarketAdminPermissionCheckerForConfiguratorProxyCalldata, + setMarketAdminPermissionCheckerForCometProxyCalldata, + setMarketUpdateProposerCalldata, + ], + ] + ); + + const actions = [ + { + contract: scrollMessenger, + signature: 'sendMessage(address,uint256,bytes,uint256)', + args: [bridgeReceiver.address, 0, l2ProposalData, 600_000], + value: exp(0.1, 18), + }, + ]; + + const description = + 'Governance proposal with actions to change proxy admins, upgrade the configurator, and set the market admin and related roles.'; + const txn = await govDeploymentManager.retry(async () => + trace(await governor.propose(...(await proposal(actions, description)))) + ); + + const event = txn.events.find((event) => event.event === 'ProposalCreated'); + const [proposalId] = event.args; + + trace(`Created proposal ${proposalId}.`); + } +}); diff --git a/forge/script/marketupdates/DeployContracts.s.sol b/forge/script/marketupdates/DeployContracts.s.sol index b27437b5..586d553c 100644 --- a/forge/script/marketupdates/DeployContracts.s.sol +++ b/forge/script/marketupdates/DeployContracts.s.sol @@ -10,11 +10,21 @@ import "@comet-contracts/CometProxyAdmin.sol"; import "@comet-contracts/marketupdates/MarketAdminPermissionChecker.sol"; import "@comet-contracts/Create2DeployerInterface.sol"; import "./helpers/MarketUpdateAddresses.sol"; -import "./helpers/MarketUpdateContractsDeployer.sol"; +import "./helpers/ChainAddresses.sol"; contract DeployContracts is Script { address public deployedWalletAddress; + address constant public create2DeployerAddress = 0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2; + + struct DeployedContracts { + address marketUpdateTimelock; + address marketUpdateProposer; + address newCometProxyAdmin; + address newConfiguratorImplementation; + address marketAdminPermissionChecker; + } + struct ContractDeploymentParams { bytes creationCode; bytes constructorArgs; @@ -23,19 +33,31 @@ contract DeployContracts is Script { } function run() external { - address timelock = 0x6d903f6003cca6255D85CcA4D3B5E5146dC33925; + uint256 passedChainId = vm.envUint("CHAIN_ID"); + + require(block.chainid == passedChainId, "Chain ID mismatch"); + + ChainAddresses.Chain chain = ChainAddresses.getChainBasedOnChainId(passedChainId); + ChainAddresses.ChainAddressesStruct memory chainAddresses = ChainAddresses.getChainAddresses(chain); + + console.log("Deploying contracts with sender: ", msg.sender); - vm.startBroadcast(vm.envUint("PRIVATE_KEY")); - - bytes32 salt = keccak256(abi.encodePacked("Salt-31")); + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + address deployer = vm.rememberKey(deployerPrivateKey); + vm.startBroadcast(deployer); + + console.log("Broadcasting transaction with deployer: ", deployer); + + bytes32 salt = keccak256(abi.encodePacked("Salt-34")); /// Call library function - MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer.deployContracts( + DeployedContracts memory deployedContracts = deployContracts( salt, MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS, MarketUpdateAddresses.MARKET_ADMIN_PAUSE_GUARDIAN_ADDRESS, MarketUpdateAddresses.MARKET_UPDATE_PROPOSAL_GUARDIAN_ADDRESS, - timelock + chainAddresses.governorTimelockAddress ); /// Console log deployed contracts @@ -47,4 +69,155 @@ contract DeployContracts is Script { vm.stopBroadcast(); } + + function deployContracts( + bytes32 salt, + address marketUpdateMultiSig, // TODO: Check this is properly used + address marketAdminPauseGuardianAddress, // TODO: Check this is properly used + address marketUpdateProposalGuardianAddress, // TODO: Check this is properly used + address localTimelockAddress + ) public returns (DeployedContracts memory) { + + ICreate2Deployer create2Deployer = ICreate2Deployer(create2DeployerAddress); + + // Prepare deployment parameters for each contract + ContractDeploymentParams memory marketUpdateTimelockParams = ContractDeploymentParams({ + creationCode: type(MarketUpdateTimelock).creationCode, + constructorArgs: abi.encode(msg.sender, 360000), // TODO: add comment on how 360000 is calculated + expectedRuntimeCode: type(MarketUpdateTimelock).runtimeCode, + contractName: "MarketUpdateTimelock" + }); + + address computedMarketUpdateTimelockAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateTimelockParams); + + console.log("Current Governor of timelock", MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).governor()); + + ContractDeploymentParams memory marketUpdateProposerParams = ContractDeploymentParams({ + creationCode: type(MarketUpdateProposer).creationCode, + constructorArgs: abi.encode( + msg.sender, + marketUpdateMultiSig, + marketUpdateProposalGuardianAddress, + computedMarketUpdateTimelockAddress + ), + expectedRuntimeCode: type(MarketUpdateProposer).runtimeCode, + contractName: "MarketUpdateProposer" + }); + + address computedMarketUpdateProposerAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateProposerParams); + MarketUpdateProposer(computedMarketUpdateProposerAddress).setGovernor(localTimelockAddress); + + MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setMarketUpdateProposer(computedMarketUpdateProposerAddress); + MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setGovernor(localTimelockAddress); + + ContractDeploymentParams memory configuratorParams = ContractDeploymentParams({ + creationCode: type(Configurator).creationCode, + constructorArgs: "", + expectedRuntimeCode: type(Configurator).runtimeCode, + contractName: "Configurator" + }); + + address computedConfiguratorAddress = deployContractWithCreate2(create2Deployer, salt, configuratorParams); + + ContractDeploymentParams memory cometProxyAdminParams = ContractDeploymentParams({ + creationCode: type(CometProxyAdmin).creationCode, + constructorArgs: abi.encode(msg.sender), + expectedRuntimeCode: type(CometProxyAdmin).runtimeCode, + contractName: "CometProxyAdmin" + }); + + address computedCometProxyAdminAddress = deployContractWithCreate2(create2Deployer, salt, cometProxyAdminParams); + CometProxyAdmin(computedCometProxyAdminAddress).transferOwnership(localTimelockAddress); + + console.log("Owner of cometProxyAdmin: ", CometProxyAdmin(computedCometProxyAdminAddress).owner()); + + ContractDeploymentParams memory marketAdminPermissionCheckerParams = ContractDeploymentParams({ + creationCode: type(MarketAdminPermissionChecker).creationCode, + constructorArgs: abi.encode(msg.sender, marketUpdateMultiSig, address(0)), + expectedRuntimeCode: type(MarketAdminPermissionChecker).runtimeCode, + contractName: "MarketAdminPermissionChecker" + }); + + address computedMarketAdminPermissionCheckerAddress = deployContractWithCreate2(create2Deployer, salt, marketAdminPermissionCheckerParams); + MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).transferOwnership(localTimelockAddress); + + return DeployedContracts({ + marketUpdateTimelock: computedMarketUpdateTimelockAddress, + marketUpdateProposer: computedMarketUpdateProposerAddress, + newCometProxyAdmin: computedCometProxyAdminAddress, + newConfiguratorImplementation: computedConfiguratorAddress, + marketAdminPermissionChecker: computedMarketAdminPermissionCheckerAddress + }); + } + + function deployContractWithCreate2( + ICreate2Deployer create2Deployer, + bytes32 salt, + ContractDeploymentParams memory params + ) internal returns (address) { + bytes memory bytecode = abi.encodePacked(params.creationCode, params.constructorArgs); + address computedAddress = create2Deployer.computeAddress(salt, keccak256(bytecode)); + checkOrDeployAndCompareBytecodes(create2Deployer, salt, bytecode, computedAddress, params.expectedRuntimeCode); + return computedAddress; + } + + function checkOrDeployAndCompareBytecodes( + ICreate2Deployer create2Deployer, + bytes32 salt, + bytes memory actualBytecode, + address computedAddress, + bytes memory expectedBytecode + ) internal { + uint256 contractCodeSize = getContractCodeSizeAtAddress(computedAddress); + + if (contractCodeSize > 0) { + bytes memory deployedBytecode = verifyDeployedBytecode(computedAddress, contractCodeSize); + + require( + keccak256(deployedBytecode) == keccak256(expectedBytecode), + "Deployed bytecode does not match the expected bytecode" + ); + } else { + deployAndCompareBytecodes(create2Deployer, salt, actualBytecode, computedAddress, expectedBytecode); + } + } + + function deployAndCompareBytecodes( + ICreate2Deployer create2Deployer, + bytes32 salt, + bytes memory actualBytecode, + address computedAddress, + bytes memory expectedBytecode + ) internal { + create2Deployer.deploy(0, salt, actualBytecode); + + uint256 size = getContractCodeSizeAtAddress(computedAddress); + require(size > 0, "No contract deployed at this address"); + + bytes memory deployedBytecode = new bytes(size); + assembly { + extcodecopy(computedAddress, add(deployedBytecode, 0x20), 0, size) + } + + require( + keccak256(deployedBytecode) == keccak256(expectedBytecode), + "Deployed bytecode does not match the expected bytecode" + ); + } + + function getContractCodeSizeAtAddress(address contractAddress) internal view returns (uint256) { + uint256 size; + assembly { + size := extcodesize(contractAddress) + } + return size; + } + + function verifyDeployedBytecode(address computedAddress, uint256 contractCodeSize) internal view returns (bytes memory) { + bytes memory deployedBytecode = new bytes(contractCodeSize); + assembly { + extcodecopy(computedAddress, add(deployedBytecode, 0x20), 0, contractCodeSize) + } + return deployedBytecode; + } } diff --git a/forge/script/marketupdates/helpers/ChainAddresses.sol b/forge/script/marketupdates/helpers/ChainAddresses.sol index 6cec498d..7058b095 100644 --- a/forge/script/marketupdates/helpers/ChainAddresses.sol +++ b/forge/script/marketupdates/helpers/ChainAddresses.sol @@ -7,6 +7,8 @@ library ChainAddresses { address governorTimelockAddress; address configuratorProxyAddress; address cometProxyAdminAddress; + address marketUpdatePauseGuardian; + address marketUpdateProposalGuardian; } enum Chain { @@ -15,7 +17,9 @@ library ChainAddresses { ARBITRUM, BASE, SCROLL, - OPTIMISM + OPTIMISM, + MAINNET_SEPOLIA, + OP_SEPOLIA } @@ -59,37 +63,65 @@ library ChainAddresses { return ChainAddressesStruct({ governorTimelockAddress: MAINNET_GOVERNOR_TIMELOCK, configuratorProxyAddress: MAINNET_CONFIGURATOR_PROXY, - cometProxyAdminAddress: MAINNET_COMET_PROXY_ADMIN + cometProxyAdminAddress: MAINNET_COMET_PROXY_ADMIN, + marketUpdatePauseGuardian: address(0), + marketUpdateProposalGuardian: address(0) }); } else if (chain == Chain.POLYGON) { return ChainAddressesStruct({ governorTimelockAddress: POLYGON_LOCAL_TIMELOCK, configuratorProxyAddress: POLYGON_CONFIGURATOR_PROXY, - cometProxyAdminAddress: POLYGON_COMET_PROXY_ADMIN + cometProxyAdminAddress: POLYGON_COMET_PROXY_ADMIN, + marketUpdatePauseGuardian: address(0), + marketUpdateProposalGuardian: address(0) }); } else if (chain == Chain.ARBITRUM) { return ChainAddressesStruct({ governorTimelockAddress: ARBITRUM_LOCAL_TIMELOCK, configuratorProxyAddress: ARBITRUM_CONFIGURATOR_PROXY, - cometProxyAdminAddress: ARBITRUM_COMET_PROXY_ADMIN + cometProxyAdminAddress: ARBITRUM_COMET_PROXY_ADMIN, + marketUpdatePauseGuardian: address(0), + marketUpdateProposalGuardian: address(0) }); } else if (chain == Chain.BASE) { return ChainAddressesStruct({ governorTimelockAddress: BASE_LOCAL_TIMELOCK, configuratorProxyAddress: BASE_CONFIGURATOR_PROXY, - cometProxyAdminAddress: BASE_COMET_PROXY_ADMIN + cometProxyAdminAddress: BASE_COMET_PROXY_ADMIN, + marketUpdatePauseGuardian: address(0), + marketUpdateProposalGuardian: address(0) }); } else if (chain == Chain.SCROLL) { return ChainAddressesStruct({ governorTimelockAddress: SCROLL_LOCAL_TIMELOCK, configuratorProxyAddress: SCROLL_CONFIGURATOR_PROXY, - cometProxyAdminAddress: SCROLL_COMET_PROXY_ADMIN + cometProxyAdminAddress: SCROLL_COMET_PROXY_ADMIN, + marketUpdatePauseGuardian: address(0), + marketUpdateProposalGuardian: address(0) }); } else if (chain == Chain.OPTIMISM) { return ChainAddressesStruct({ governorTimelockAddress: OPTIMISM_LOCAL_TIMELOCK, configuratorProxyAddress: OPTIMISM_CONFIGURATOR_PROXY, - cometProxyAdminAddress: OPTIMISM_COMET_PROXY_ADMIN + cometProxyAdminAddress: OPTIMISM_COMET_PROXY_ADMIN, + marketUpdatePauseGuardian: address(0), + marketUpdateProposalGuardian: address(0) + }); + } else if (chain == Chain.OP_SEPOLIA) { + return ChainAddressesStruct({ + governorTimelockAddress: OPTIMISM_LOCAL_TIMELOCK, + configuratorProxyAddress: OPTIMISM_CONFIGURATOR_PROXY, + cometProxyAdminAddress: OPTIMISM_COMET_PROXY_ADMIN, + marketUpdatePauseGuardian: address(0), + marketUpdateProposalGuardian: address(0) + }); + } else if (chain == Chain.MAINNET_SEPOLIA) { + return ChainAddressesStruct({ + governorTimelockAddress: MAINNET_GOVERNOR_TIMELOCK, + configuratorProxyAddress: MAINNET_CONFIGURATOR_PROXY, + cometProxyAdminAddress: MAINNET_COMET_PROXY_ADMIN, + marketUpdatePauseGuardian: address(0), + marketUpdateProposalGuardian: address(0) }); } else { revert("MarketUpdateAddresses: Chain not supported"); @@ -114,4 +146,26 @@ library ChainAddresses { } } + function getChainBasedOnChainId(uint chainId) public pure returns (Chain) { + if(chainId == 1) { + return Chain.ETHEREUM; + } else if(chainId == 137) { + return Chain.POLYGON; + } else if(chainId == 42161) { + return Chain.ARBITRUM; + } else if(chainId == 8453) { + return Chain.BASE; + } else if(chainId == 534352) { + return Chain.SCROLL; + } else if(chainId == 10) { + return Chain.OPTIMISM; + } else if(chainId == 11155420) { + return Chain.OP_SEPOLIA; + } else if(chainId == 11155111) { + return Chain.MAINNET_SEPOLIA; + } else { + revert("MarketUpdateAddresses: Chain not supported"); + } + } + } diff --git a/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol b/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol index 74d14b05..4fef5a2d 100644 --- a/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol +++ b/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol @@ -9,7 +9,7 @@ import "@comet-contracts/CometProxyAdmin.sol"; import "@comet-contracts/marketupdates/MarketAdminPermissionChecker.sol"; import "@forge-std/src/console.sol"; import "./MarketUpdateAddresses.sol"; - +import "@forge-std/src/Vm.sol"; library MarketUpdateContractsDeployer { @@ -31,29 +31,34 @@ library MarketUpdateContractsDeployer { } function deployContracts( + Vm vm, bytes32 salt, address marketUpdateMultiSig, // TODO: Check this is properly used address marketAdminPauseGuardianAddress, // TODO: Check this is properly used address marketUpdateProposalGuardianAddress, // TODO: Check this is properly used - address governorTimelockAddress + address localTimelockAddress ) public returns (DeployedContracts memory) { + console.log("Deploying contracts with sender", msg.sender); ICreate2Deployer create2Deployer = ICreate2Deployer(create2DeployerAddress); + vm.startBroadcast(msg.sender); // Prepare deployment parameters for each contract ContractDeploymentParams memory marketUpdateTimelockParams = ContractDeploymentParams({ creationCode: type(MarketUpdateTimelock).creationCode, - constructorArgs: abi.encode(governorTimelockAddress, 360000), // TODO: add comment on how 360000 is calculated + constructorArgs: abi.encode(msg.sender, 360000), // TODO: add comment on how 360000 is calculated expectedRuntimeCode: type(MarketUpdateTimelock).runtimeCode, contractName: "MarketUpdateTimelock" }); address computedMarketUpdateTimelockAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateTimelockParams); + console.log("Current Governor of timelock", MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).governor()); + ContractDeploymentParams memory marketUpdateProposerParams = ContractDeploymentParams({ creationCode: type(MarketUpdateProposer).creationCode, constructorArgs: abi.encode( - governorTimelockAddress, + msg.sender, marketUpdateMultiSig, marketUpdateProposalGuardianAddress, computedMarketUpdateTimelockAddress @@ -63,6 +68,10 @@ library MarketUpdateContractsDeployer { }); address computedMarketUpdateProposerAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateProposerParams); + MarketUpdateProposer(computedMarketUpdateProposerAddress).setGovernor(localTimelockAddress); + + MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setMarketUpdateProposer(computedMarketUpdateProposerAddress); + MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setGovernor(localTimelockAddress); ContractDeploymentParams memory configuratorParams = ContractDeploymentParams({ creationCode: type(Configurator).creationCode, @@ -75,24 +84,26 @@ library MarketUpdateContractsDeployer { ContractDeploymentParams memory cometProxyAdminParams = ContractDeploymentParams({ creationCode: type(CometProxyAdmin).creationCode, - constructorArgs: abi.encode(governorTimelockAddress), + constructorArgs: abi.encode(msg.sender), expectedRuntimeCode: type(CometProxyAdmin).runtimeCode, contractName: "CometProxyAdmin" }); address computedCometProxyAdminAddress = deployContractWithCreate2(create2Deployer, salt, cometProxyAdminParams); + CometProxyAdmin(computedCometProxyAdminAddress).transferOwnership(localTimelockAddress); console.log("Owner of cometProxyAdmin: ", CometProxyAdmin(computedCometProxyAdminAddress).owner()); ContractDeploymentParams memory marketAdminPermissionCheckerParams = ContractDeploymentParams({ creationCode: type(MarketAdminPermissionChecker).creationCode, - constructorArgs: abi.encode(governorTimelockAddress, address(0), address(0)), + constructorArgs: abi.encode(msg.sender, marketUpdateMultiSig, address(0)), expectedRuntimeCode: type(MarketAdminPermissionChecker).runtimeCode, contractName: "MarketAdminPermissionChecker" }); address computedMarketAdminPermissionCheckerAddress = deployContractWithCreate2(create2Deployer, salt, marketAdminPermissionCheckerParams); - + MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).transferOwnership(localTimelockAddress); + vm.stopBroadcast(); return DeployedContracts({ marketUpdateTimelock: computedMarketUpdateTimelockAddress, marketUpdateProposer: computedMarketUpdateProposerAddress, diff --git a/forge/simulate.md b/forge/simulate.md index d753eb01..6164b4a9 100644 --- a/forge/simulate.md +++ b/forge/simulate.md @@ -1,6 +1,133 @@ -# Work - only for arbitrum -- [ ] Find the local timelocks and use it -- [ ] Verify - When we create a deployment proposal, bridge receiver should send to local timelock -- [ ] ForDeployment - Add logic related to moving the time in timelock and executing the transaction -- [ ] ForKinkUpdates - Add logic related to moving the time in timelock and executing the transaction -- [ ] Make the test pass for arbitrum +# Deployment +Assuming contracts are deployed using forge scripts, we want to write a migration for creating a proposal +for market updates. + +So in the migration, we can call a helper contract which has functions to prepare a proposal. We can see ho to +avoid the initialization of that contract, as in really we just need to call a library which returns the information +needed for creating the proposal. + +# Proposals for L2 +Proposals for l2 has two parts +### 1) Preparation +Preparation involves deploying of the contracts. Here we can just deploy the contracts using the forge scripts. + +Robin with connect with Compound team on Monday to take a decision on this. + + +### 2) Proposal creation +Proposal creation involves two parts + +##### 1) Create L2 payload +Creating the payload of the actions that needs to be taken by local timelock of L2. The payload is +`abi.encode(targets, values, signatures, calldatas)`. We have the code to get the targets, values, signatures, calldatas +i.e. + +```solidity + +// This gets all the chain and market specific addresses. +MarketUpdateAddresses.MarketUpdateAddressesStruct memory addresses = MarketUpdateAddresses.getAddressesForChain( + chain, + deployedContracts, + MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS +); + + +// This gets the payload for the proposal +GovernanceHelper.ProposalRequest memory proposalRequest = GovernanceHelper.createDeploymentProposalRequest(addresses); +``` + +Here DeployedAddresses has the addresses of all the deployed contracts and ProposalRequest has the targets, values, signatures, calldatas. +```solidity +struct DeployedContracts { + address marketUpdateTimelock; + address marketUpdateProposer; + address newCometProxyAdmin; + address newConfiguratorImplementation; + address marketAdminPermissionChecker; +} + + +struct ProposalRequest { + address[] targets; + uint256[] values; + string[] signatures; + bytes[] calldatas; +} +``` +We can either encode in solidity or in the migration script. + +If we look at an existing migration script i.g. `deployments/optimism/usdc/migrations/1721299083_add_wsteth_as_collateral.ts` +We see this part implemented in typescipt +```typescript +const newAssetConfig = { + asset: wstETH.address, + priceFeed: wstETHPricefeed.address, + decimals: await wstETH.decimals(), + borrowCollateralFactor: exp(0.80, 18), + liquidateCollateralFactor: exp(0.85, 18), + liquidationFactor: exp(0.90, 18), + supplyCap: exp(600, 18), +}; + +newPriceFeedAddress = wstETHPricefeed.address; + +const addAssetCalldata = await calldata( + configurator.populateTransaction.addAsset(comet.address, newAssetConfig) +); +const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] +); + +const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, cometAdmin.address], + [0, 0], + [ + 'addAsset(address,(address,address,uint8,uint64,uint64,uint64,uint128))', + 'deployAndUpgradeTo(address,address)', + ], + [addAssetCalldata, deployAndUpgradeToCalldata], + ] +); +``` +##### 2) Creating Mainnet Proposal +For this we plan to use existing migrations as they have the code related to calling of the bridge and for doing +it in a forge script, we have to do quite some unit testing. So we plan to use the existing migrations. + +See this code +```typescript +const mainnetActions = [ + // Send the proposal to the L2 bridge + { + contract: opL1CrossDomainMessenger, + signature: 'sendMessage(address,bytes,uint32)', + args: [bridgeReceiver.address, l2ProposalData, 3_000_000] + }, +]; + +const description = '# Add wstETH as collateral into cUSDCv3 on Optimism\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to add wstETH into cUSDCv3 on Optimism network. This proposal takes the governance steps recommended and necessary to update a Compound III USDC market on Optimism. Simulations have confirmed the market’s readiness, as much as possible, using the [Comet scenario suite](https://github.com/compound-finance/comet/tree/main/scenario). The new parameters include setting the risk parameters based off of the [recommendations from Gauntlet](https://www.comp.xyz/t/gauntlet-wsteth-listing-for-usdc-and-usdt-comet-on-optimism/5441/1).\n\nFurther detailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/892) and [forum discussion](https://www.comp.xyz/t/gauntlet-wsteth-listing-for-usdc-and-usdt-comet-on-optimism/5441).\n\n\n## Proposal Actions\n\nThe first proposal action adds wstETH to the USDC Comet on Optimism. This sends the encoded `addAsset` and `deployAndUpgradeTo` calls across the bridge to the governance receiver on Optimism.'; +const txn = await govDeploymentManager.retry(async () => + trace( + await governor.propose(...(await proposal(mainnetActions, description))) + ) +); + +const event = txn.events.find( + (event) => event.event === 'ProposalCreated' +); +const [proposalId] = event.args; +trace(`Created proposal ${proposalId}.`); + +``` + +# Our Deployment Plan +- We plan to deploy the contracts using the forge scripts. Alternatively we can create a `Deployer(Helper)` or +deploy all the contracts in the prepare function of the migration. +- We plan to create the payload in the migration script. + +# Checklist +- [ ] See what are our options for calling the libraries in the migration script. If +we can call the libraries in the migration script, we can a lot of the extra typescript code. +- [ ] Check pauseGuardian, multisig, and proposalGuardian are set properly diff --git a/forge/test/MarketUpdateDeploymentBaseTest.sol b/forge/test/MarketUpdateDeploymentBaseTest.sol index f24e1b15..8ab12db7 100644 --- a/forge/test/MarketUpdateDeploymentBaseTest.sol +++ b/forge/test/MarketUpdateDeploymentBaseTest.sol @@ -8,6 +8,7 @@ import "../script/marketupdates/helpers/MarketUpdateAddresses.sol"; import "../script/marketupdates/helpers/ChainAddresses.sol"; import "../script/marketupdates/helpers/MarketUpdateContractsDeployer.sol"; import "../script/marketupdates/helpers/BridgeHelper.sol"; +import "@forge-std/src/console.sol"; abstract contract MarketUpdateDeploymentBaseTest { @@ -17,6 +18,7 @@ abstract contract MarketUpdateDeploymentBaseTest { bytes32 salt = keccak256(abi.encodePacked("Salt-31")); MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer.deployContracts( + vm, salt, MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS, MarketUpdateAddresses.MARKET_ADMIN_PAUSE_GUARDIAN_ADDRESS, @@ -63,6 +65,7 @@ abstract contract MarketUpdateDeploymentBaseTest { address localTimelock = ChainAddresses.getLocalTimelockAddress(chain); MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer.deployContracts( + vm, salt, MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS, MarketUpdateAddresses.MARKET_ADMIN_PAUSE_GUARDIAN_ADDRESS, diff --git a/foundry.toml b/foundry.toml index 55c967f6..a5dc0ebc 100644 --- a/foundry.toml +++ b/foundry.toml @@ -24,3 +24,7 @@ arbitrum = "${ARBITRUM_RPC_URL}" optimism = "${OPTIMISM_RPC_URL}" scroll = "${SCROLL_RPC_URL}" base = "${BASE_RPC_URL}" +sepolia = "${SEPOLIA_RPC_URL}" + +[etherscan] +sepolia = { key = "${ETHERSCAN_API_KEY}" } \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index d9cda975..d3ced2a7 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -254,7 +254,16 @@ const config: HardhatUserConfig = { : { mnemonic: MNEMONIC, accountsBalance: (10n ** 36n).toString() }, // this should only be relied upon for test harnesses and coverage (which does not use viaIR flag) allowUnlimitedContractSize: true, - hardfork: 'shanghai' + hardfork: 'shanghai', + chains: { + 534352: { + hardforkHistory: { + london: 0, + berlin: 0, + shanghai: 0, + } + } + } }, localhost: { url: 'http://127.0.0.1:8545', diff --git a/plugins/scenario/utils/hreForBase.ts b/plugins/scenario/utils/hreForBase.ts index 5609d957..1c82ef63 100644 --- a/plugins/scenario/utils/hreForBase.ts +++ b/plugins/scenario/utils/hreForBase.ts @@ -55,8 +55,8 @@ export function nonForkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment { } }, ctx.tasksDSL.getTaskDefinitions(), - ctx.extendersManager.getExtenders(), - ctx.experimentalHardhatNetworkMessageTraceHooks, + ctx.tasksDSL.getScopesDefinitions(), + ctx.environmentExtenders, userConfig ); } @@ -105,8 +105,8 @@ export function forkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment { forkedConfig, hardhatArguments, ctx.tasksDSL.getTaskDefinitions(), - ctx.extendersManager.getExtenders(), - ctx.experimentalHardhatNetworkMessageTraceHooks, + ctx.tasksDSL.getScopesDefinitions(), + ctx.environmentExtenders, userConfig ); } @@ -117,4 +117,4 @@ export default function hreForBase(base: ForkSpec, fork = true): HardhatRuntimeE } else { return nonForkedHreForBase(base); } -} \ No newline at end of file +} diff --git a/scripts/marketupdates/deploySafe.ts b/scripts/marketupdates/deploySafe.ts index 106f6817..b5930f00 100644 --- a/scripts/marketupdates/deploySafe.ts +++ b/scripts/marketupdates/deploySafe.ts @@ -1,22 +1,38 @@ import {SafeAccountConfig, SafeFactory} from '@safe-global/protocol-kit'; import {ethers} from 'hardhat'; -async function deploySafe(owners:string[], threshold:number, salt:string){ - const [deployer] = await ethers.getSigners(); - console.log('Deploying safe with the account:', deployer.address); - const balance = await deployer.getBalance(); - console.log("Account balance:", ethers.utils.formatEther(balance)); - const network = await ethers.provider.getNetwork(); - console.log('Network:', network); +async function deploySafe(owners:string[], threshold:number, salt:string, chainId: number){ let rpcUrl: string; - if (network.chainId === 11155420) { - rpcUrl = process.env.OP_SEPOLIA_RPC!; - } else if (network.chainId === 421614) { - rpcUrl = process.env.ARB_SEPOLIA_RPC!; - } else if (network.chainId === 11155111) { - rpcUrl = process.env.ETH_SEPOLIA_RPC!; - } else { - throw new Error('Unsupported network'); + switch (chainId) { + case 11155420: // Optimism Sepolia + rpcUrl = process.env.OP_SEPOLIA_RPC!; + break; + case 421614: // Arbitrum Sepolia + rpcUrl = process.env.ARB_SEPOLIA_RPC!; + break; + case 11155111: // Ethereum Sepolia + rpcUrl = process.env.ETH_SEPOLIA_RPC!; + break; + case 1: // Ethereum Mainnet + rpcUrl = process.env.ETH_MAINNET_RPC!; + break; + case 137: // Polygon Mainnet + rpcUrl = process.env.POLYGON_MAINNET_RPC!; + break; + case 8453: // Base Mainnet + rpcUrl = process.env.BASE_MAINNET_RPC!; + break; + case 10: // Optimism Mainnet + rpcUrl = process.env.OP_MAINNET_RPC!; + break; + case 42161: // Arbitrum Mainnet + rpcUrl = process.env.ARB_MAINNET_RPC!; + break; + case 534352: // Scroll Mainnet + rpcUrl = process.env.SCROLL_MAINNET_RPC!; + break; + default: + throw new Error('Unsupported chain ID'); } let signer; @@ -29,7 +45,7 @@ async function deploySafe(owners:string[], threshold:number, salt:string){ const safeFactory = await SafeFactory.init({ provider: rpcUrl, signer: signer, safeVersion:'1.4.1' }); const safeAccountConfig: SafeAccountConfig = { - owners:[deployer.address, ...owners], + owners:[...owners], threshold: threshold }; @@ -46,16 +62,36 @@ async function deploySafe(owners:string[], threshold:number, salt:string){ async function main() { - const owners = ['0x7053e25f7076F4986D632A3C04313C81831e0d55', '0x77B65c68E52C31eb844fb3b4864B91133e2C1308']; // Replace with actual addresses - const threshold = 2; // Require 2 out of 3 approvals - const salt = ethers.utils.keccak256(ethers.utils.toUtf8Bytes('deterministic-safe-8')); + const owners = JSON.parse(process.env.OWNERS || '[]'); + const threshold = parseInt(process.env.THRESHOLD || '0', 10); + const chainId = parseInt(process.env.CHAIN_ID || '0', 10); - const {safe} = await deploySafe(owners, threshold, salt); + if (chainId <= 0) { + throw new Error( + 'Invalid chain ID. Please provide a positive integer for the CHAIN_ID environment variable.' + ); + } + + if (owners.length === 0) { + throw new Error( + "No owners provided. Please pass the owners' addresses as a JSON array in the OWNERS environment variable." + ); + } + + if (threshold <= 0) { + throw new Error( + 'Invalid threshold value. Please provide a positive integer for the THRESHOLD environment variable.' + ); + } + + const salt = ethers.utils.keccak256(ethers.utils.toUtf8Bytes('deterministic-safe-11')); + + const {safe} = await deploySafe(owners, threshold, salt, chainId); const safeBalance = await safe.getBalance(); console.log('Safe balance:', safeBalance.toString()); - const chainId = await safe.getChainId(); - console.log('Safe chainId:', chainId); + const chainIdFromSafe = await safe.getChainId(); + console.log('Safe chainId:', chainIdFromSafe); // loading already deployed safe diff --git a/src/deploy/index.ts b/src/deploy/index.ts index 7381208a..bce8d60e 100644 --- a/src/deploy/index.ts +++ b/src/deploy/index.ts @@ -77,7 +77,7 @@ export const COMP_WHALES = { '0x54A37d93E57c5DA659F508069Cf65A381b61E189' ], - testnet: ['0xbbfe34e868343e6f4f5e8b5308de980d7bd88c46'] + testnet: ['0x0579A616689f7ed748dC07692A3F150D44b0CA09'] }; export const WHALES = { @@ -171,4 +171,4 @@ export async function proposal(actions: ProposalAction[], description: string): } } return [targets, values, signatures, calldatas, description]; -} \ No newline at end of file +} From 3f556612df8fa1ff56c2d94d7ccf4995e282bf9f Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 15 Oct 2024 17:27:57 -0400 Subject: [PATCH 13/28] Update Safe deploy scripts --- Makefile | 18 ++++-- scripts/marketupdates/deploySafe.ts | 86 ++++++++++++----------------- 2 files changed, 46 insertions(+), 58 deletions(-) diff --git a/Makefile b/Makefile index 5acd1e01..0bb2d3e0 100644 --- a/Makefile +++ b/Makefile @@ -10,22 +10,28 @@ MARKET_UPDATE_PROPOSER = 0xDeployedComputedProposer CONFIGURATOR = 0xDeployedComputedConfigurator COMET_PROXY_ADMIN = 0xDeployedComputedProxyAdmin MARKET_ADMIN_PERMISSION_CHECKER = 0xDeployedComputedMarketAdminPermissionChecker -CHAIN_ID = ChainIdOfTheNetwork -ETHERSCAN_API_KEY = "YourEtherscanApiKey" + SOLIDITY_COMPILER_VERSION = "0.8.15" -SENDER = "0xYourSenderAddress" +SENDER = "0x470579d16401a36BF63b1428eaA7189FBdE5Fee9" EVM_VERSION = "london" -RPC_URL = "RPCUrlOfTheNetwork" -OWNERS = '["0xOwner1", "0xOwner2", "0xOwner3"]' +OWNERS = '["0xDD659911EcBD4458db07Ee7cDdeC79bf8F859AbC", "0xda32C5AEE8Fc5C51Ed9a99f5608c33f435F740B4", "0x1D8e0b8F4CEd9262C9ac0c0870BF8B45D74ad9D9", "0x47526FDDBA0A5a7ef001FaaD4836b771B3e92522"]' THRESHOLD = 2 +#RPC_URL = "RPCUrlOfTheNetwork" +#SENDER = "0x470579d16401a36BF63b1428eaA7189FBdE5Fee9" +#ETHERSCAN_API_KEY = "" +#CHAIN_ID = ChainIdOfTheNetwork +#SALT = 'salt-salt-sale-salt' + +include .env + # Define targets for each contract verify-all: verify-MarketUpdateTimelock verify-MarketUpdateProposer verify-Configurator verify-CometProxyAdmin verify-MarketAdminPermissionChecker # Deploying Safe deploy-safe: @echo "Deploying Safe..." - OWNERS=$(OWNERS) THRESHOLD=$(THRESHOLD) CHAIN_ID=$(CHAIN_ID) yarn hardhat run scripts/marketupdates/deploySafe.ts + OWNERS=$(OWNERS) THRESHOLD=$(THRESHOLD) SALT=$(SALT) CHAIN_ID=$(CHAIN_ID) yarn hardhat run scripts/marketupdates/deploySafe.ts # Deploying the contracts deploy-contracts: diff --git a/scripts/marketupdates/deploySafe.ts b/scripts/marketupdates/deploySafe.ts index b5930f00..1fa61af9 100644 --- a/scripts/marketupdates/deploySafe.ts +++ b/scripts/marketupdates/deploySafe.ts @@ -2,37 +2,23 @@ import {SafeAccountConfig, SafeFactory} from '@safe-global/protocol-kit'; import {ethers} from 'hardhat'; async function deploySafe(owners:string[], threshold:number, salt:string, chainId: number){ - let rpcUrl: string; - switch (chainId) { - case 11155420: // Optimism Sepolia - rpcUrl = process.env.OP_SEPOLIA_RPC!; - break; - case 421614: // Arbitrum Sepolia - rpcUrl = process.env.ARB_SEPOLIA_RPC!; - break; - case 11155111: // Ethereum Sepolia - rpcUrl = process.env.ETH_SEPOLIA_RPC!; - break; - case 1: // Ethereum Mainnet - rpcUrl = process.env.ETH_MAINNET_RPC!; - break; - case 137: // Polygon Mainnet - rpcUrl = process.env.POLYGON_MAINNET_RPC!; - break; - case 8453: // Base Mainnet - rpcUrl = process.env.BASE_MAINNET_RPC!; - break; - case 10: // Optimism Mainnet - rpcUrl = process.env.OP_MAINNET_RPC!; - break; - case 42161: // Arbitrum Mainnet - rpcUrl = process.env.ARB_MAINNET_RPC!; - break; - case 534352: // Scroll Mainnet - rpcUrl = process.env.SCROLL_MAINNET_RPC!; - break; - default: - throw new Error('Unsupported chain ID'); + const rpcUrls = { + 11155420: process.env.OP_SEPOLIA_RPC, // Optimism Sepolia + 421614: process.env.ARB_SEPOLIA_RPC, // Arbitrum Sepolia + 11155111: process.env.ETH_SEPOLIA_RPC, // Ethereum Sepolia + 1: process.env.ETH_MAINNET_RPC, // Ethereum Mainnet + 137: process.env.POLYGON_MAINNET_RPC, // Polygon Mainnet + 8453: process.env.BASE_MAINNET_RPC, // Base Mainnet + 10: process.env.OP_MAINNET_RPC, // Optimism Mainnet + 42161: process.env.ARB_MAINNET_RPC, // Arbitrum Mainnet + 534352: process.env.SCROLL_MAINNET_RPC, // Scroll Mainnet + 5000: process.env.MANTLE_RPC_URL, // Mantle Mainnet + }; + + const rpcUrl = rpcUrls[chainId]; + + if (!rpcUrl) { + throw new Error('Unsupported chain ID'); } let signer; @@ -49,6 +35,8 @@ async function deploySafe(owners:string[], threshold:number, salt:string, chainI threshold: threshold }; + console.log('Deploying safe with config:', safeAccountConfig); + console.log('Predicting safe address..'); const predictedDeployAddress = await safeFactory.predictSafeAddress(safeAccountConfig,salt); console.log('Predicted deployed address:', predictedDeployAddress); @@ -63,9 +51,10 @@ async function main() { const owners = JSON.parse(process.env.OWNERS || '[]'); - const threshold = parseInt(process.env.THRESHOLD || '0', 10); + const threshold = parseInt(process.env.THRESHOLD || '1', 10); const chainId = parseInt(process.env.CHAIN_ID || '0', 10); - + const saltString = process.env.SALT || ''; + if (chainId <= 0) { throw new Error( 'Invalid chain ID. Please provide a positive integer for the CHAIN_ID environment variable.' @@ -78,34 +67,27 @@ async function main() { ); } - if (threshold <= 0) { + if (threshold <= 1) { throw new Error( 'Invalid threshold value. Please provide a positive integer for the THRESHOLD environment variable.' ); } - - const salt = ethers.utils.keccak256(ethers.utils.toUtf8Bytes('deterministic-safe-11')); + + if (saltString == '') { + throw new Error( + 'Invalid salt value. Please provide a salt for the SALT environment variable.' + ); + } + + const salt = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(saltString)); const {safe} = await deploySafe(owners, threshold, salt, chainId); - const safeBalance = await safe.getBalance(); - console.log('Safe balance:', safeBalance.toString()); const chainIdFromSafe = await safe.getChainId(); - console.log('Safe chainId:', chainIdFromSafe); + console.log('Deployed safe chainId:', chainIdFromSafe); - // loading already deployed safe - - // const predictedSafe: PredictedSafeProps = { - // safeAccountConfig, - // safeDeploymentConfig - // }; - - // const protocolKit = await Safe.init({ - // provider, - // signer, - // safeAddress - // }); - + const safeOwners = await safe.getOwners(); + console.log('Deployed safe owners:', safeOwners); } main() From 8671a90a71ed306e825442eecca8160452ea1804 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 15 Oct 2024 17:28:38 -0400 Subject: [PATCH 14/28] Fix deployment scripts --- Makefile | 20 +- .../1728988057_gov_market_updates.ts | 173 +++++++++++++++++ .../marketupdates/DeployContracts.s.sol | 180 +----------------- .../marketupdates/helpers/ChainAddresses.sol | 64 +++++-- .../helpers/GovernanceHelper.sol | 48 ++--- .../helpers/MarketUpdateContractsDeployer.sol | 72 +++++-- .../MarketUpdateArbitrumDeploymentTest.t.sol | 26 +-- .../test/MarketUpdateBaseDeploymentTest.t.sol | 18 +- forge/test/MarketUpdateDeploymentBaseTest.sol | 65 ++++--- .../MarketUpdateMainnetDeploymentTest.t.sol | 43 ++--- .../MarketUpdateOptimismDeploymentTest.t.sol | 18 +- .../MarketUpdatePolygonDeploymentTest.t.sol | 12 +- .../MarketUpdateScrollDeploymentTest.t.sol | 6 +- tasks/deployment_manager/task.ts | 2 +- 14 files changed, 407 insertions(+), 340 deletions(-) create mode 100644 deployments/scroll/usdc/migrations/1728988057_gov_market_updates.ts diff --git a/Makefile b/Makefile index 0bb2d3e0..8aa1c330 100644 --- a/Makefile +++ b/Makefile @@ -2,14 +2,12 @@ # Declare constants at the top -GOVERNOR_TIMELOCK_ADDRESS = 0xDeployedGovernorTimelock -MARKET_UPDATE_MULTISIG = 0xDeployedMarketUpdateMultisig -PROPOSAL_GUARDIAN_ADDRESS = 0xDeployedProposalGuardian -MARKET_ADMIN_TIMELOCK_ADDRESS = 0xDeployedComputedTimelock -MARKET_UPDATE_PROPOSER = 0xDeployedComputedProposer -CONFIGURATOR = 0xDeployedComputedConfigurator -COMET_PROXY_ADMIN = 0xDeployedComputedProxyAdmin -MARKET_ADMIN_PERMISSION_CHECKER = 0xDeployedComputedMarketAdminPermissionChecker +MARKET_UPDATE_MULTISIG = 0x7e14050080306cd36b47DE61ce604b3a1EC70c4e +MARKET_ADMIN_TIMELOCK_ADDRESS = 0x81Bc6016Fa365bfE929a51Eec9217B441B598eC6 +MARKET_UPDATE_PROPOSER = 0xB6Ef3AC71E9baCF1F4b9426C149d855Bfc4415F9 +CONFIGURATOR_IMPL = 0x371DB45c7ee248dAFf4Dc1FFB67A20faa0ecFE02 +COMET_PROXY_ADMIN = 0x24D86Da09C4Dd64e50dB7501b0f695d030f397aF +MARKET_ADMIN_PERMISSION_CHECKER = 0x62DD0452411113404cf9a7fE88A5E6E86f9B71a6 SOLIDITY_COMPILER_VERSION = "0.8.15" SENDER = "0x470579d16401a36BF63b1428eaA7189FBdE5Fee9" @@ -54,7 +52,7 @@ verify-MarketUpdateTimelock: --chain-id $(CHAIN_ID) \ --compiler-version $(SOLIDITY_COMPILER_VERSION) \ --optimizer-runs 200 \ - --constructor-args $(shell cast abi-encode "constructor(address,uint256)" $(SENDER) 360000) \ + --constructor-args $(shell cast abi-encode "constructor(address,uint256)" $(SENDER) 172800) \ --etherscan-api-key $(ETHERSCAN_API_KEY) \ --watch \ --via-ir \ @@ -68,7 +66,7 @@ verify-MarketUpdateProposer: --chain-id $(CHAIN_ID) \ --compiler-version $(SOLIDITY_COMPILER_VERSION) \ --optimizer-runs 200 \ - --constructor-args $(shell cast abi-encode "constructor(address,address,address,address)" $(SENDER) $(MARKET_UPDATE_MULTISIG) $(PROPOSAL_GUARDIAN_ADDRESS) $(MARKET_ADMIN_TIMELOCK_ADDRESS)) \ + --constructor-args $(shell cast abi-encode "constructor(address,address,address,address)" $(SENDER) $(MARKET_UPDATE_MULTISIG) 0x0000000000000000000000000000000000000000 $(MARKET_ADMIN_TIMELOCK_ADDRESS)) \ --etherscan-api-key $(ETHERSCAN_API_KEY) \ --watch \ --via-ir \ @@ -99,7 +97,7 @@ verify-Configurator: --etherscan-api-key $(ETHERSCAN_API_KEY) \ --watch \ --via-ir \ - ${CONFIGURATOR} \ + ${CONFIGURATOR_IMPL} \ contracts/Configurator.sol:Configurator # Verifying MarketAdminPermissionChecker diff --git a/deployments/scroll/usdc/migrations/1728988057_gov_market_updates.ts b/deployments/scroll/usdc/migrations/1728988057_gov_market_updates.ts new file mode 100644 index 00000000..e60e757d --- /dev/null +++ b/deployments/scroll/usdc/migrations/1728988057_gov_market_updates.ts @@ -0,0 +1,173 @@ +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { + MarketAdminPermissionChecker, + MarketUpdateProposer, + MarketUpdateTimelock, + CometProxyAdmin, + Configurator, +} from './../../../../build/types'; +import { expect } from 'chai'; +import { exp, proposal } from '../../../../src/deploy'; + +interface Vars {} + +const marketAdminAddress = '0x7e14050080306cd36b47DE61ce604b3a1EC70c4e'; + +const localTimelockAddress = '0xF6013e80E9e6AC211Cc031ad1CE98B3Aa20b73E4'; + +const marketUpdateTimelockAddress = '0x81Bc6016Fa365bfE929a51Eec9217B441B598eC6'; +const marketUpdateProposerAddress = '0xB6Ef3AC71E9baCF1F4b9426C149d855Bfc4415F9'; +const newConfiguratorImplementationAddress = '0x371DB45c7ee248dAFf4Dc1FFB67A20faa0ecFE02'; +const newCometProxyAdminAddress = '0x24D86Da09C4Dd64e50dB7501b0f695d030f397aF'; +const marketAdminPermissionCheckerAddress = '0x62DD0452411113404cf9a7fE88A5E6E86f9B71a6'; + +const communityMultiSigAddress = '0x0747a435b8a60070A7a111D015046d765098e4cc'; + +const cometProxyAdminOldAddress = '0x87A27b91f4130a25E9634d23A5B8E05e342bac50'; +const configuratorProxyAddress = '0xECAB0bEEa3e5DEa0c35d3E69468EAC20098032D7'; +const cometProxyAddress = '0xB2f97c1Bd3bf02f5e74d13f02E3e26F93D77CE44'; + +export default migration('1728988057_gov_market_updates', { + prepare: async () => { + return {}; + }, + + enact: async ( + deploymentManager: DeploymentManager, + govDeploymentManager: DeploymentManager, + ) => { + const trace = deploymentManager.tracer(); + const ethers = deploymentManager.hre.ethers; + const { utils } = ethers; + + const { bridgeReceiver } = await deploymentManager.getContracts(); + + const { scrollMessenger, governor } = + await govDeploymentManager.getContracts(); + + + const changeProxyAdminForCometProxyCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [cometProxyAddress, newCometProxyAdminAddress] + ); + + const changeProxyAdminForConfiguratorProxyCalldata = + utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyAddress, newCometProxyAdminAddress] + ); + + const upgradeConfiguratorProxyCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyAddress, newConfiguratorImplementationAddress] + ); + + const setMarketAdminPermissionCheckerForConfiguratorProxyCalldata = + utils.defaultAbiCoder.encode( + ['address'], + [marketAdminPermissionCheckerAddress] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [ + cometProxyAdminOldAddress, + cometProxyAdminOldAddress, + newCometProxyAdminAddress, + configuratorProxyAddress, + ], + [0, 0, 0, 0], + [ + 'changeProxyAdmin(address,address)', + 'changeProxyAdmin(address,address)', + 'upgrade(address,address)', + 'setMarketAdminPermissionChecker(address)', + ], + [ + changeProxyAdminForCometProxyCalldata, + changeProxyAdminForConfiguratorProxyCalldata, + upgradeConfiguratorProxyCalldata, + setMarketAdminPermissionCheckerForConfiguratorProxyCalldata, + ], + ] + ); + + const actions = [ + { + contract: scrollMessenger, + signature: 'sendMessage(address,uint256,bytes,uint256)', + args: [bridgeReceiver.address, 0, l2ProposalData, 6_000_000], + value: exp(0.1, 18), + }, + ]; + + const description = + 'Governance proposal with actions to change proxy admins, upgrade the configurator, and set the market admin and related roles.'; + const txn = await govDeploymentManager.retry(async () => + trace(await governor.propose(...(await proposal(actions, description)))) + ); + + const event = txn.events.find((event) => event.event === 'ProposalCreated'); + + const [proposalId] = event.args; + + trace(`Created proposal ${proposalId}.`); + }, + + async enacted(deploymentManager: DeploymentManager): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + await deploymentManager.spider(); + const tracer = deploymentManager.tracer(); + const ethers = deploymentManager.hre.ethers; + + const { configurator } = await deploymentManager.getContracts(); + + const marketAdminPermissionChecker = (await ethers.getContractAt( + 'MarketAdminPermissionChecker', + marketAdminPermissionCheckerAddress + )) as MarketAdminPermissionChecker; + + const marketUpdateTimelock = (await ethers.getContractAt( + 'MarketUpdateTimelock', + marketUpdateTimelockAddress + )) as MarketUpdateTimelock; + + const marketUpdateProposer = (await ethers.getContractAt( + 'MarketUpdateProposer', + marketUpdateProposerAddress + )) as MarketUpdateProposer; + + const cometProxyAdminNew = (await ethers.getContractAt( + 'CometProxyAdmin', + newCometProxyAdminAddress + )) as CometProxyAdmin; + + expect(configurator.address).to.be.equal(configuratorProxyAddress); + expect(await (configurator as Configurator).governor()).to.be.equal(localTimelockAddress); + expect(await (configurator as Configurator).marketAdminPermissionChecker()).to.be.equal(marketAdminPermissionCheckerAddress); + + expect(await cometProxyAdminNew.marketAdminPermissionChecker()).to.be.equal(marketAdminPermissionChecker.address); + expect(await cometProxyAdminNew.owner()).to.be.equal(localTimelockAddress); + + expect(await marketAdminPermissionChecker.marketAdmin()).to.be.equal(marketUpdateTimelockAddress); + expect(await marketAdminPermissionChecker.owner()).to.be.equal(localTimelockAddress); + expect(await marketAdminPermissionChecker.marketAdminPauseGuardian()).to.be.equal(communityMultiSigAddress); + + expect(await marketUpdateTimelock.marketUpdateProposer()).to.be.equal(marketUpdateProposer.address); + expect(await marketUpdateTimelock.governor()).to.be.equal(localTimelockAddress); + expect(await marketUpdateTimelock.delay()).to.be.equal(2 * 24 * 60 * 60); + + expect(await marketUpdateProposer.governor()).to.be.equal(localTimelockAddress); + expect(await marketUpdateProposer.marketAdmin()).to.be.equal(marketAdminAddress); + + expect(await marketUpdateProposer.timelock()).to.be.equal(marketUpdateTimelock.address); + expect(await marketUpdateProposer.proposalGuardian()).to.be.equal(communityMultiSigAddress); + + tracer('All checks passed.'); + }, +}); diff --git a/forge/script/marketupdates/DeployContracts.s.sol b/forge/script/marketupdates/DeployContracts.s.sol index 586d553c..22ad7849 100644 --- a/forge/script/marketupdates/DeployContracts.s.sol +++ b/forge/script/marketupdates/DeployContracts.s.sol @@ -10,27 +10,17 @@ import "@comet-contracts/CometProxyAdmin.sol"; import "@comet-contracts/marketupdates/MarketAdminPermissionChecker.sol"; import "@comet-contracts/Create2DeployerInterface.sol"; import "./helpers/MarketUpdateAddresses.sol"; +import "./helpers/MarketUpdateContractsDeployer.sol"; import "./helpers/ChainAddresses.sol"; contract DeployContracts is Script { address public deployedWalletAddress; address constant public create2DeployerAddress = 0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2; + address constant public ZER0_ADDRESS_MARKET_UPDATE_PROPOSAL_GUARDIAN = address(0); + address constant public ZER0_ADDRESS_MARKET_ADMIN_PAUSE_GUARDIAN = address(0); + address constant public INITIAL_ADDRESS_MARKET_UPDATE_MULTI_SIG = address(0x7e14050080306cd36b47DE61ce604b3a1EC70c4e); - struct DeployedContracts { - address marketUpdateTimelock; - address marketUpdateProposer; - address newCometProxyAdmin; - address newConfiguratorImplementation; - address marketAdminPermissionChecker; - } - - struct ContractDeploymentParams { - bytes creationCode; - bytes constructorArgs; - bytes expectedRuntimeCode; - string contractName; - } function run() external { uint256 passedChainId = vm.envUint("CHAIN_ID"); @@ -49,14 +39,15 @@ contract DeployContracts is Script { console.log("Broadcasting transaction with deployer: ", deployer); - bytes32 salt = keccak256(abi.encodePacked("Salt-34")); + bytes32 salt = keccak256(abi.encodePacked(vm.envString("SALT"))); /// Call library function - DeployedContracts memory deployedContracts = deployContracts( + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer._deployContracts( salt, - MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS, - MarketUpdateAddresses.MARKET_ADMIN_PAUSE_GUARDIAN_ADDRESS, - MarketUpdateAddresses.MARKET_UPDATE_PROPOSAL_GUARDIAN_ADDRESS, + msg.sender, + chainAddresses.marketAdmin, + chainAddresses.marketUpdatePauseGuardian, + chainAddresses.marketUpdateProposalGuardian, chainAddresses.governorTimelockAddress ); @@ -69,155 +60,4 @@ contract DeployContracts is Script { vm.stopBroadcast(); } - - function deployContracts( - bytes32 salt, - address marketUpdateMultiSig, // TODO: Check this is properly used - address marketAdminPauseGuardianAddress, // TODO: Check this is properly used - address marketUpdateProposalGuardianAddress, // TODO: Check this is properly used - address localTimelockAddress - ) public returns (DeployedContracts memory) { - - ICreate2Deployer create2Deployer = ICreate2Deployer(create2DeployerAddress); - - // Prepare deployment parameters for each contract - ContractDeploymentParams memory marketUpdateTimelockParams = ContractDeploymentParams({ - creationCode: type(MarketUpdateTimelock).creationCode, - constructorArgs: abi.encode(msg.sender, 360000), // TODO: add comment on how 360000 is calculated - expectedRuntimeCode: type(MarketUpdateTimelock).runtimeCode, - contractName: "MarketUpdateTimelock" - }); - - address computedMarketUpdateTimelockAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateTimelockParams); - - console.log("Current Governor of timelock", MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).governor()); - - ContractDeploymentParams memory marketUpdateProposerParams = ContractDeploymentParams({ - creationCode: type(MarketUpdateProposer).creationCode, - constructorArgs: abi.encode( - msg.sender, - marketUpdateMultiSig, - marketUpdateProposalGuardianAddress, - computedMarketUpdateTimelockAddress - ), - expectedRuntimeCode: type(MarketUpdateProposer).runtimeCode, - contractName: "MarketUpdateProposer" - }); - - address computedMarketUpdateProposerAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateProposerParams); - MarketUpdateProposer(computedMarketUpdateProposerAddress).setGovernor(localTimelockAddress); - - MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setMarketUpdateProposer(computedMarketUpdateProposerAddress); - MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setGovernor(localTimelockAddress); - - ContractDeploymentParams memory configuratorParams = ContractDeploymentParams({ - creationCode: type(Configurator).creationCode, - constructorArgs: "", - expectedRuntimeCode: type(Configurator).runtimeCode, - contractName: "Configurator" - }); - - address computedConfiguratorAddress = deployContractWithCreate2(create2Deployer, salt, configuratorParams); - - ContractDeploymentParams memory cometProxyAdminParams = ContractDeploymentParams({ - creationCode: type(CometProxyAdmin).creationCode, - constructorArgs: abi.encode(msg.sender), - expectedRuntimeCode: type(CometProxyAdmin).runtimeCode, - contractName: "CometProxyAdmin" - }); - - address computedCometProxyAdminAddress = deployContractWithCreate2(create2Deployer, salt, cometProxyAdminParams); - CometProxyAdmin(computedCometProxyAdminAddress).transferOwnership(localTimelockAddress); - - console.log("Owner of cometProxyAdmin: ", CometProxyAdmin(computedCometProxyAdminAddress).owner()); - - ContractDeploymentParams memory marketAdminPermissionCheckerParams = ContractDeploymentParams({ - creationCode: type(MarketAdminPermissionChecker).creationCode, - constructorArgs: abi.encode(msg.sender, marketUpdateMultiSig, address(0)), - expectedRuntimeCode: type(MarketAdminPermissionChecker).runtimeCode, - contractName: "MarketAdminPermissionChecker" - }); - - address computedMarketAdminPermissionCheckerAddress = deployContractWithCreate2(create2Deployer, salt, marketAdminPermissionCheckerParams); - MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).transferOwnership(localTimelockAddress); - - return DeployedContracts({ - marketUpdateTimelock: computedMarketUpdateTimelockAddress, - marketUpdateProposer: computedMarketUpdateProposerAddress, - newCometProxyAdmin: computedCometProxyAdminAddress, - newConfiguratorImplementation: computedConfiguratorAddress, - marketAdminPermissionChecker: computedMarketAdminPermissionCheckerAddress - }); - } - - function deployContractWithCreate2( - ICreate2Deployer create2Deployer, - bytes32 salt, - ContractDeploymentParams memory params - ) internal returns (address) { - bytes memory bytecode = abi.encodePacked(params.creationCode, params.constructorArgs); - address computedAddress = create2Deployer.computeAddress(salt, keccak256(bytecode)); - checkOrDeployAndCompareBytecodes(create2Deployer, salt, bytecode, computedAddress, params.expectedRuntimeCode); - return computedAddress; - } - - function checkOrDeployAndCompareBytecodes( - ICreate2Deployer create2Deployer, - bytes32 salt, - bytes memory actualBytecode, - address computedAddress, - bytes memory expectedBytecode - ) internal { - uint256 contractCodeSize = getContractCodeSizeAtAddress(computedAddress); - - if (contractCodeSize > 0) { - bytes memory deployedBytecode = verifyDeployedBytecode(computedAddress, contractCodeSize); - - require( - keccak256(deployedBytecode) == keccak256(expectedBytecode), - "Deployed bytecode does not match the expected bytecode" - ); - } else { - deployAndCompareBytecodes(create2Deployer, salt, actualBytecode, computedAddress, expectedBytecode); - } - } - - function deployAndCompareBytecodes( - ICreate2Deployer create2Deployer, - bytes32 salt, - bytes memory actualBytecode, - address computedAddress, - bytes memory expectedBytecode - ) internal { - create2Deployer.deploy(0, salt, actualBytecode); - - uint256 size = getContractCodeSizeAtAddress(computedAddress); - require(size > 0, "No contract deployed at this address"); - - bytes memory deployedBytecode = new bytes(size); - assembly { - extcodecopy(computedAddress, add(deployedBytecode, 0x20), 0, size) - } - - require( - keccak256(deployedBytecode) == keccak256(expectedBytecode), - "Deployed bytecode does not match the expected bytecode" - ); - } - - function getContractCodeSizeAtAddress(address contractAddress) internal view returns (uint256) { - uint256 size; - assembly { - size := extcodesize(contractAddress) - } - return size; - } - - function verifyDeployedBytecode(address computedAddress, uint256 contractCodeSize) internal view returns (bytes memory) { - bytes memory deployedBytecode = new bytes(contractCodeSize); - assembly { - extcodecopy(computedAddress, add(deployedBytecode, 0x20), 0, contractCodeSize) - } - return deployedBytecode; - } } diff --git a/forge/script/marketupdates/helpers/ChainAddresses.sol b/forge/script/marketupdates/helpers/ChainAddresses.sol index 7058b095..61f6ecad 100644 --- a/forge/script/marketupdates/helpers/ChainAddresses.sol +++ b/forge/script/marketupdates/helpers/ChainAddresses.sol @@ -9,6 +9,7 @@ library ChainAddresses { address cometProxyAdminAddress; address marketUpdatePauseGuardian; address marketUpdateProposalGuardian; + address marketAdmin; } enum Chain { @@ -28,92 +29,124 @@ library ChainAddresses { address constant public MAINNET_CONFIGURATOR_PROXY = 0x316f9708bB98af7dA9c68C1C3b5e79039cD336E3; // See - https://etherscan.io/address/0x316f9708bB98af7dA9c68C1C3b5e79039cD336E3 address constant public MAINNET_COMET_PROXY_ADMIN = 0x1EC63B5883C3481134FD50D5DAebc83Ecd2E8779; // See - https://etherscan.io/address/0x1EC63B5883C3481134FD50D5DAebc83Ecd2E8779 + address constant public MAINNET_MARKET_ADMIN = 0xA1C7b6d8b4DeD5ee46330C865cC8aeCfB13c8b65; // See - https://etherscan.io/address/0xA1C7b6d8b4DeD5ee46330C865cC8aeCfB13c8b65 + address constant public MAINNET_MARKET_UPDATE_PAUSE_GUARDIAN = 0xbbf3f1421D886E9b2c5D716B5192aC998af2012c ; // See - pauseGuardian in https://etherscan.io/address/0xc3d688B66703497DAA19211EEdff47f25384cdc3#readProxyContract + address constant public MAINNET_MARKET_UPDATE_PROPOSAL_GUARDIAN = 0xbbf3f1421D886E9b2c5D716B5192aC998af2012c ; // See - https://etherscan.io/address/0xc3d688B66703497DAA19211EEdff47f25384cdc3#readProxyContract + + // Polygon addresses address constant public POLYGON_LOCAL_TIMELOCK = 0xCC3E7c85Bb0EE4f09380e041fee95a0caeDD4a02; // See - https://polygonscan.com/address/0xCC3E7c85Bb0EE4f09380e041fee95a0caeDD4a02 address constant public POLYGON_CONFIGURATOR_PROXY = 0x83E0F742cAcBE66349E3701B171eE2487a26e738; // See - https://polygonscan.com/address/0x83E0F742cAcBE66349E3701B171eE2487a26e738 address constant public POLYGON_COMET_PROXY_ADMIN = 0xd712ACe4ca490D4F3E92992Ecf3DE12251b975F9; // See - https://polygonscan.com/address/0xd712ACe4ca490D4F3E92992Ecf3DE12251b975F9 address constant public POLYGON_BRIDGE_RECEIVER = 0x18281dfC4d00905DA1aaA6731414EABa843c468A; // See - https://polygonscan.com/address/0x18281dfC4d00905DA1aaA6731414EABa843c468A + address constant public POLYGON_MARKET_ADMIN = 0x7e14050080306cd36b47DE61ce604b3a1EC70c4e; // See - https://polygonscan.com/address/0x7e14050080306cd36b47DE61ce604b3a1EC70c4e + address constant public POLYGON_MARKET_UPDATE_PAUSE_GUARDIAN = 0x8Ab717CAC3CbC4934E63825B88442F5810aAF6e5 ; // See - pauseGuardian in https://polygonscan.com/address/0x8Ab717CAC3CbC4934E63825B88442F5810aAF6e5#readProxyContract + address constant public POLYGON_MARKET_UPDATE_PROPOSAL_GUARDIAN = 0x8Ab717CAC3CbC4934E63825B88442F5810aAF6e5 ; // See - https://polygonscan.com/address/0x8Ab717CAC3CbC4934E63825B88442F5810aAF6e5#readProxyContract + // Arbitrum addresses address constant public ARBITRUM_LOCAL_TIMELOCK = 0x3fB4d38ea7EC20D91917c09591490Eeda38Cf88A; // See - https://arbiscan.io/address/0x3fB4d38ea7EC20D91917c09591490Eeda38Cf88A address constant public ARBITRUM_CONFIGURATOR_PROXY = 0xb21b06D71c75973babdE35b49fFDAc3F82Ad3775; // See - https://arbiscan.io/address/0xb21b06D71c75973babdE35b49fFDAc3F82Ad3775 address constant public ARBITRUM_COMET_PROXY_ADMIN = 0xD10b40fF1D92e2267D099Da3509253D9Da4D715e; // See - https://arbiscan.io/address/0xD10b40fF1D92e2267D099Da3509253D9Da4D715e address constant public ARBITRUM_BRIDGE_RECEIVER = 0x42480C37B249e33aABaf4c22B20235656bd38068; // See - https://arbiscan.io/address/0x42480C37B249e33aABaf4c22B20235656bd38068 + address constant public ARBITRUM_MARKET_ADMIN = 0x7e14050080306cd36b47DE61ce604b3a1EC70c4e; // See - https://arbiscan.io/address/0x7e14050080306cd36b47DE61ce604b3a1EC70c4e + address constant public ARBITRUM_MARKET_UPDATE_PAUSE_GUARDIAN = 0x78E6317DD6D43DdbDa00Dce32C2CbaFc99361a9d; // See - https://arbiscan.io/address/0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07#readProxyContract + address constant public ARBITRUM_MARKET_UPDATE_PROPOSAL_GUARDIAN = 0x78E6317DD6D43DdbDa00Dce32C2CbaFc99361a9d; // See - https://arbiscan.io/address/0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07#readProxyContract + // Base addresses address constant public BASE_LOCAL_TIMELOCK = 0xCC3E7c85Bb0EE4f09380e041fee95a0caeDD4a02; // See - https://basescan.org/address/0xCC3E7c85Bb0EE4f09380e041fee95a0caeDD4a02 address constant public BASE_CONFIGURATOR_PROXY = 0x45939657d1CA34A8FA39A924B71D28Fe8431e581; // See - https://basescan.org/address/0x45939657d1CA34A8FA39A924B71D28Fe8431e581 address constant public BASE_COMET_PROXY_ADMIN = 0xbdE8F31D2DdDA895264e27DD990faB3DC87b372d; // See - https://basescan.org/address/0xbdE8F31D2DdDA895264e27DD990faB3DC87b372d address constant public BASE_BRIDGE_RECEIVER = 0x18281dfC4d00905DA1aaA6731414EABa843c468A; // See - https://basescan.org/address/0x18281dfC4d00905DA1aaA6731414EABa843c468A + address constant public BASE_MARKET_ADMIN = 0x7e14050080306cd36b47DE61ce604b3a1EC70c4e; + address constant public BASE_MARKET_UPDATE_PAUSE_GUARDIAN = 0x3cb4653F3B45F448D9100b118B75a1503281d2ee; // See - https://basescan.org/address/0x46e6b214b524310239732D51387075E0e70970bf#readProxyContract + address constant public BASE_MARKET_UPDATE_PROPOSAL_GUARDIAN = 0x3cb4653F3B45F448D9100b118B75a1503281d2ee; // See - https://basescan.org/address/0x46e6b214b524310239732D51387075E0e70970bf#readProxyContract + // Scroll addresses address constant public SCROLL_LOCAL_TIMELOCK = 0xF6013e80E9e6AC211Cc031ad1CE98B3Aa20b73E4; // See - https://scrollscan.com/address/0xF6013e80E9e6AC211Cc031ad1CE98B3Aa20b73E4 address constant public SCROLL_CONFIGURATOR_PROXY = 0xECAB0bEEa3e5DEa0c35d3E69468EAC20098032D7; // See - https://scrollscan.com/address/0xECAB0bEEa3e5DEa0c35d3E69468EAC20098032D7 address constant public SCROLL_COMET_PROXY_ADMIN = 0x87A27b91f4130a25E9634d23A5B8E05e342bac50; // See - https://scrollscan.com/address/0x87A27b91f4130a25E9634d23A5B8E05e342bac50 address constant public SCROLL_BRIDGE_RECEIVER = 0xC6bf5A64896D679Cf89843DbeC6c0f5d3C9b610D; // See - https://scrollscan.com/address/0xC6bf5A64896D679Cf89843DbeC6c0f5d3C9b610D + address constant public SCROLL_MARKET_ADMIN = 0x7e14050080306cd36b47DE61ce604b3a1EC70c4e; // See - https://scrollscan.com/address/0x7e14050080306cd36b47DE61ce604b3a1EC70c4e + address constant public SCROLL_MARKET_UPDATE_PAUSE_GUARDIAN = 0x0747a435b8a60070A7a111D015046d765098e4cc; // See - https://scrollscan.com/address/0xB2f97c1Bd3bf02f5e74d13f02E3e26F93D77CE44#readProxyContract + address constant public SCROLL_MARKET_UPDATE_PROPOSAL_GUARDIAN = 0x0747a435b8a60070A7a111D015046d765098e4cc; // See - https://scrollscan.com/address/0xB2f97c1Bd3bf02f5e74d13f02E3e26F93D77CE44#readProxyContract + // Optimism addresses address constant public OPTIMISM_LOCAL_TIMELOCK = 0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07; // See - https://optimistic.etherscan.io/address/0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07 address constant public OPTIMISM_CONFIGURATOR_PROXY = 0x84E93EC6170ED630f5ebD89A1AAE72d4F63f2713; // See - https://optimistic.etherscan.io/address/0x84E93EC6170ED630f5ebD89A1AAE72d4F63f2713 address constant public OPTIMISM_COMET_PROXY_ADMIN = 0x3C30B5a5A04656565686f800481580Ac4E7ed178; // See - https://optimistic.etherscan.io/address/0x3C30B5a5A04656565686f800481580Ac4E7ed178 address constant public OPTIMISM_BRIDGE_RECEIVER = 0xC3a73A70d1577CD5B02da0bA91C0Afc8fA434DAF; // See - https://optimistic.etherscan.io/address/0x18281dfC4d00905DA1aaA6731414EABa843c468A + address constant public OPTIMISM_MARKET_ADMIN = 0x7e14050080306cd36b47DE61ce604b3a1EC70c4e; // See - https://optimistic.etherscan.io/address/0x7e14050080306cd36b47DE61ce604b3a1EC70c4e + address constant public OPTIMISM_MARKET_UPDATE_PAUSE_GUARDIAN = 0x3fFd6c073a4ba24a113B18C8F373569640916A45; // See - https://optimistic.etherscan.io/address/0xE36A30D249f7761327fd973001A32010b521b6Fd#readProxyContract + address constant public OPTIMISM_MARKET_UPDATE_PROPOSAL_GUARDIAN = 0x3fFd6c073a4ba24a113B18C8F373569640916A45; // See - https://optimistic.etherscan.io/address/0xE36A30D249f7761327fd973001A32010b521b6Fd#readProxyContract + function getChainAddresses(Chain chain) internal pure returns (ChainAddressesStruct memory) { if (chain == Chain.ETHEREUM) { return ChainAddressesStruct({ governorTimelockAddress: MAINNET_GOVERNOR_TIMELOCK, configuratorProxyAddress: MAINNET_CONFIGURATOR_PROXY, cometProxyAdminAddress: MAINNET_COMET_PROXY_ADMIN, - marketUpdatePauseGuardian: address(0), - marketUpdateProposalGuardian: address(0) + marketUpdatePauseGuardian: MAINNET_MARKET_UPDATE_PAUSE_GUARDIAN, + marketUpdateProposalGuardian: MAINNET_MARKET_UPDATE_PROPOSAL_GUARDIAN, + marketAdmin: MAINNET_MARKET_ADMIN }); } else if (chain == Chain.POLYGON) { return ChainAddressesStruct({ governorTimelockAddress: POLYGON_LOCAL_TIMELOCK, configuratorProxyAddress: POLYGON_CONFIGURATOR_PROXY, cometProxyAdminAddress: POLYGON_COMET_PROXY_ADMIN, - marketUpdatePauseGuardian: address(0), - marketUpdateProposalGuardian: address(0) + marketUpdatePauseGuardian: POLYGON_MARKET_UPDATE_PAUSE_GUARDIAN, + marketUpdateProposalGuardian: POLYGON_MARKET_UPDATE_PROPOSAL_GUARDIAN, + marketAdmin: POLYGON_MARKET_ADMIN }); } else if (chain == Chain.ARBITRUM) { return ChainAddressesStruct({ governorTimelockAddress: ARBITRUM_LOCAL_TIMELOCK, configuratorProxyAddress: ARBITRUM_CONFIGURATOR_PROXY, cometProxyAdminAddress: ARBITRUM_COMET_PROXY_ADMIN, - marketUpdatePauseGuardian: address(0), - marketUpdateProposalGuardian: address(0) + marketUpdatePauseGuardian: ARBITRUM_MARKET_UPDATE_PAUSE_GUARDIAN, + marketUpdateProposalGuardian: ARBITRUM_MARKET_UPDATE_PROPOSAL_GUARDIAN, + marketAdmin: ARBITRUM_MARKET_ADMIN }); } else if (chain == Chain.BASE) { return ChainAddressesStruct({ governorTimelockAddress: BASE_LOCAL_TIMELOCK, configuratorProxyAddress: BASE_CONFIGURATOR_PROXY, cometProxyAdminAddress: BASE_COMET_PROXY_ADMIN, - marketUpdatePauseGuardian: address(0), - marketUpdateProposalGuardian: address(0) + marketUpdatePauseGuardian: BASE_MARKET_UPDATE_PAUSE_GUARDIAN, + marketUpdateProposalGuardian: BASE_MARKET_UPDATE_PROPOSAL_GUARDIAN, + marketAdmin: BASE_MARKET_ADMIN }); } else if (chain == Chain.SCROLL) { return ChainAddressesStruct({ governorTimelockAddress: SCROLL_LOCAL_TIMELOCK, configuratorProxyAddress: SCROLL_CONFIGURATOR_PROXY, cometProxyAdminAddress: SCROLL_COMET_PROXY_ADMIN, - marketUpdatePauseGuardian: address(0), - marketUpdateProposalGuardian: address(0) + marketUpdatePauseGuardian: SCROLL_MARKET_UPDATE_PAUSE_GUARDIAN, + marketUpdateProposalGuardian: SCROLL_MARKET_UPDATE_PROPOSAL_GUARDIAN, + marketAdmin: SCROLL_MARKET_ADMIN }); } else if (chain == Chain.OPTIMISM) { return ChainAddressesStruct({ governorTimelockAddress: OPTIMISM_LOCAL_TIMELOCK, configuratorProxyAddress: OPTIMISM_CONFIGURATOR_PROXY, cometProxyAdminAddress: OPTIMISM_COMET_PROXY_ADMIN, - marketUpdatePauseGuardian: address(0), - marketUpdateProposalGuardian: address(0) + marketUpdatePauseGuardian: OPTIMISM_MARKET_UPDATE_PAUSE_GUARDIAN, + marketUpdateProposalGuardian: OPTIMISM_MARKET_UPDATE_PROPOSAL_GUARDIAN, + marketAdmin: OPTIMISM_MARKET_ADMIN }); } else if (chain == Chain.OP_SEPOLIA) { return ChainAddressesStruct({ governorTimelockAddress: OPTIMISM_LOCAL_TIMELOCK, configuratorProxyAddress: OPTIMISM_CONFIGURATOR_PROXY, cometProxyAdminAddress: OPTIMISM_COMET_PROXY_ADMIN, - marketUpdatePauseGuardian: address(0), - marketUpdateProposalGuardian: address(0) + marketUpdatePauseGuardian: OPTIMISM_MARKET_UPDATE_PAUSE_GUARDIAN, + marketUpdateProposalGuardian: OPTIMISM_MARKET_UPDATE_PROPOSAL_GUARDIAN, + marketAdmin: OPTIMISM_MARKET_ADMIN }); } else if (chain == Chain.MAINNET_SEPOLIA) { return ChainAddressesStruct({ @@ -121,7 +154,8 @@ library ChainAddresses { configuratorProxyAddress: MAINNET_CONFIGURATOR_PROXY, cometProxyAdminAddress: MAINNET_COMET_PROXY_ADMIN, marketUpdatePauseGuardian: address(0), - marketUpdateProposalGuardian: address(0) + marketUpdateProposalGuardian: address(0), + marketAdmin: address(0) }); } else { revert("MarketUpdateAddresses: Chain not supported"); diff --git a/forge/script/marketupdates/helpers/GovernanceHelper.sol b/forge/script/marketupdates/helpers/GovernanceHelper.sol index 4f25feb0..d2b9b9fb 100644 --- a/forge/script/marketupdates/helpers/GovernanceHelper.sol +++ b/forge/script/marketupdates/helpers/GovernanceHelper.sol @@ -38,7 +38,7 @@ library GovernanceHelper { // Dynamically allocate arrays based on the number of markets uint256 numMarkets = addresses.markets.length; - uint256 totalTargets = 6 + numMarkets; // 6 fixed operations + numMarkets + uint256 totalTargets = 3 + numMarkets; // 6 fixed operations + numMarkets address[] memory targets = new address[](totalTargets); uint256[] memory values = new uint256[](totalTargets); string[] memory signatures = new string[](totalTargets); @@ -67,25 +67,25 @@ library GovernanceHelper { signatures[offset + 1] = "upgrade(address,address)"; calldatas[offset + 1] = abi.encode(configuratorProxyAddress, configuratorNewAddress); - // Set Market Admin - targets[offset + 2] = marketAdminPermissionCheckerAddress; - signatures[offset + 2] = "setMarketAdmin(address)"; - calldatas[offset + 2] = abi.encode(marketUpdateTimelockAddress); - +// // Set Market Admin +// targets[offset + 2] = marketAdminPermissionCheckerAddress; +// signatures[offset + 2] = "setMarketAdmin(address)"; +// calldatas[offset + 2] = abi.encode(marketUpdateTimelockAddress); +// // Set Market Admin Permission Checker on the configurator - targets[offset + 3] = configuratorProxyAddress; - signatures[offset + 3] = "setMarketAdminPermissionChecker(address)"; - calldatas[offset + 3] = abi.encode(marketAdminPermissionCheckerAddress); - - // Set Market Admin Permission Checker on the new comet proxy admin - targets[offset + 4] = cometProxyAdminNewAddress; - signatures[offset + 4] = "setMarketAdminPermissionChecker(address)"; - calldatas[offset + 4] = abi.encode(marketAdminPermissionCheckerAddress); - - // Set Market Update Proposer - targets[offset + 5] = marketUpdateTimelockAddress; - signatures[offset + 5] = "setMarketUpdateProposer(address)"; - calldatas[offset + 5] = abi.encode(marketUpdateProposerAddress); + targets[offset + 2] = configuratorProxyAddress; + signatures[offset + 2] = "setMarketAdminPermissionChecker(address)"; + calldatas[offset + 2] = abi.encode(marketAdminPermissionCheckerAddress); +// +// // Set Market Admin Permission Checker on the new comet proxy admin +// targets[offset + 4] = cometProxyAdminNewAddress; +// signatures[offset + 4] = "setMarketAdminPermissionChecker(address)"; +// calldatas[offset + 4] = abi.encode(marketAdminPermissionCheckerAddress); +// +// // Set Market Update Proposer +// targets[offset + 5] = marketUpdateTimelockAddress; +// signatures[offset + 5] = "setMarketUpdateProposer(address)"; +// calldatas[offset + 5] = abi.encode(marketUpdateProposerAddress); return ProposalRequest(targets, values, signatures, calldatas); } @@ -123,8 +123,8 @@ library GovernanceHelper { moveProposalToExecution(vm, proposalId); } - function createAndPassMarketUpdateProposal(Vm vm, ProposalRequest memory proposalRequest, string memory description, address marketUpdateProposer) public { - vm.startPrank(MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS); + function createAndPassMarketUpdateProposal(Vm vm, address marketAdmin, ProposalRequest memory proposalRequest, string memory description, address marketUpdateProposer) public { + vm.startPrank(marketAdmin); MarketUpdateProposer(marketUpdateProposer).propose(proposalRequest.targets, proposalRequest.values, proposalRequest.signatures, proposalRequest.calldatas, description); // Fast forward by 5 days @@ -135,8 +135,8 @@ library GovernanceHelper { vm.stopPrank(); } - function createAndPassMarketUpdateProposalL2(Vm vm, ProposalRequest memory proposalRequest, string memory description, address marketUpdateProposer) public { - vm.startPrank(MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS); + function createAndPassMarketUpdateProposalL2(Vm vm, address marketAdmin, ProposalRequest memory proposalRequest, string memory description, address marketUpdateProposer) public { + vm.startPrank(marketAdmin); MarketUpdateProposer(marketUpdateProposer).propose(proposalRequest.targets, proposalRequest.values, proposalRequest.signatures, proposalRequest.calldatas, description); // Fast forward by 5 days @@ -162,6 +162,7 @@ library GovernanceHelper { } function moveProposalToSucceed(Vm vm, uint proposalId) public { + console.log("Moving proposal to Succeeded"); require(governorBravo.state(proposalId) == IGovernorBravo.ProposalState.Active, "Proposal is not Active"); @@ -174,6 +175,7 @@ library GovernanceHelper { } function moveProposalToExecution(Vm vm, uint proposalId) public { + console.log("Moving proposal to Execution"); uint proposalEta = governorBravo.proposals(proposalId).eta; require(proposalEta != 0, "Proposal has not been queued"); diff --git a/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol b/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol index 4fef5a2d..76538508 100644 --- a/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol +++ b/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol @@ -14,6 +14,9 @@ import "@forge-std/src/Vm.sol"; library MarketUpdateContractsDeployer { address constant public create2DeployerAddress = 0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2; + address constant public ZER0_ADDRESS_MARKET_UPDATE_PROPOSAL_GUARDIAN = address(0); + address constant public ZER0_ADDRESS_MARKET_ADMIN_PAUSE_GUARDIAN = address(0); + address constant public INITIAL_ADDRESS_MARKET_UPDATE_MULTI_SIG = address(0x7e14050080306cd36b47DE61ce604b3a1EC70c4e); struct DeployedContracts { address marketUpdateTimelock; @@ -33,20 +36,45 @@ library MarketUpdateContractsDeployer { function deployContracts( Vm vm, bytes32 salt, - address marketUpdateMultiSig, // TODO: Check this is properly used - address marketAdminPauseGuardianAddress, // TODO: Check this is properly used - address marketUpdateProposalGuardianAddress, // TODO: Check this is properly used + address marketUpdateMultiSig, + address marketAdminPauseGuardianAddress, + address marketUpdateProposalGuardianAddress, address localTimelockAddress ) public returns (DeployedContracts memory) { console.log("Deploying contracts with sender", msg.sender); + vm.startBroadcast(msg.sender); + + DeployedContracts memory deployedContracts = _deployContracts( + salt, + msg.sender, + marketUpdateMultiSig, + marketAdminPauseGuardianAddress, + marketUpdateProposalGuardianAddress, + localTimelockAddress + ); + + vm.stopBroadcast(); + return deployedContracts; + } + + function _deployContracts( + bytes32 salt, + address msgSender, + address marketUpdateMultiSig, + address marketAdminPauseGuardianAddress, + address marketUpdateProposalGuardianAddress, + address localTimelockAddress + ) internal returns (DeployedContracts memory) { + console.log("Deploying contracts with sender", msgSender); + ICreate2Deployer create2Deployer = ICreate2Deployer(create2DeployerAddress); - vm.startBroadcast(msg.sender); + // Prepare deployment parameters for each contract ContractDeploymentParams memory marketUpdateTimelockParams = ContractDeploymentParams({ creationCode: type(MarketUpdateTimelock).creationCode, - constructorArgs: abi.encode(msg.sender, 360000), // TODO: add comment on how 360000 is calculated + constructorArgs: abi.encode(msgSender, 2 days), // 2 days expectedRuntimeCode: type(MarketUpdateTimelock).runtimeCode, contractName: "MarketUpdateTimelock" }); @@ -58,9 +86,9 @@ library MarketUpdateContractsDeployer { ContractDeploymentParams memory marketUpdateProposerParams = ContractDeploymentParams({ creationCode: type(MarketUpdateProposer).creationCode, constructorArgs: abi.encode( - msg.sender, - marketUpdateMultiSig, - marketUpdateProposalGuardianAddress, + msgSender, + INITIAL_ADDRESS_MARKET_UPDATE_MULTI_SIG, + ZER0_ADDRESS_MARKET_UPDATE_PROPOSAL_GUARDIAN, computedMarketUpdateTimelockAddress ), expectedRuntimeCode: type(MarketUpdateProposer).runtimeCode, @@ -68,6 +96,8 @@ library MarketUpdateContractsDeployer { }); address computedMarketUpdateProposerAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateProposerParams); + MarketUpdateProposer(computedMarketUpdateProposerAddress).setMarketAdmin(marketUpdateMultiSig); + MarketUpdateProposer(computedMarketUpdateProposerAddress).setProposalGuardian(marketUpdateProposalGuardianAddress); MarketUpdateProposer(computedMarketUpdateProposerAddress).setGovernor(localTimelockAddress); MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setMarketUpdateProposer(computedMarketUpdateProposerAddress); @@ -82,28 +112,32 @@ library MarketUpdateContractsDeployer { address computedConfiguratorAddress = deployContractWithCreate2(create2Deployer, salt, configuratorParams); + ContractDeploymentParams memory marketAdminPermissionCheckerParams = ContractDeploymentParams({ + creationCode: type(MarketAdminPermissionChecker).creationCode, + constructorArgs: abi.encode(msgSender, INITIAL_ADDRESS_MARKET_UPDATE_MULTI_SIG, address(0)), + expectedRuntimeCode: type(MarketAdminPermissionChecker).runtimeCode, + contractName: "MarketAdminPermissionChecker" + }); + + address computedMarketAdminPermissionCheckerAddress = deployContractWithCreate2(create2Deployer, salt, marketAdminPermissionCheckerParams); + MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).setMarketAdmin(computedMarketUpdateTimelockAddress); + MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).setMarketAdminPauseGuardian(marketAdminPauseGuardianAddress); + + MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).transferOwnership(localTimelockAddress); + ContractDeploymentParams memory cometProxyAdminParams = ContractDeploymentParams({ creationCode: type(CometProxyAdmin).creationCode, - constructorArgs: abi.encode(msg.sender), + constructorArgs: abi.encode(msgSender), expectedRuntimeCode: type(CometProxyAdmin).runtimeCode, contractName: "CometProxyAdmin" }); address computedCometProxyAdminAddress = deployContractWithCreate2(create2Deployer, salt, cometProxyAdminParams); + CometProxyAdmin(computedCometProxyAdminAddress).setMarketAdminPermissionChecker(MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress)); CometProxyAdmin(computedCometProxyAdminAddress).transferOwnership(localTimelockAddress); console.log("Owner of cometProxyAdmin: ", CometProxyAdmin(computedCometProxyAdminAddress).owner()); - ContractDeploymentParams memory marketAdminPermissionCheckerParams = ContractDeploymentParams({ - creationCode: type(MarketAdminPermissionChecker).creationCode, - constructorArgs: abi.encode(msg.sender, marketUpdateMultiSig, address(0)), - expectedRuntimeCode: type(MarketAdminPermissionChecker).runtimeCode, - contractName: "MarketAdminPermissionChecker" - }); - - address computedMarketAdminPermissionCheckerAddress = deployContractWithCreate2(create2Deployer, salt, marketAdminPermissionCheckerParams); - MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).transferOwnership(localTimelockAddress); - vm.stopBroadcast(); return DeployedContracts({ marketUpdateTimelock: computedMarketUpdateTimelockAddress, marketUpdateProposer: computedMarketUpdateProposerAddress, diff --git a/forge/test/MarketUpdateArbitrumDeploymentTest.t.sol b/forge/test/MarketUpdateArbitrumDeploymentTest.t.sol index e800ee7c..38d0f1c3 100644 --- a/forge/test/MarketUpdateArbitrumDeploymentTest.t.sol +++ b/forge/test/MarketUpdateArbitrumDeploymentTest.t.sol @@ -26,12 +26,10 @@ contract MarketUpdateArbitrumDeploymentTest is Test, MarketUpdateDeploymentBaseT updateAndVerifySupplyKinkInL2( vm, + "USDC", ChainAddresses.Chain.ARBITRUM, MarketAddresses.ARBITRUM_USDC_MARKET, - ChainAddresses.ARBITRUM_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDC" + deployedContracts ); } @@ -40,12 +38,11 @@ contract MarketUpdateArbitrumDeploymentTest is Test, MarketUpdateDeploymentBaseT updateAndVerifySupplyKinkInL2( vm, + "USDCe", ChainAddresses.Chain.ARBITRUM, MarketAddresses.ARBITRUM_USDCe_MARKET, - ChainAddresses.ARBITRUM_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDCe" + deployedContracts + ); } @@ -54,12 +51,11 @@ contract MarketUpdateArbitrumDeploymentTest is Test, MarketUpdateDeploymentBaseT updateAndVerifySupplyKinkInL2( vm, + "USDT", ChainAddresses.Chain.ARBITRUM, MarketAddresses.ARBITRUM_USDT_MARKET, - ChainAddresses.ARBITRUM_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDT" + deployedContracts + ); } @@ -68,12 +64,10 @@ contract MarketUpdateArbitrumDeploymentTest is Test, MarketUpdateDeploymentBaseT updateAndVerifySupplyKinkInL2( vm, + "ETH", ChainAddresses.Chain.ARBITRUM, MarketAddresses.ARBITRUM_ETH_MARKET, - ChainAddresses.ARBITRUM_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "ETH" + deployedContracts ); } } diff --git a/forge/test/MarketUpdateBaseDeploymentTest.t.sol b/forge/test/MarketUpdateBaseDeploymentTest.t.sol index 23881033..f9fdf1ec 100644 --- a/forge/test/MarketUpdateBaseDeploymentTest.t.sol +++ b/forge/test/MarketUpdateBaseDeploymentTest.t.sol @@ -26,12 +26,10 @@ contract MarketUpdateBaseDeploymentTest is Test, MarketUpdateDeploymentBaseTest updateAndVerifySupplyKinkInL2( vm, + "USDbC", ChainAddresses.Chain.BASE, MarketAddresses.BASE_USDbC_MARKET, - ChainAddresses.BASE_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDbC" + deployedContracts ); } @@ -40,12 +38,10 @@ contract MarketUpdateBaseDeploymentTest is Test, MarketUpdateDeploymentBaseTest updateAndVerifySupplyKinkInL2( vm, + "USDC", ChainAddresses.Chain.BASE, MarketAddresses.BASE_USDC_MARKET, - ChainAddresses.BASE_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDC" + deployedContracts ); } @@ -54,12 +50,10 @@ contract MarketUpdateBaseDeploymentTest is Test, MarketUpdateDeploymentBaseTest updateAndVerifySupplyKinkInL2( vm, + "ETH", ChainAddresses.Chain.BASE, MarketAddresses.BASE_ETH_MARKET, - ChainAddresses.BASE_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "ETH" + deployedContracts ); } } diff --git a/forge/test/MarketUpdateDeploymentBaseTest.sol b/forge/test/MarketUpdateDeploymentBaseTest.sol index 8ab12db7..a017f12b 100644 --- a/forge/test/MarketUpdateDeploymentBaseTest.sol +++ b/forge/test/MarketUpdateDeploymentBaseTest.sol @@ -3,27 +3,31 @@ pragma solidity ^0.8.15; import "@forge-std/src/Vm.sol"; import "@comet-contracts/bridges/arbitrum/ArbitrumBridgeReceiver.sol"; +import "@comet-contracts/marketupdates/MarketAdminPermissionChecker.sol"; import "../script/marketupdates/helpers/GovernanceHelper.sol"; import "../script/marketupdates/helpers/MarketUpdateAddresses.sol"; import "../script/marketupdates/helpers/ChainAddresses.sol"; import "../script/marketupdates/helpers/MarketUpdateContractsDeployer.sol"; import "../script/marketupdates/helpers/BridgeHelper.sol"; import "@forge-std/src/console.sol"; +import "forge-std/Test.sol"; -abstract contract MarketUpdateDeploymentBaseTest { +abstract contract MarketUpdateDeploymentBaseTest is Test { IGovernorBravo public governorBravo = IGovernorBravo(MarketUpdateAddresses.GOVERNOR_BRAVO_PROXY_ADDRESS); function createMarketUpdateDeployment(Vm vm) public returns (MarketUpdateContractsDeployer.DeployedContracts memory) { - bytes32 salt = keccak256(abi.encodePacked("Salt-31")); - + bytes32 salt = keccak256(abi.encodePacked(vm.envString("SALT"))); + ChainAddresses.Chain chain = ChainAddresses.getChainBasedOnChainId(1); + ChainAddresses.ChainAddressesStruct memory chainAddresses = ChainAddresses.getChainAddresses(chain); + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer.deployContracts( vm, salt, - MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS, - MarketUpdateAddresses.MARKET_ADMIN_PAUSE_GUARDIAN_ADDRESS, - MarketUpdateAddresses.MARKET_UPDATE_PROPOSAL_GUARDIAN_ADDRESS, - MarketUpdateAddresses.GOVERNOR_BRAVO_TIMELOCK_ADDRESS + chainAddresses.marketAdmin, + chainAddresses.marketUpdatePauseGuardian, + chainAddresses.marketUpdateProposalGuardian, + chainAddresses.governorTimelockAddress ); @@ -60,16 +64,18 @@ abstract contract MarketUpdateDeploymentBaseTest { } function createMarketUpdateDeploymentForL2(Vm vm, ChainAddresses.Chain chain) public returns (MarketUpdateContractsDeployer.DeployedContracts memory) { - bytes32 salt = keccak256(abi.encodePacked("Salt-31")); + bytes32 salt = keccak256(abi.encodePacked(vm.envString("SALT"))); address localTimelock = ChainAddresses.getLocalTimelockAddress(chain); + ChainAddresses.ChainAddressesStruct memory chainAddresses = ChainAddresses.getChainAddresses(chain); + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer.deployContracts( vm, salt, - MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS, - MarketUpdateAddresses.MARKET_ADMIN_PAUSE_GUARDIAN_ADDRESS, - MarketUpdateAddresses.MARKET_UPDATE_PROPOSAL_GUARDIAN_ADDRESS, + chainAddresses.marketAdmin, + chainAddresses.marketUpdatePauseGuardian, + chainAddresses.marketUpdateProposalGuardian, localTimelock ); @@ -96,17 +102,18 @@ abstract contract MarketUpdateDeploymentBaseTest { function updateAndVerifySupplyKink( Vm vm, - address cometProxy, - address configuratorProxy, - address cometProxyAdminNew, - address marketUpdateProposer, - string memory marketName - ) public { - + string memory marketName, + address cometProxy, + ChainAddresses.ChainAddressesStruct memory chainAddresses, + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts + ) public { + address configuratorProxy = chainAddresses.configuratorProxyAddress; + address cometProxyAdminNew = deployedContracts.newCometProxyAdmin; + address marketUpdateProposer = deployedContracts.marketUpdateProposer; uint256 oldSupplyKinkBeforeGovernorUpdate = Comet(payable(cometProxy)).supplyKink(); uint256 newSupplyKinkByGovernorTimelock = 300000000000000000; - - assert(oldSupplyKinkBeforeGovernorUpdate != newSupplyKinkByGovernorTimelock); + + assertEq(MarketAdminPermissionChecker(deployedContracts.marketAdminPermissionChecker).marketAdmin(), deployedContracts.marketUpdateTimelock); address[] memory targets = new address[](2); uint256[] memory values = new uint256[](2); @@ -144,7 +151,7 @@ abstract contract MarketUpdateDeploymentBaseTest { calldatas[0] = abi.encode(cometProxy, newSupplyKinkByMarketAdmin); description = string(abi.encodePacked("Proposal to update Supply Kink for ", marketName, " Market by Market Admin")); - GovernanceHelper.createAndPassMarketUpdateProposal(vm, proposalRequest, description, marketUpdateProposer); + GovernanceHelper.createAndPassMarketUpdateProposal(vm, chainAddresses.marketAdmin, proposalRequest, description, marketUpdateProposer); uint256 newSupplyKinkAfterMarketAdminUpdate = Comet(payable(cometProxy)).supplyKink(); assert(newSupplyKinkAfterMarketAdminUpdate == newSupplyKinkByMarketAdmin); @@ -152,13 +159,17 @@ abstract contract MarketUpdateDeploymentBaseTest { function updateAndVerifySupplyKinkInL2( Vm vm, + string memory marketName, ChainAddresses.Chain chain, address cometProxy, - address configuratorProxy, - address cometProxyAdminNew, - address marketUpdateProposer, - string memory marketName - ) public { + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts + ) public { + + ChainAddresses.ChainAddressesStruct memory chainAddresses = ChainAddresses.getChainAddresses(chain); + + address configuratorProxy = chainAddresses.configuratorProxyAddress; + address cometProxyAdminNew = deployedContracts.newCometProxyAdmin; + address marketUpdateProposer = deployedContracts.marketUpdateProposer; uint256 oldSupplyKinkBeforeGovernorUpdate = Comet(payable(cometProxy)).supplyKink(); uint256 newSupplyKinkByGovernorTimelock = 300000000000000000; @@ -201,7 +212,7 @@ abstract contract MarketUpdateDeploymentBaseTest { calldatas[0] = abi.encode(cometProxy, newSupplyKinkByMarketAdmin); description = string(abi.encodePacked("Proposal to update Supply Kink for ", marketName, " Market by Market Admin")); - GovernanceHelper.createAndPassMarketUpdateProposalL2(vm, proposalRequest, description, marketUpdateProposer); + GovernanceHelper.createAndPassMarketUpdateProposalL2(vm, chainAddresses.marketAdmin, proposalRequest, description, marketUpdateProposer); uint256 newSupplyKinkAfterMarketAdminUpdate = Comet(payable(cometProxy)).supplyKink(); assert(newSupplyKinkAfterMarketAdminUpdate == newSupplyKinkByMarketAdmin); diff --git a/forge/test/MarketUpdateMainnetDeploymentTest.t.sol b/forge/test/MarketUpdateMainnetDeploymentTest.t.sol index fc5251e1..9daf536b 100644 --- a/forge/test/MarketUpdateMainnetDeploymentTest.t.sol +++ b/forge/test/MarketUpdateMainnetDeploymentTest.t.sol @@ -12,13 +12,15 @@ import "../script/marketupdates/helpers/MarketAddresses.sol"; import "../script/marketupdates/helpers/GovernanceHelper.sol"; import "./MarketUpdateDeploymentBaseTest.sol"; -contract MarketUpdateMainnetDeploymentTest is Test, MarketUpdateDeploymentBaseTest { +contract MarketUpdateMainnetDeploymentTest is MarketUpdateDeploymentBaseTest { - MarketUpdateContractsDeployer.DeployedContracts deployedContracts; + MarketUpdateContractsDeployer.DeployedContracts internal deployedContracts; + ChainAddresses.ChainAddressesStruct internal chainAddresses; function setUp() public { vm.createSelectFork("mainnet"); deployedContracts = createMarketUpdateDeployment(vm); + chainAddresses = ChainAddresses.getChainAddresses(ChainAddresses.Chain.ETHEREUM); } function test_UsdcDeployment() public { @@ -26,11 +28,10 @@ contract MarketUpdateMainnetDeploymentTest is Test, MarketUpdateDeploymentBaseTe updateAndVerifySupplyKink( vm, - MarketAddresses.MAINNET_USDC_MARKET, - ChainAddresses.MAINNET_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDC" + "USDC", + MarketAddresses.MAINNET_USDC_MARKET, + chainAddresses, + deployedContracts ); } @@ -39,11 +40,11 @@ contract MarketUpdateMainnetDeploymentTest is Test, MarketUpdateDeploymentBaseTe updateAndVerifySupplyKink( vm, - MarketAddresses.MAINNET_USDT_MARKET, - ChainAddresses.MAINNET_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDT" + "USDT", + MarketAddresses.MAINNET_USDT_MARKET, + chainAddresses, + deployedContracts + ); } @@ -52,11 +53,10 @@ contract MarketUpdateMainnetDeploymentTest is Test, MarketUpdateDeploymentBaseTe updateAndVerifySupplyKink( vm, - MarketAddresses.MAINNET_ETH_MARKET, - ChainAddresses.MAINNET_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "ETH" + "ETH", + MarketAddresses.MAINNET_ETH_MARKET, + chainAddresses, + deployedContracts ); } @@ -65,11 +65,10 @@ contract MarketUpdateMainnetDeploymentTest is Test, MarketUpdateDeploymentBaseTe updateAndVerifySupplyKink( vm, - MarketAddresses.MAINNET_WST_ETH_MARKET, - ChainAddresses.MAINNET_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "WST_ETH" + "WST_ETH", + MarketAddresses.MAINNET_WST_ETH_MARKET, + chainAddresses, + deployedContracts ); } } diff --git a/forge/test/MarketUpdateOptimismDeploymentTest.t.sol b/forge/test/MarketUpdateOptimismDeploymentTest.t.sol index d3d4ffd1..26bf5e25 100644 --- a/forge/test/MarketUpdateOptimismDeploymentTest.t.sol +++ b/forge/test/MarketUpdateOptimismDeploymentTest.t.sol @@ -26,12 +26,10 @@ contract MarketUpdateOptimismDeploymentTest is Test, MarketUpdateDeploymentBaseT updateAndVerifySupplyKinkInL2( vm, + "USDC", ChainAddresses.Chain.OPTIMISM, MarketAddresses.OPTIMISM_USDC_MARKET, - ChainAddresses.OPTIMISM_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDC" + deployedContracts ); } @@ -40,12 +38,10 @@ contract MarketUpdateOptimismDeploymentTest is Test, MarketUpdateDeploymentBaseT updateAndVerifySupplyKinkInL2( vm, + "USDT", ChainAddresses.Chain.OPTIMISM, MarketAddresses.OPTIMISM_USDT_MARKET, - ChainAddresses.OPTIMISM_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDT" + deployedContracts ); } @@ -54,12 +50,10 @@ contract MarketUpdateOptimismDeploymentTest is Test, MarketUpdateDeploymentBaseT updateAndVerifySupplyKinkInL2( vm, + "ETH", ChainAddresses.Chain.OPTIMISM, MarketAddresses.OPTIMISM_ETH_MARKET, - ChainAddresses.OPTIMISM_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "ETH" + deployedContracts ); } } diff --git a/forge/test/MarketUpdatePolygonDeploymentTest.t.sol b/forge/test/MarketUpdatePolygonDeploymentTest.t.sol index 23a4e605..7337ded5 100644 --- a/forge/test/MarketUpdatePolygonDeploymentTest.t.sol +++ b/forge/test/MarketUpdatePolygonDeploymentTest.t.sol @@ -26,12 +26,10 @@ contract MarketUpdatePolygonDeploymentTest is Test, MarketUpdateDeploymentBaseTe updateAndVerifySupplyKinkInL2( vm, + "USDCe", ChainAddresses.Chain.POLYGON, MarketAddresses.POLYGON_USDCe_MARKET, - ChainAddresses.POLYGON_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDCe" + deployedContracts ); } @@ -40,12 +38,10 @@ contract MarketUpdatePolygonDeploymentTest is Test, MarketUpdateDeploymentBaseTe updateAndVerifySupplyKinkInL2( vm, + "USDT", ChainAddresses.Chain.POLYGON, MarketAddresses.POLYGON_USDT_MARKET, - ChainAddresses.POLYGON_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDT" + deployedContracts ); } } diff --git a/forge/test/MarketUpdateScrollDeploymentTest.t.sol b/forge/test/MarketUpdateScrollDeploymentTest.t.sol index abf20998..5e185cfa 100644 --- a/forge/test/MarketUpdateScrollDeploymentTest.t.sol +++ b/forge/test/MarketUpdateScrollDeploymentTest.t.sol @@ -26,12 +26,10 @@ contract MarketUpdateScrollDeploymentTest is Test, MarketUpdateDeploymentBaseTes updateAndVerifySupplyKinkInL2( vm, + "USDC", ChainAddresses.Chain.SCROLL, MarketAddresses.SCROLL_USDC_MARKET, - ChainAddresses.SCROLL_CONFIGURATOR_PROXY, - deployedContracts.newCometProxyAdmin, - deployedContracts.marketUpdateProposer, - "USDC" + deployedContracts ); } } diff --git a/tasks/deployment_manager/task.ts b/tasks/deployment_manager/task.ts index ad8d3ad0..cf69fdc2 100644 --- a/tasks/deployment_manager/task.ts +++ b/tasks/deployment_manager/task.ts @@ -93,7 +93,7 @@ task('deploy', 'Deploys market') const verify = noVerify ? false : !simulate; const desc = verify ? 'Verify' : 'Would verify'; - if (noVerify || simulate) { + if (noVerify && simulate) { // Don't even print if --no-verify is set with --simulate } else { await dm.verifyContracts(async (address, args) => { From f923b663f233f4c043b2c1a6e6f47911436ac863 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 15 Oct 2024 17:35:28 -0400 Subject: [PATCH 15/28] Restore the deleted script --- .../1726480777_add_cbbtc_as_collateral.ts | 152 ++++++++++++++ .../1728316375_gov_marketupdates.ts | 193 ------------------ 2 files changed, 152 insertions(+), 193 deletions(-) create mode 100644 deployments/base/weth/migrations/1726480777_add_cbbtc_as_collateral.ts delete mode 100644 deployments/optimism/usdc/migrations/1728316375_gov_marketupdates.ts diff --git a/deployments/base/weth/migrations/1726480777_add_cbbtc_as_collateral.ts b/deployments/base/weth/migrations/1726480777_add_cbbtc_as_collateral.ts new file mode 100644 index 00000000..d8951214 --- /dev/null +++ b/deployments/base/weth/migrations/1726480777_add_cbbtc_as_collateral.ts @@ -0,0 +1,152 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, exp, proposal } from '../../../../src/deploy'; +import { utils } from 'ethers'; + +const CBBTC_ADDRESS = '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf'; +const CBBTC_USD_PRICE_FEED_ADDRESS = '0x07DA0E54543a844a80ABE69c8A12F22B3aA59f9D'; +const ETH_USD_PRICE_FEED_ADDRESS = '0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70'; +let newPriceFeedAddress: string; + +export default migration('1726480777_add_cbbtc_as_collateral', { + async prepare(deploymentManager: DeploymentManager) { + const _cbBTCPriceFeed = await deploymentManager.deploy( + 'cbBTC:priceFeed', + 'pricefeeds/ReverseMultiplicativePriceFeed.sol', + [ + CBBTC_USD_PRICE_FEED_ADDRESS, // cbBTC / USD price feed + ETH_USD_PRICE_FEED_ADDRESS, // USD / ETH price feed + 8, // decimals + 'cbBTC / ETH price feed', // description + ] + ); + + return { cbBTCPriceFeedAddress: _cbBTCPriceFeed.address }; + }, + + enact: async ( + deploymentManager: DeploymentManager, + govDeploymentManager: DeploymentManager, + { cbBTCPriceFeedAddress } + ) => { + const trace = deploymentManager.tracer(); + + const cbBTC = await deploymentManager.existing( + 'cbBTC', + CBBTC_ADDRESS, + 'base', + 'contracts/ERC20.sol:ERC20' + ); + const cbBTCPriceFeed = await deploymentManager.existing( + 'cbBTC:priceFeed', + cbBTCPriceFeedAddress, + 'base' + ); + + const { + bridgeReceiver, + comet, + cometAdmin, + configurator, + } = await deploymentManager.getContracts(); + + const { governor, baseL1CrossDomainMessenger } = await govDeploymentManager.getContracts(); + + const newAssetConfig = { + asset: cbBTC.address, + priceFeed: cbBTCPriceFeed.address, + decimals: await cbBTC.decimals(), + borrowCollateralFactor: exp(0.80, 18), + liquidateCollateralFactor: exp(0.85, 18), + liquidationFactor: exp(0.95, 18), + supplyCap: exp(45, 8), + }; + + newPriceFeedAddress = cbBTCPriceFeed.address; + + const addAssetCalldata = await calldata( + configurator.populateTransaction.addAsset(comet.address, newAssetConfig) + ); + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, cometAdmin.address], + [0, 0], + [ + 'addAsset(address,(address,address,uint8,uint64,uint64,uint64,uint128))', + 'deployAndUpgradeTo(address,address)', + ], + [addAssetCalldata, deployAndUpgradeToCalldata], + ] + ); + + const mainnetActions = [ + // Send the proposal to the L2 bridge + { + contract: baseL1CrossDomainMessenger, + signature: 'sendMessage(address,bytes,uint32)', + args: [bridgeReceiver.address, l2ProposalData, 3_000_000] + }, + ]; + + const description = '# Add cbBTC as collateral into cWETHv3 on Base\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to add cbBTC into cWETHv3 on Base network. This proposal takes the governance steps recommended and necessary to update a Compound III WETH market on Base. Simulations have confirmed the market’s readiness, as much as possible, using the [Comet scenario suite](https://github.com/compound-finance/comet/tree/main/scenario). The new parameters include setting the risk parameters based off of the [recommendations from Gauntlet](https://www.comp.xyz/t/add-collateral-cbbtc-to-weth-market-on-base-and-mainnet/5689/2).\n\nFurther detailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/926) and [forum discussion](https://www.comp.xyz/t/add-collateral-cbbtc-to-weth-market-on-base-and-mainnet/5689).\n\n\n## Proposal Actions\n\nThe first proposal action adds cbBTC to the WETH Comet on Base. This sends the encoded `addAsset` and `deployAndUpgradeTo` calls across the bridge to the governance receiver on Base.'; + const txn = await govDeploymentManager.retry(async () => + trace( + await governor.propose(...(await proposal(mainnetActions, description))) + ) + ); + + const event = txn.events.find( + (event) => event.event === 'ProposalCreated' + ); + const [proposalId] = event.args; + trace(`Created proposal ${proposalId}.`); + }, + + async enacted(deploymentManager: DeploymentManager): Promise { + return true; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet, configurator } = await deploymentManager.getContracts(); + + const cbBTCAssetIndex = Number(await comet.numAssets()) - 1; + + const cbBTCAssetConfig = { + asset: CBBTC_ADDRESS, + priceFeed: newPriceFeedAddress, + decimals: 8, + borrowCollateralFactor: exp(0.80, 18), + liquidateCollateralFactor: exp(0.85, 18), + liquidationFactor: exp(0.95, 18), + supplyCap: exp(45, 8), + }; + + // 1. Compare proposed asset config with Comet asset info + const cbBTCAssetInfo = await comet.getAssetInfoByAddress(CBBTC_ADDRESS); + expect(cbBTCAssetIndex).to.be.equal(cbBTCAssetInfo.offset); + expect(cbBTCAssetConfig.asset).to.be.equal(cbBTCAssetInfo.asset); + expect(cbBTCAssetConfig.priceFeed).to.be.equal(cbBTCAssetInfo.priceFeed); + expect(exp(1, cbBTCAssetConfig.decimals)).to.be.equal(cbBTCAssetInfo.scale); + expect(cbBTCAssetConfig.borrowCollateralFactor).to.be.equal(cbBTCAssetInfo.borrowCollateralFactor); + expect(cbBTCAssetConfig.liquidateCollateralFactor).to.be.equal(cbBTCAssetInfo.liquidateCollateralFactor); + expect(cbBTCAssetConfig.liquidationFactor).to.be.equal(cbBTCAssetInfo.liquidationFactor); + expect(cbBTCAssetConfig.supplyCap).to.be.equal(cbBTCAssetInfo.supplyCap); + + // 2. Compare proposed asset config with Configurator asset config + const configuratorCbBTCAssetConfig = (await configurator.getConfiguration(comet.address)).assetConfigs[cbBTCAssetIndex]; + expect(cbBTCAssetConfig.asset).to.be.equal(configuratorCbBTCAssetConfig.asset); + expect(cbBTCAssetConfig.priceFeed).to.be.equal(configuratorCbBTCAssetConfig.priceFeed); + expect(cbBTCAssetConfig.decimals).to.be.equal(configuratorCbBTCAssetConfig.decimals); + expect(cbBTCAssetConfig.borrowCollateralFactor).to.be.equal(configuratorCbBTCAssetConfig.borrowCollateralFactor); + expect(cbBTCAssetConfig.liquidateCollateralFactor).to.be.equal(configuratorCbBTCAssetConfig.liquidateCollateralFactor); + expect(cbBTCAssetConfig.liquidationFactor).to.be.equal(configuratorCbBTCAssetConfig.liquidationFactor); + expect(cbBTCAssetConfig.supplyCap).to.be.equal(configuratorCbBTCAssetConfig.supplyCap); + }, +}); diff --git a/deployments/optimism/usdc/migrations/1728316375_gov_marketupdates.ts b/deployments/optimism/usdc/migrations/1728316375_gov_marketupdates.ts deleted file mode 100644 index 7b7c19d5..00000000 --- a/deployments/optimism/usdc/migrations/1728316375_gov_marketupdates.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { exp, proposal } from '../../../../src/deploy'; -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; - -interface Vars { - deployedContracts: any; -}; - -const governorTimelockAddress = '0x6d903f6003cca6255D85CcA4D3B5E5146dC33925'; -const marketUpdateMultiSig = '0x7053e25f7076F4986D632A3C04313C81831e0d55'; -const marketUpdateProposalGuardian = - '0x77B65c68E52C31eb844fb3b4864B91133e2C1308'; -const delay = 360000; - - -export default migration('1728316375_gov_marketupdates', { - prepare: async (deploymentManager: DeploymentManager) => { - const ethers = deploymentManager.hre.ethers; - - const marketUpdateTimelock = await deploymentManager.deploy( - 'marketUpdateTimelock', - 'marketupdates/MarketUpdateTimelock.sol', - [governorTimelockAddress, delay], - true - ); - - const marketUpdateProposer = await deploymentManager.deploy( - 'marketUpdateProposer', - 'marketupdates/MarketUpdateProposer.sol', - [ - governorTimelockAddress, - marketUpdateMultiSig, - marketUpdateProposalGuardian, - marketUpdateTimelock.address, - ], - true - ); - - const configurator = await deploymentManager.deploy( - 'configuratorNew', - 'Configurator.sol', - [], - true - ); - - const cometProxyAdmin = await deploymentManager.deploy( - 'cometProxyAdminNew', - 'CometProxyAdmin.sol', - [governorTimelockAddress], - true - ); - - const marketAdminPermissionChecker = await deploymentManager.deploy( - 'marketAdminPermissionChecker', - 'marketupdates/MarketAdminPermissionChecker.sol', - [ - governorTimelockAddress, - ethers.constants.AddressZero, - ethers.constants.AddressZero, - ] - ); - const deployedContracts = { - marketUpdateTimelock, - marketUpdateProposer, - configurator, - cometProxyAdmin, - marketAdminPermissionChecker, - }; - - return { deployedContracts }; - }, - - enact: async ( - deploymentManager: DeploymentManager, - govDeploymentManager: DeploymentManager, - vars: Vars - ) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - const { utils } = ethers; - - // Assuming that we have the addresses of the contracts we need to interact with - const addresses: any = {}; - - const { bridgeReceiver, comet, cometAdmin, configurator, rewards } = - await deploymentManager.getContracts(); - - const { scrollMessenger, scrollL1USDCGateway, governor, USDC } = - await govDeploymentManager.getContracts(); - - const cometProxyAdminOldAddress = addresses.cometProxyAdminAddress; - const configuratorProxyAddress = addresses.configuratorProxyAddress; - const configuratorNewAddress = addresses.configuratorImplementationAddress; - const cometProxyAdminNewAddress = addresses.newCometProxyAdminAddress; - const marketAdminPermissionCheckerAddress = - addresses.marketAdminPermissionCheckerAddress; - const marketUpdateTimelockAddress = addresses.marketUpdateTimelockAddress; - const marketUpdateProposerAddress = addresses.marketAdminProposerAddress; - const cometProxyAddress = addresses.markets[0].cometProxyAddress; - - const changeProxyAdminForCometProxyCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [cometProxyAddress, cometProxyAdminNewAddress] - ); - - const changeProxyAdminForConfiguratorProxyCalldata = - utils.defaultAbiCoder.encode( - ['address', 'address'], - [configuratorProxyAddress, cometProxyAdminNewAddress] - ); - - const upgradeConfiguratorProxyCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [configuratorProxyAddress, configuratorNewAddress] - ); - - const setMarketAdminCalldata = utils.defaultAbiCoder.encode( - ['address'], - [marketUpdateTimelockAddress] - ); - - const setMarketAdminPermissionCheckerForConfiguratorProxyCalldata = - utils.defaultAbiCoder.encode( - ['address'], - [marketAdminPermissionCheckerAddress] - ); - - const setMarketAdminPermissionCheckerForCometProxyCalldata = - utils.defaultAbiCoder.encode( - ['address'], - [marketAdminPermissionCheckerAddress] - ); - - const setMarketUpdateProposerCalldata = utils.defaultAbiCoder.encode( - ['address'], - [marketUpdateProposerAddress] - ); - - const l2ProposalData = utils.defaultAbiCoder.encode( - ['address[]', 'uint256[]', 'string[]', 'bytes[]'], - [ - [ - cometProxyAdminOldAddress, - cometProxyAdminOldAddress, - cometProxyAdminNewAddress, - marketAdminPermissionCheckerAddress, - configuratorProxyAddress, - cometProxyAdminNewAddress, - marketUpdateTimelockAddress, - ], - [0, 0, 0, 0, 0, 0, 0], - [ - 'changeProxyAdmin(address,address)', - 'changeProxyAdmin(address,address)', - 'upgrade(address,address)', - 'setMarketAdmin(address)', - 'setMarketAdminPermissionChecker(address)', - 'setMarketAdminPermissionChecker(address)', - 'setMarketUpdateProposer(address)', - ], - [ - changeProxyAdminForCometProxyCalldata, - changeProxyAdminForConfiguratorProxyCalldata, - upgradeConfiguratorProxyCalldata, - setMarketAdminCalldata, - setMarketAdminPermissionCheckerForConfiguratorProxyCalldata, - setMarketAdminPermissionCheckerForCometProxyCalldata, - setMarketUpdateProposerCalldata, - ], - ] - ); - - const actions = [ - { - contract: scrollMessenger, - signature: 'sendMessage(address,uint256,bytes,uint256)', - args: [bridgeReceiver.address, 0, l2ProposalData, 600_000], - value: exp(0.1, 18), - }, - ]; - - const description = - 'Governance proposal with actions to change proxy admins, upgrade the configurator, and set the market admin and related roles.'; - const txn = await govDeploymentManager.retry(async () => - trace(await governor.propose(...(await proposal(actions, description)))) - ); - - const event = txn.events.find((event) => event.event === 'ProposalCreated'); - const [proposalId] = event.args; - - trace(`Created proposal ${proposalId}.`); - } -}); From fda374577184fab88b5bcf46894d3e017143cf79 Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 15 Oct 2024 17:50:34 -0400 Subject: [PATCH 16/28] remove extra file --- forge/simulate.md | 133 ---------------------------------------------- 1 file changed, 133 deletions(-) delete mode 100644 forge/simulate.md diff --git a/forge/simulate.md b/forge/simulate.md deleted file mode 100644 index 6164b4a9..00000000 --- a/forge/simulate.md +++ /dev/null @@ -1,133 +0,0 @@ -# Deployment -Assuming contracts are deployed using forge scripts, we want to write a migration for creating a proposal -for market updates. - -So in the migration, we can call a helper contract which has functions to prepare a proposal. We can see ho to -avoid the initialization of that contract, as in really we just need to call a library which returns the information -needed for creating the proposal. - -# Proposals for L2 -Proposals for l2 has two parts -### 1) Preparation -Preparation involves deploying of the contracts. Here we can just deploy the contracts using the forge scripts. - -Robin with connect with Compound team on Monday to take a decision on this. - - -### 2) Proposal creation -Proposal creation involves two parts - -##### 1) Create L2 payload -Creating the payload of the actions that needs to be taken by local timelock of L2. The payload is -`abi.encode(targets, values, signatures, calldatas)`. We have the code to get the targets, values, signatures, calldatas -i.e. - -```solidity - -// This gets all the chain and market specific addresses. -MarketUpdateAddresses.MarketUpdateAddressesStruct memory addresses = MarketUpdateAddresses.getAddressesForChain( - chain, - deployedContracts, - MarketUpdateAddresses.MARKET_UPDATE_MULTISIG_ADDRESS -); - - -// This gets the payload for the proposal -GovernanceHelper.ProposalRequest memory proposalRequest = GovernanceHelper.createDeploymentProposalRequest(addresses); -``` - -Here DeployedAddresses has the addresses of all the deployed contracts and ProposalRequest has the targets, values, signatures, calldatas. -```solidity -struct DeployedContracts { - address marketUpdateTimelock; - address marketUpdateProposer; - address newCometProxyAdmin; - address newConfiguratorImplementation; - address marketAdminPermissionChecker; -} - - -struct ProposalRequest { - address[] targets; - uint256[] values; - string[] signatures; - bytes[] calldatas; -} -``` -We can either encode in solidity or in the migration script. - -If we look at an existing migration script i.g. `deployments/optimism/usdc/migrations/1721299083_add_wsteth_as_collateral.ts` -We see this part implemented in typescipt -```typescript -const newAssetConfig = { - asset: wstETH.address, - priceFeed: wstETHPricefeed.address, - decimals: await wstETH.decimals(), - borrowCollateralFactor: exp(0.80, 18), - liquidateCollateralFactor: exp(0.85, 18), - liquidationFactor: exp(0.90, 18), - supplyCap: exp(600, 18), -}; - -newPriceFeedAddress = wstETHPricefeed.address; - -const addAssetCalldata = await calldata( - configurator.populateTransaction.addAsset(comet.address, newAssetConfig) -); -const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [configurator.address, comet.address] -); - -const l2ProposalData = utils.defaultAbiCoder.encode( - ['address[]', 'uint256[]', 'string[]', 'bytes[]'], - [ - [configurator.address, cometAdmin.address], - [0, 0], - [ - 'addAsset(address,(address,address,uint8,uint64,uint64,uint64,uint128))', - 'deployAndUpgradeTo(address,address)', - ], - [addAssetCalldata, deployAndUpgradeToCalldata], - ] -); -``` -##### 2) Creating Mainnet Proposal -For this we plan to use existing migrations as they have the code related to calling of the bridge and for doing -it in a forge script, we have to do quite some unit testing. So we plan to use the existing migrations. - -See this code -```typescript -const mainnetActions = [ - // Send the proposal to the L2 bridge - { - contract: opL1CrossDomainMessenger, - signature: 'sendMessage(address,bytes,uint32)', - args: [bridgeReceiver.address, l2ProposalData, 3_000_000] - }, -]; - -const description = '# Add wstETH as collateral into cUSDCv3 on Optimism\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to add wstETH into cUSDCv3 on Optimism network. This proposal takes the governance steps recommended and necessary to update a Compound III USDC market on Optimism. Simulations have confirmed the market’s readiness, as much as possible, using the [Comet scenario suite](https://github.com/compound-finance/comet/tree/main/scenario). The new parameters include setting the risk parameters based off of the [recommendations from Gauntlet](https://www.comp.xyz/t/gauntlet-wsteth-listing-for-usdc-and-usdt-comet-on-optimism/5441/1).\n\nFurther detailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/892) and [forum discussion](https://www.comp.xyz/t/gauntlet-wsteth-listing-for-usdc-and-usdt-comet-on-optimism/5441).\n\n\n## Proposal Actions\n\nThe first proposal action adds wstETH to the USDC Comet on Optimism. This sends the encoded `addAsset` and `deployAndUpgradeTo` calls across the bridge to the governance receiver on Optimism.'; -const txn = await govDeploymentManager.retry(async () => - trace( - await governor.propose(...(await proposal(mainnetActions, description))) - ) -); - -const event = txn.events.find( - (event) => event.event === 'ProposalCreated' -); -const [proposalId] = event.args; -trace(`Created proposal ${proposalId}.`); - -``` - -# Our Deployment Plan -- We plan to deploy the contracts using the forge scripts. Alternatively we can create a `Deployer(Helper)` or -deploy all the contracts in the prepare function of the migration. -- We plan to create the payload in the migration script. - -# Checklist -- [ ] See what are our options for calling the libraries in the migration script. If -we can call the libraries in the migration script, we can a lot of the extra typescript code. -- [ ] Check pauseGuardian, multisig, and proposalGuardian are set properly From 177595d02d65c519abafe1035e3e5d303d0d2a7e Mon Sep 17 00:00:00 2001 From: robin Date: Wed, 16 Oct 2024 07:58:40 -0400 Subject: [PATCH 17/28] Update node to v18 as 16 is no longer supported --- .github/workflows/deploy-market.yaml | 4 ++-- .github/workflows/enact-migration.yaml | 4 ++-- .github/workflows/prepare-migration.yaml | 4 ++-- .github/workflows/run-contract-linter.yaml | 2 +- .github/workflows/run-coverage.yaml | 2 +- .github/workflows/run-eslint.yaml | 2 +- .github/workflows/run-gas-profiler.yaml | 2 +- .github/workflows/run-scenarios.yaml | 4 ++-- .github/workflows/run-slither.yaml | 2 +- .github/workflows/run-unit-tests.yaml | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/deploy-market.yaml b/.github/workflows/deploy-market.yaml index fe6e3502..eeefe16b 100644 --- a/.github/workflows/deploy-market.yaml +++ b/.github/workflows/deploy-market.yaml @@ -57,7 +57,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '16' + node-version: '18' - name: Install packages run: yarn install --non-interactive --frozen-lockfile @@ -90,4 +90,4 @@ jobs: git config user.email "<>" git add deployments/\*/roots.json git commit -m "Modified deployment roots from GitHub Actions" - git push origin \ No newline at end of file + git push origin diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index d2d62842..c7c9f3a3 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -94,7 +94,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '16' + node-version: '18' - name: Install packages run: yarn install --non-interactive --frozen-lockfile @@ -153,4 +153,4 @@ jobs: git config user.email "<>" git add deployments/${{ github.event.inputs.network }}/${{ github.event.inputs.deployment }}/migrations/${{ github.event.inputs.migration }}.ts git commit -m "Modified migration from GitHub Actions" || echo "No changes to commit" - git push origin \ No newline at end of file + git push origin diff --git a/.github/workflows/prepare-migration.yaml b/.github/workflows/prepare-migration.yaml index 9d6206a1..e1a71612 100644 --- a/.github/workflows/prepare-migration.yaml +++ b/.github/workflows/prepare-migration.yaml @@ -57,7 +57,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '16' + node-version: '18' - name: Install packages run: yarn install --non-interactive --frozen-lockfile @@ -81,4 +81,4 @@ jobs: if: success() || failure() # run this step even if previous step failed with: name: ${{ github.event.inputs.network }}-${{ github.event.inputs.deployment }}-${{ github.event.inputs.migration }} - path: deployments/${{ github.event.inputs.network }}/${{ github.event.inputs.deployment }}/artifacts/${{ github.event.inputs.migration }}.json \ No newline at end of file + path: deployments/${{ github.event.inputs.network }}/${{ github.event.inputs.deployment }}/artifacts/${{ github.event.inputs.migration }}.json diff --git a/.github/workflows/run-contract-linter.yaml b/.github/workflows/run-contract-linter.yaml index 2513cc18..01e2a42a 100644 --- a/.github/workflows/run-contract-linter.yaml +++ b/.github/workflows/run-contract-linter.yaml @@ -21,7 +21,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '16' + node-version: '18' - name: Install packages run: yarn install --non-interactive --frozen-lockfile && yarn build diff --git a/.github/workflows/run-coverage.yaml b/.github/workflows/run-coverage.yaml index b28829b5..f2a6faad 100644 --- a/.github/workflows/run-coverage.yaml +++ b/.github/workflows/run-coverage.yaml @@ -23,7 +23,7 @@ jobs: - uses: actions/setup-node@v4 with: cache: 'yarn' - node-version: '16' + node-version: '18' - name: Install packages run: yarn install --non-interactive --frozen-lockfile diff --git a/.github/workflows/run-eslint.yaml b/.github/workflows/run-eslint.yaml index 1961fec4..b8bdd325 100644 --- a/.github/workflows/run-eslint.yaml +++ b/.github/workflows/run-eslint.yaml @@ -21,7 +21,7 @@ jobs: - uses: actions/setup-node@v4 with: cache: 'yarn' - node-version: '16' + node-version: '18' - name: Install packages run: yarn install --non-interactive --frozen-lockfile && yarn build diff --git a/.github/workflows/run-gas-profiler.yaml b/.github/workflows/run-gas-profiler.yaml index d49ba915..f050dad5 100644 --- a/.github/workflows/run-gas-profiler.yaml +++ b/.github/workflows/run-gas-profiler.yaml @@ -21,7 +21,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '16' + node-version: '18' - name: Install packages run: yarn install --non-interactive --frozen-lockfile && yarn build diff --git a/.github/workflows/run-scenarios.yaml b/.github/workflows/run-scenarios.yaml index fcff8271..759e813a 100644 --- a/.github/workflows/run-scenarios.yaml +++ b/.github/workflows/run-scenarios.yaml @@ -29,7 +29,7 @@ jobs: - uses: actions/setup-node@v4 with: cache: 'yarn' - node-version: '16' + node-version: '18' - name: Cache Deployments uses: actions/cache@v4 @@ -64,4 +64,4 @@ jobs: with: name: Scenario Tests (${{ matrix.bases }}) # Name of the check run which will be created path: scenario-results.json # Path to test results (inside artifact .zip) - reporter: mocha-json # Format of test results \ No newline at end of file + reporter: mocha-json # Format of test results diff --git a/.github/workflows/run-slither.yaml b/.github/workflows/run-slither.yaml index 2ca5a871..456a6fff 100644 --- a/.github/workflows/run-slither.yaml +++ b/.github/workflows/run-slither.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '16' + node-version: '18' - uses: actions/setup-python@v4 with: diff --git a/.github/workflows/run-unit-tests.yaml b/.github/workflows/run-unit-tests.yaml index 49779a40..2aae1e19 100644 --- a/.github/workflows/run-unit-tests.yaml +++ b/.github/workflows/run-unit-tests.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '16' + node-version: '18' - name: Install packages run: yarn install --non-interactive --frozen-lockfile From d61b35c19fe51dd0e06f405ceae23a3bfb438266 Mon Sep 17 00:00:00 2001 From: robin Date: Wed, 16 Oct 2024 10:16:52 -0400 Subject: [PATCH 18/28] fix typescript error --- package.json | 2 +- tsconfig.json | 3 ++- yarn.lock | 7 ++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 7305fd64..62fa8317 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "solhint": "^3.3.6", "ts-node": "^10.4.0", "typechain": "^6.0.2", - "typescript": "^4.4.4", + "typescript": "^5.6.3", "vendoza": "0.0.4" }, "repository": "git@github.com:compound-finance/comet.git", diff --git a/tsconfig.json b/tsconfig.json index 5fd29a12..0c06eb43 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,5 +11,6 @@ "files": [ "./index.ts", "./hardhat.config.ts", - ] + ], + "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index 1f357a7d..b2ce06ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4524,11 +4524,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@^4.1.2, typescript@^4.4.4: +typescript@^4.1.2: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +typescript@^5.6.3: + version "5.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== + typescript@~4.0.3: version "4.0.8" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.8.tgz#5739105541db80a971fdbd0d56511d1a6f17d37f" From f06e83c932230c339bba6dd71ef750afb1622a48 Mon Sep 17 00:00:00 2001 From: robin Date: Wed, 16 Oct 2024 10:58:29 -0400 Subject: [PATCH 19/28] Fix ProxyAdmin contract deployment --- plugins/deployment_manager/test/DeploymentManagerTest.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/deployment_manager/test/DeploymentManagerTest.ts b/plugins/deployment_manager/test/DeploymentManagerTest.ts index 44d3e8b8..e7caea61 100644 --- a/plugins/deployment_manager/test/DeploymentManagerTest.ts +++ b/plugins/deployment_manager/test/DeploymentManagerTest.ts @@ -30,7 +30,8 @@ export interface TestContracts { } export async function setupContracts(deploymentManager: DeploymentManager): Promise { - let proxyAdminArgs: [] = []; + const signers = await deploymentManager.getSigners(); + let proxyAdminArgs: string[] = [signers[0].address]; let proxyAdmin: ProxyAdmin = await deploymentManager.deploy( 'proxyAdmin', 'vendor/proxy/transparent/ProxyAdmin.sol', From 6e0ef6579b4fe66482723a927addebb9da0351c5 Mon Sep 17 00:00:00 2001 From: robin Date: Wed, 16 Oct 2024 11:11:52 -0400 Subject: [PATCH 20/28] Fix ProxyAdmin contract deployment --- plugins/deployment_manager/test/SpiderTest.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/deployment_manager/test/SpiderTest.ts b/plugins/deployment_manager/test/SpiderTest.ts index 0beba07f..5b2c3aff 100644 --- a/plugins/deployment_manager/test/SpiderTest.ts +++ b/plugins/deployment_manager/test/SpiderTest.ts @@ -28,9 +28,10 @@ async function setupContracts( cache: Cache, hre: HardhatRuntimeEnvironment ): Promise { + const signers = await hre.ethers.getSigners(); let proxyAdmin: ProxyAdmin = await deploy( 'vendor/proxy/transparent/ProxyAdmin.sol', - [], + [signers[0].address], hre, { cache, network: 'test-network' } ); From e4f57fbaab566796a767ed6378cef68cffd11b14 Mon Sep 17 00:00:00 2001 From: robin Date: Wed, 16 Oct 2024 12:52:16 -0400 Subject: [PATCH 21/28] Configure environment variables --- .github/workflows/run-forge-tests.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/run-forge-tests.yaml b/.github/workflows/run-forge-tests.yaml index 6a10f752..e10a1cc1 100644 --- a/.github/workflows/run-forge-tests.yaml +++ b/.github/workflows/run-forge-tests.yaml @@ -30,6 +30,12 @@ jobs: ARBISCAN_KEY: ${{ secrets.ARBISCAN_KEY }} LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} + MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }} + OPTIMISM_RPC_URL: ${{ secrets.OPTIMISM_RPC_URL }} + BASE_RPC_URL: ${{ secrets.BASE_RPC_URL }} + SCROLL_RPC_URL: ${{ secrets.SCROLL_RPC_URL }} + ARBITRUM_RPC_URL: ${{ secrets.ARBITRUM_RPC_URL }} + POLYGON_RPC_URL: ${{ secrets.POLYGON_RPC_URL }} - name: Build Comet with older solc versions run: | From f4b1fdd5ddbbaefb7d8484d3b5a1889a0fa37519 Mon Sep 17 00:00:00 2001 From: robin Date: Wed, 16 Oct 2024 13:04:30 -0400 Subject: [PATCH 22/28] Add salt that is used in market update deployments --- .github/workflows/run-forge-tests.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/run-forge-tests.yaml b/.github/workflows/run-forge-tests.yaml index e10a1cc1..95bb79e0 100644 --- a/.github/workflows/run-forge-tests.yaml +++ b/.github/workflows/run-forge-tests.yaml @@ -36,6 +36,7 @@ jobs: SCROLL_RPC_URL: ${{ secrets.SCROLL_RPC_URL }} ARBITRUM_RPC_URL: ${{ secrets.ARBITRUM_RPC_URL }} POLYGON_RPC_URL: ${{ secrets.POLYGON_RPC_URL }} + SALT: ${{ secrets.SALT }} - name: Build Comet with older solc versions run: | From 197ba6d626ef95ed16d243e620e372bcf356230d Mon Sep 17 00:00:00 2001 From: robin Date: Wed, 16 Oct 2024 16:04:48 -0400 Subject: [PATCH 23/28] Update permission to try to fix dorny/test-reporter@v1 error --- .github/workflows/run-unit-tests.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/run-unit-tests.yaml b/.github/workflows/run-unit-tests.yaml index 2aae1e19..76130a80 100644 --- a/.github/workflows/run-unit-tests.yaml +++ b/.github/workflows/run-unit-tests.yaml @@ -2,6 +2,10 @@ name: Run Unit Tests on: workflow_dispatch: pull_request: + +permissions: + checks: write # Grant write permission to checks + jobs: unit-tests: name: Unit tests From 56ea0f3bfe09b426aae92f2898581863c337e97d Mon Sep 17 00:00:00 2001 From: robin Date: Wed, 16 Oct 2024 18:03:33 -0400 Subject: [PATCH 24/28] Add proposal description --- .../1728988057_gov_market_updates.ts | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/deployments/scroll/usdc/migrations/1728988057_gov_market_updates.ts b/deployments/scroll/usdc/migrations/1728988057_gov_market_updates.ts index e60e757d..a73b8dd4 100644 --- a/deployments/scroll/usdc/migrations/1728988057_gov_market_updates.ts +++ b/deployments/scroll/usdc/migrations/1728988057_gov_market_updates.ts @@ -104,7 +104,26 @@ export default migration('1728988057_gov_market_updates', { ]; const description = - 'Governance proposal with actions to change proxy admins, upgrade the configurator, and set the market admin and related roles.'; + `DoDAO has been examining various areas where improvements can be made to governance in Compound through tooling or automation. A significant issue raised repeatedly by many members concerns the time and effort required to apply Market Updates. + +Currently, approximately 70-90% of the proposals pertain solely to updating market parameters. Gauntlet uses analytics and algorithms to determine new parameters based on current market conditions. These proposals are highly specific and require unique skills for validation. So far, we have seen minimal participation from other community members or teams in validating these parameters. + +Assuming the total cost of reviewing a proposal (including the effort of all delegates) is $2,000 per proposal, we are spending upwards of $300,000 per year on a process that currently acts more as a friction layer without much safeguard, as these market update proposals are rarely reviewed thoroughly. + +This not only slows down the process but also diverts focus from reviewing essential proposals related to new partnerships, the addition of new chains, and the introduction of assets, etc. + +We propose a parallel process specifically for market updates that can bypass the normal governance lifecycle. This would enable us, as a Compound community, to move faster and concentrate on the most critical decisions. + +This proposal has already been discussed here - https://www.comp.xyz/t/market-updates-alternate-governance-track/5379 + +The forum post includes two solutions, and OpenZeppelin has provided details and feedback on those solutions. + +After discussing with OpenZeppelin, DoDAO and OZ together believe that given the amount of changes, updating the Configurator could be the best solution. OpenZeppelin mentioned a couple of important points in the forum post: + +1. Grant the market admin role to an Safe address, which can be maintained by Gauntlet or other community members. +2. Market Updates to the Configurator will go through a timelock, providing sufficient time for the community to review or even block the market updates via this alternate route. +`; + const txn = await govDeploymentManager.retry(async () => trace(await governor.propose(...(await proposal(actions, description)))) ); From 771d6f466e2e3b36365949fb1d46c7a982ccab92 Mon Sep 17 00:00:00 2001 From: Robin Nagpal Date: Wed, 16 Oct 2024 19:11:23 -0400 Subject: [PATCH 25/28] Fix slither build --- .github/workflows/run-slither.yaml | 3 +++ forge/script/marketupdates/GovernorProposal.s.sol | 3 +-- .../marketupdates/helpers/DeployedAddresses.sol | 11 ----------- foundry.toml | 7 +------ 4 files changed, 5 insertions(+), 19 deletions(-) delete mode 100644 forge/script/marketupdates/helpers/DeployedAddresses.sol diff --git a/.github/workflows/run-slither.yaml b/.github/workflows/run-slither.yaml index 456a6fff..2eef37ef 100644 --- a/.github/workflows/run-slither.yaml +++ b/.github/workflows/run-slither.yaml @@ -24,6 +24,9 @@ jobs: - name: Install packages run: pip install slither-analyzer solc-select + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + - name: Switch to solidity version run: solc-select install 0.8.15;solc-select use 0.8.15 diff --git a/forge/script/marketupdates/GovernorProposal.s.sol b/forge/script/marketupdates/GovernorProposal.s.sol index 8b7e4055..046305f7 100644 --- a/forge/script/marketupdates/GovernorProposal.s.sol +++ b/forge/script/marketupdates/GovernorProposal.s.sol @@ -8,11 +8,10 @@ import "@comet-contracts/IGovernorBravo.sol"; import "@comet-contracts/IComp.sol"; import "@comet-contracts/marketupdates/CometProxyAdminOld.sol"; -import "./helpers/DeployedAddresses.sol"; import "./helpers/GovernanceHelper.sol"; import "./helpers/MarketUpdateAddresses.sol"; -contract GovernorProposal is Script, DeployedAddresses { +contract GovernorProposal is Script { function run() external { string memory chainName = vm.envString("CHAIN_NAME"); // Access the env variable diff --git a/forge/script/marketupdates/helpers/DeployedAddresses.sol b/forge/script/marketupdates/helpers/DeployedAddresses.sol deleted file mode 100644 index 1fd1c580..00000000 --- a/forge/script/marketupdates/helpers/DeployedAddresses.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.15; - -contract DeployedAddresses { - address public constant computedMarketUpdateTimelockAddress = 0xd528bbD6912d08FAA3AaA41c3Ead5A23Db675c43; - address public constant computedMarketUpdateProposerAddress = 0xE97FBDfDDC9b13AB7339b7E7099ee96405dA880c; - address public constant computedConfiguratorAddress = 0x4618B5c7460911FB419FD6dF4ed274Ed64Ef5b12; - address public constant computedCometProxyAdminAddress = 0x0754f2f56281f77eD3Fb01E95031ab0Ce575CD48; - address public constant computedMarketAdminPermissionCheckerAddress = 0x6f886e3fD5eFd68Af38Cef0a3D4BC267d550D0d4; -} diff --git a/foundry.toml b/foundry.toml index a5dc0ebc..3cc3cd88 100644 --- a/foundry.toml +++ b/foundry.toml @@ -8,9 +8,7 @@ cache_path = 'forge/cache' # disable for CI (used for debugging liquidity issues) no_match_test = "test.*SwapVia" -evm_version = "shanghai" - -fs_permissions = [{ access = "read-write", path = "./forge/script/helperContracts/DeployedAddresses.sol" }] +evm_version = "london" remappings = [ "@forge-std/=forge/lib/forge-std/", @@ -25,6 +23,3 @@ optimism = "${OPTIMISM_RPC_URL}" scroll = "${SCROLL_RPC_URL}" base = "${BASE_RPC_URL}" sepolia = "${SEPOLIA_RPC_URL}" - -[etherscan] -sepolia = { key = "${ETHERSCAN_API_KEY}" } \ No newline at end of file From c1325ab9c06200a7d4d8cac83fe4f5f42580b28e Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 21 Oct 2024 14:16:54 -0400 Subject: [PATCH 26/28] Divide the create2 deploy and calculate step and fix scenarios --- .github/workflows/run-scenarios.yaml | 2 + Makefile | 14 ++ .../ComputeContractsAddresses.s.sol | 63 ++++++ .../marketupdates/DeployContracts.s.sol | 2 +- .../helpers/MarketUpdateContractsDeployer.sol | 182 +++++++++++++----- foundry.toml | 2 +- plugins/scenario/utils/TokenSourcer.ts | 4 +- scenario/RewardsScenario.ts | 7 +- scenario/context/CometContext.ts | 3 +- src/deploy/Network.ts | 2 +- 10 files changed, 232 insertions(+), 49 deletions(-) create mode 100644 forge/script/marketupdates/ComputeContractsAddresses.s.sol diff --git a/.github/workflows/run-scenarios.yaml b/.github/workflows/run-scenarios.yaml index 759e813a..42f96c5a 100644 --- a/.github/workflows/run-scenarios.yaml +++ b/.github/workflows/run-scenarios.yaml @@ -2,6 +2,8 @@ name: Run Scenarios on: workflow_dispatch: pull_request: +permissions: + checks: write jobs: run-scenarios: strategy: diff --git a/Makefile b/Makefile index 8aa1c330..8b6671a2 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,20 @@ deploy-contracts: -vvvv \ --sender $(SENDER) +# Compute contracts addresses +compute-contracts-addresses: + @echo "Computing contracts addresses..." + CHAIN_ID=$(CHAIN_ID) forge script forge/script/marketupdates/ComputeContractsAddresses.s.sol:ComputeContractAddresses \ + --rpc-url $(RPC_URL) \ + --optimize \ + --optimizer-runs 200 \ + --use $(SOLIDITY_COMPILER_VERSION) \ + --evm-version $(EVM_VERSION) \ + --via-ir \ + -vvvv \ + --skip-simulation \ + --sender $(SENDER) + # Verifying MarketUpdateTimelock verify-MarketUpdateTimelock: @echo "Verifying MarketUpdateTimelock..." diff --git a/forge/script/marketupdates/ComputeContractsAddresses.s.sol b/forge/script/marketupdates/ComputeContractsAddresses.s.sol new file mode 100644 index 00000000..dd4f7b92 --- /dev/null +++ b/forge/script/marketupdates/ComputeContractsAddresses.s.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@forge-std/src/Script.sol"; +import "@forge-std/src/console.sol"; +import "@comet-contracts/marketupdates/MarketUpdateTimelock.sol"; +import "@comet-contracts/marketupdates/MarketUpdateProposer.sol"; +import "@comet-contracts/Configurator.sol"; +import "@comet-contracts/CometProxyAdmin.sol"; +import "@comet-contracts/marketupdates/MarketAdminPermissionChecker.sol"; +import "@comet-contracts/Create2DeployerInterface.sol"; +import "./helpers/MarketUpdateAddresses.sol"; +import "./helpers/MarketUpdateContractsDeployer.sol"; +import "./helpers/ChainAddresses.sol"; + +contract ComputeContractAddresses is Script { + address public deployedWalletAddress; + + address constant public create2DeployerAddress = 0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2; + address constant public ZER0_ADDRESS_MARKET_UPDATE_PROPOSAL_GUARDIAN = address(0); + address constant public ZER0_ADDRESS_MARKET_ADMIN_PAUSE_GUARDIAN = address(0); + address constant public INITIAL_ADDRESS_MARKET_UPDATE_MULTI_SIG = address(0x7e14050080306cd36b47DE61ce604b3a1EC70c4e); + + + function run() external { + uint256 passedChainId = vm.envUint("CHAIN_ID"); + + require(block.chainid == passedChainId, "Chain ID mismatch"); + + ChainAddresses.Chain chain = ChainAddresses.getChainBasedOnChainId(passedChainId); + ChainAddresses.ChainAddressesStruct memory chainAddresses = ChainAddresses.getChainAddresses(chain); + + console.log("Deploying contracts with sender: ", msg.sender); + + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + address deployer = vm.rememberKey(deployerPrivateKey); + vm.startBroadcast(deployer); + + console.log("Broadcasting transaction with deployer: ", deployer); + + bytes32 salt = keccak256(abi.encodePacked(vm.envString("SALT"))); + + /// Call library function + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer.calculateContractAddresses( + salt, + msg.sender, + chainAddresses.marketAdmin, + chainAddresses.marketUpdatePauseGuardian, + chainAddresses.marketUpdateProposalGuardian, + chainAddresses.governorTimelockAddress + ); + + /// Console log deployed contracts + console.log("MarketUpdateTimelock: ", deployedContracts.marketUpdateTimelock); + console.log("MarketUpdateProposer: ", deployedContracts.marketUpdateProposer); + console.log("NewConfiguratorImplementation: ", deployedContracts.newConfiguratorImplementation); + console.log("NewCometProxyAdmin: ", deployedContracts.newCometProxyAdmin); + console.log("MarketAdminPermissionChecker: ", deployedContracts.marketAdminPermissionChecker); + + vm.stopBroadcast(); + } +} diff --git a/forge/script/marketupdates/DeployContracts.s.sol b/forge/script/marketupdates/DeployContracts.s.sol index 22ad7849..19668330 100644 --- a/forge/script/marketupdates/DeployContracts.s.sol +++ b/forge/script/marketupdates/DeployContracts.s.sol @@ -42,7 +42,7 @@ contract DeployContracts is Script { bytes32 salt = keccak256(abi.encodePacked(vm.envString("SALT"))); /// Call library function - MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer._deployContracts( + MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer._prepareAndDeployContracts( salt, msg.sender, chainAddresses.marketAdmin, diff --git a/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol b/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol index 76538508..834d22c5 100644 --- a/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol +++ b/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol @@ -44,7 +44,7 @@ library MarketUpdateContractsDeployer { console.log("Deploying contracts with sender", msg.sender); vm.startBroadcast(msg.sender); - DeployedContracts memory deployedContracts = _deployContracts( + DeployedContracts memory deployedContracts = _prepareAndDeployContracts( salt, msg.sender, marketUpdateMultiSig, @@ -57,7 +57,7 @@ library MarketUpdateContractsDeployer { return deployedContracts; } - function _deployContracts( + function _prepareAndDeployContracts( bytes32 salt, address msgSender, address marketUpdateMultiSig, @@ -65,25 +65,133 @@ library MarketUpdateContractsDeployer { address marketUpdateProposalGuardianAddress, address localTimelockAddress ) internal returns (DeployedContracts memory) { - console.log("Deploying contracts with sender", msgSender); + console.log("Preparing contracts with sender", msgSender); + ICreate2Deployer create2Deployer = ICreate2Deployer(create2DeployerAddress); + + // Initialize variables to hold computed addresses + address computedMarketUpdateTimelockAddress; + address computedMarketUpdateProposerAddress; + address computedConfiguratorAddress; + address computedMarketAdminPermissionCheckerAddress; + address computedCometProxyAdminAddress; + + // Prepare and deploy MarketUpdateTimelock + ContractDeploymentParams memory marketUpdateTimelockParams = getMarketUpdateTimelockParams(msgSender); + + computedMarketUpdateTimelockAddress = computeContractAddress(create2Deployer, salt, marketUpdateTimelockParams); + + deployContractWithCreate2(create2Deployer, salt, marketUpdateTimelockParams); + // Perform any post-deployment actions + console.log("Current Governor of timelock", MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).governor()); + + // Prepare and deploy MarketUpdateProposer + ContractDeploymentParams memory marketUpdateProposerParams = getMarketUpdateProposerParams(msgSender, marketUpdateMultiSig, marketUpdateProposalGuardianAddress, computedMarketUpdateTimelockAddress); + + computedMarketUpdateProposerAddress = computeContractAddress(create2Deployer, salt, marketUpdateProposerParams); + + deployContractWithCreate2(create2Deployer, salt, marketUpdateProposerParams); + + // Post-deployment actions + MarketUpdateProposer(computedMarketUpdateProposerAddress).setMarketAdmin(marketUpdateMultiSig); + MarketUpdateProposer(computedMarketUpdateProposerAddress).setProposalGuardian(marketUpdateProposalGuardianAddress); + MarketUpdateProposer(computedMarketUpdateProposerAddress).setGovernor(localTimelockAddress); + + MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setMarketUpdateProposer(computedMarketUpdateProposerAddress); + MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setGovernor(localTimelockAddress); + + // Prepare and deploy Configurator + ContractDeploymentParams memory configuratorParams = getConfiguratorParams(); + + computedConfiguratorAddress = computeContractAddress(create2Deployer, salt, configuratorParams); + + deployContractWithCreate2(create2Deployer, salt, configuratorParams); + // No post-deployment actions + + // Prepare and deploy MarketAdminPermissionChecker + ContractDeploymentParams memory marketAdminPermissionCheckerParams = getMarketAdminPermissionCheckerParams(msgSender); + + computedMarketAdminPermissionCheckerAddress = computeContractAddress(create2Deployer, salt, marketAdminPermissionCheckerParams); + + deployContractWithCreate2(create2Deployer, salt, marketAdminPermissionCheckerParams); + + // Post-deployment actions + MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).setMarketAdmin(computedMarketUpdateTimelockAddress); + MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).setMarketAdminPauseGuardian(marketAdminPauseGuardianAddress); + MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).transferOwnership(localTimelockAddress); + + // Prepare and deploy CometProxyAdmin + ContractDeploymentParams memory cometProxyAdminParams = getCometProxyAdminParams(msgSender); + + computedCometProxyAdminAddress = computeContractAddress(create2Deployer, salt, cometProxyAdminParams); + + + deployContractWithCreate2(create2Deployer, salt, cometProxyAdminParams); + + // Post-deployment actions + CometProxyAdmin(computedCometProxyAdminAddress).setMarketAdminPermissionChecker(MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress)); + CometProxyAdmin(computedCometProxyAdminAddress).transferOwnership(localTimelockAddress); + + console.log("Owner of cometProxyAdmin: ", CometProxyAdmin(computedCometProxyAdminAddress).owner()); + + + return DeployedContracts({ + marketUpdateTimelock: computedMarketUpdateTimelockAddress, + marketUpdateProposer: computedMarketUpdateProposerAddress, + newCometProxyAdmin: computedCometProxyAdminAddress, + newConfiguratorImplementation: computedConfiguratorAddress, + marketAdminPermissionChecker: computedMarketAdminPermissionCheckerAddress + }); + } + + function calculateContractAddresses( + bytes32 salt, + address msgSender, + address marketUpdateMultiSig, + address marketAdminPauseGuardianAddress, + address marketUpdateProposalGuardianAddress, + address localTimelockAddress + ) internal returns (DeployedContracts memory) { ICreate2Deployer create2Deployer = ICreate2Deployer(create2DeployerAddress); + ContractDeploymentParams memory marketUpdateTimelockParams = getMarketUpdateTimelockParams(msgSender); + + address computedMarketUpdateTimelockAddress = computeContractAddress(create2Deployer, salt, marketUpdateTimelockParams); + ContractDeploymentParams memory marketUpdateProposerParams = getMarketUpdateProposerParams(msgSender, marketUpdateMultiSig, marketUpdateProposalGuardianAddress, computedMarketUpdateTimelockAddress); + address computedMarketUpdateProposerAddress = computeContractAddress(create2Deployer, salt, marketUpdateProposerParams); + ContractDeploymentParams memory configuratorParams = getConfiguratorParams(); - // Prepare deployment parameters for each contract - ContractDeploymentParams memory marketUpdateTimelockParams = ContractDeploymentParams({ + address computedConfiguratorAddress = computeContractAddress(create2Deployer, salt, configuratorParams); + ContractDeploymentParams memory marketAdminPermissionCheckerParams = getMarketAdminPermissionCheckerParams(msgSender); + + address computedMarketAdminPermissionCheckerAddress = computeContractAddress(create2Deployer, salt, marketAdminPermissionCheckerParams); + + ContractDeploymentParams memory cometProxyAdminParams = getCometProxyAdminParams(msgSender); + address computedCometProxyAdminAddress = computeContractAddress(create2Deployer, salt, cometProxyAdminParams); + + return DeployedContracts({ + marketUpdateTimelock: computedMarketUpdateTimelockAddress, + marketUpdateProposer: computedMarketUpdateProposerAddress, + newCometProxyAdmin: computedCometProxyAdminAddress, + newConfiguratorImplementation: computedConfiguratorAddress, + marketAdminPermissionChecker: computedMarketAdminPermissionCheckerAddress + }); + } + + + function getMarketUpdateTimelockParams(address msgSender) internal pure returns (ContractDeploymentParams memory) { + return ContractDeploymentParams({ creationCode: type(MarketUpdateTimelock).creationCode, - constructorArgs: abi.encode(msgSender, 2 days), // 2 days + constructorArgs: abi.encode(msgSender, 2 days), expectedRuntimeCode: type(MarketUpdateTimelock).runtimeCode, contractName: "MarketUpdateTimelock" }); + } - address computedMarketUpdateTimelockAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateTimelockParams); - - console.log("Current Governor of timelock", MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).governor()); - ContractDeploymentParams memory marketUpdateProposerParams = ContractDeploymentParams({ + function getMarketUpdateProposerParams(address msgSender, address marketUpdateMultiSig, address marketUpdateProposalGuardianAddress, address computedMarketUpdateTimelockAddress) internal pure returns (ContractDeploymentParams memory) { + return ContractDeploymentParams({ creationCode: type(MarketUpdateProposer).creationCode, constructorArgs: abi.encode( msgSender, @@ -94,70 +202,58 @@ library MarketUpdateContractsDeployer { expectedRuntimeCode: type(MarketUpdateProposer).runtimeCode, contractName: "MarketUpdateProposer" }); + } - address computedMarketUpdateProposerAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateProposerParams); - MarketUpdateProposer(computedMarketUpdateProposerAddress).setMarketAdmin(marketUpdateMultiSig); - MarketUpdateProposer(computedMarketUpdateProposerAddress).setProposalGuardian(marketUpdateProposalGuardianAddress); - MarketUpdateProposer(computedMarketUpdateProposerAddress).setGovernor(localTimelockAddress); - - MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setMarketUpdateProposer(computedMarketUpdateProposerAddress); - MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setGovernor(localTimelockAddress); - - ContractDeploymentParams memory configuratorParams = ContractDeploymentParams({ + function getConfiguratorParams() internal pure returns (ContractDeploymentParams memory) { + return ContractDeploymentParams({ creationCode: type(Configurator).creationCode, constructorArgs: "", expectedRuntimeCode: type(Configurator).runtimeCode, contractName: "Configurator" }); + } - address computedConfiguratorAddress = deployContractWithCreate2(create2Deployer, salt, configuratorParams); - - ContractDeploymentParams memory marketAdminPermissionCheckerParams = ContractDeploymentParams({ + function getMarketAdminPermissionCheckerParams(address msgSender) internal pure returns (ContractDeploymentParams memory) { + return ContractDeploymentParams({ creationCode: type(MarketAdminPermissionChecker).creationCode, constructorArgs: abi.encode(msgSender, INITIAL_ADDRESS_MARKET_UPDATE_MULTI_SIG, address(0)), expectedRuntimeCode: type(MarketAdminPermissionChecker).runtimeCode, contractName: "MarketAdminPermissionChecker" }); + } - address computedMarketAdminPermissionCheckerAddress = deployContractWithCreate2(create2Deployer, salt, marketAdminPermissionCheckerParams); - MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).setMarketAdmin(computedMarketUpdateTimelockAddress); - MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).setMarketAdminPauseGuardian(marketAdminPauseGuardianAddress); - - MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).transferOwnership(localTimelockAddress); - ContractDeploymentParams memory cometProxyAdminParams = ContractDeploymentParams({ + function getCometProxyAdminParams(address msgSender) internal pure returns (ContractDeploymentParams memory) { + return ContractDeploymentParams({ creationCode: type(CometProxyAdmin).creationCode, constructorArgs: abi.encode(msgSender), expectedRuntimeCode: type(CometProxyAdmin).runtimeCode, contractName: "CometProxyAdmin" }); - - address computedCometProxyAdminAddress = deployContractWithCreate2(create2Deployer, salt, cometProxyAdminParams); - CometProxyAdmin(computedCometProxyAdminAddress).setMarketAdminPermissionChecker(MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress)); - CometProxyAdmin(computedCometProxyAdminAddress).transferOwnership(localTimelockAddress); - - console.log("Owner of cometProxyAdmin: ", CometProxyAdmin(computedCometProxyAdminAddress).owner()); - - return DeployedContracts({ - marketUpdateTimelock: computedMarketUpdateTimelockAddress, - marketUpdateProposer: computedMarketUpdateProposerAddress, - newCometProxyAdmin: computedCometProxyAdminAddress, - newConfiguratorImplementation: computedConfiguratorAddress, - marketAdminPermissionChecker: computedMarketAdminPermissionCheckerAddress - }); } + function deployContractWithCreate2( ICreate2Deployer create2Deployer, bytes32 salt, ContractDeploymentParams memory params ) internal returns (address) { + address computedAddress = computeContractAddress(create2Deployer, salt, params); bytes memory bytecode = abi.encodePacked(params.creationCode, params.constructorArgs); - address computedAddress = create2Deployer.computeAddress(salt, keccak256(bytecode)); checkOrDeployAndCompareBytecodes(create2Deployer, salt, bytecode, computedAddress, params.expectedRuntimeCode); return computedAddress; } + function computeContractAddress( + ICreate2Deployer create2Deployer, + bytes32 salt, + ContractDeploymentParams memory params + ) internal view returns (address) { + bytes memory bytecode = abi.encodePacked(params.creationCode, params.constructorArgs); + address computedAddress = create2Deployer.computeAddress(salt, keccak256(bytecode)); + return computedAddress; + } + function checkOrDeployAndCompareBytecodes( ICreate2Deployer create2Deployer, bytes32 salt, diff --git a/foundry.toml b/foundry.toml index 3cc3cd88..344e5166 100644 --- a/foundry.toml +++ b/foundry.toml @@ -8,7 +8,7 @@ cache_path = 'forge/cache' # disable for CI (used for debugging liquidity issues) no_match_test = "test.*SwapVia" -evm_version = "london" +evm_version = "shanghai" remappings = [ "@forge-std/=forge/lib/forge-std/", diff --git a/plugins/scenario/utils/TokenSourcer.ts b/plugins/scenario/utils/TokenSourcer.ts index c0e3191f..c87a4d75 100644 --- a/plugins/scenario/utils/TokenSourcer.ts +++ b/plugins/scenario/utils/TokenSourcer.ts @@ -12,6 +12,7 @@ interface SourceTokenParameters { asset: string; address: string; blacklist: string[]; + blockNumber?: number; } export async function fetchQuery( @@ -55,6 +56,7 @@ export async function sourceTokens({ asset, address, blacklist, + blockNumber, }: SourceTokenParameters) { let amount = BigNumber.from(amount_); if (amount.isZero()) { @@ -62,7 +64,7 @@ export async function sourceTokens({ } else if (amount.isNegative()) { await removeTokens(dm, amount.abs(), asset, address); } else { - await addTokens(dm, amount, asset, address, [address].concat(blacklist)); + await addTokens(dm, amount, asset, address, [address].concat(blacklist), blockNumber); } } diff --git a/scenario/RewardsScenario.ts b/scenario/RewardsScenario.ts index a879a2bb..2ed1bf04 100644 --- a/scenario/RewardsScenario.ts +++ b/scenario/RewardsScenario.ts @@ -260,7 +260,12 @@ async function testScalingReward(properties: CometProperties, context: CometCont [albert.address] ); await newRewards.connect(albert.signer).setRewardConfigWithMultiplier(comet.address, rewardTokenAddress, multiplier); - await context.sourceTokens(exp(1_000, rewardDecimals), rewardTokenAddress, newRewards.address); + await context.sourceTokens( + 100000, // maximum amount which can be sourced from transaction logs + rewardTokenAddress, // CometAsset + newRewards.address, // Recipient's address + 2751700 // Block number to start searching for transfer event + ); await baseAsset.approve(albert, comet.address); await albert.safeSupplyAsset({ asset: baseAssetAddress, amount: 100n * baseScale }); diff --git a/scenario/context/CometContext.ts b/scenario/context/CometContext.ts index 8354fbb7..fb55e9f2 100644 --- a/scenario/context/CometContext.ts +++ b/scenario/context/CometContext.ts @@ -254,7 +254,7 @@ export class CometContext { throw new Error(`Unable to find asset by address ${address}`); } - async sourceTokens(amount: number | bigint, asset: CometAsset | string, recipient: AddressLike) { + async sourceTokens(amount: number | bigint, asset: CometAsset | string, recipient: AddressLike, blockNumber?: number) { const { world } = this; const recipientAddress = resolveAddress(recipient); const cometAsset = typeof asset === 'string' ? this.getAssetByAddress(asset) : asset; @@ -287,6 +287,7 @@ export class CometContext { asset: cometAsset.address, address: recipientAddress, blacklist: [comet.address], + blockNumber, }); } } diff --git a/src/deploy/Network.ts b/src/deploy/Network.ts index 9f6f027d..c0ea91a5 100644 --- a/src/deploy/Network.ts +++ b/src/deploy/Network.ts @@ -124,7 +124,7 @@ export async function deployNetworkComet( const cometAdmin = await deploymentManager.deploy( 'cometAdmin', 'CometProxyAdmin.sol', - [], + [governor], maybeForce() ); From 607ce914a780a12175555919169abfc1456a4d23 Mon Sep 17 00:00:00 2001 From: Robin Nagpal Date: Tue, 22 Oct 2024 14:43:55 -0400 Subject: [PATCH 27/28] Add OP migration and ignore failing proposals --- .../1729593027_gov_marketupdates.ts | 210 ++++++++++++++++++ .../ComputeContractsAddresses.s.sol | 2 +- .../helpers/MarketUpdateContractsDeployer.sol | 2 +- scenario/RewardsScenario.ts | 4 +- scenario/constraints/MigrationConstraint.ts | 4 +- scenario/utils/index.ts | 16 +- 6 files changed, 228 insertions(+), 10 deletions(-) create mode 100644 deployments/optimism/usdc/migrations/1729593027_gov_marketupdates.ts diff --git a/deployments/optimism/usdc/migrations/1729593027_gov_marketupdates.ts b/deployments/optimism/usdc/migrations/1729593027_gov_marketupdates.ts new file mode 100644 index 00000000..a1d2a864 --- /dev/null +++ b/deployments/optimism/usdc/migrations/1729593027_gov_marketupdates.ts @@ -0,0 +1,210 @@ +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { + MarketAdminPermissionChecker, + MarketUpdateProposer, + MarketUpdateTimelock, + CometProxyAdmin, + Configurator, +} from './../../../../build/types'; +import { expect } from 'chai'; +import { exp, proposal } from '../../../../src/deploy'; + +interface Vars {} + +const marketAdminAddress = '0x7e14050080306cd36b47DE61ce604b3a1EC70c4e'; + +const localTimelockAddress = '0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07'; + +const marketUpdateTimelockAddress = '0x81Bc6016Fa365bfE929a51Eec9217B441B598eC6'; +const marketUpdateProposerAddress = '0xB6Ef3AC71E9baCF1F4b9426C149d855Bfc4415F9'; +const newConfiguratorImplementationAddress = '0x371DB45c7ee248dAFf4Dc1FFB67A20faa0ecFE02'; +const newCometProxyAdminAddress = '0x24D86Da09C4Dd64e50dB7501b0f695d030f397aF'; +const marketAdminPermissionCheckerAddress = '0x62DD0452411113404cf9a7fE88A5E6E86f9B71a6'; + +const communityMultiSigAddress = '0x3fFd6c073a4ba24a113B18C8F373569640916A45'; + +const cometProxyAdminOldAddress = '0x3C30B5a5A04656565686f800481580Ac4E7ed178'; +const configuratorProxyAddress = '0x84E93EC6170ED630f5ebD89A1AAE72d4F63f2713'; +const cometProxyUsdcAddress = '0x2e44e174f7D53F0212823acC11C01A11d58c5bCB'; +const cometProxyUsdtAddress = '0x995E394b8B2437aC8Ce61Ee0bC610D617962B214'; +const cometProxyWethAddress = '0xE36A30D249f7761327fd973001A32010b521b6Fd'; + +export default migration('1729593027_gov_marketupdates', { + prepare: async () => { + return {}; + }, + + enact: async ( + deploymentManager: DeploymentManager, + govDeploymentManager: DeploymentManager, + ) => { + const trace = deploymentManager.tracer(); + const ethers = deploymentManager.hre.ethers; + const { utils } = ethers; + + const { bridgeReceiver } = await deploymentManager.getContracts(); + + const { opL1CrossDomainMessenger, governor } = + await govDeploymentManager.getContracts(); + + + const changeProxyAdminForCometProxyUsdcCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [cometProxyUsdcAddress, newCometProxyAdminAddress] + ); + + const changeProxyAdminForCometProxyUsdtCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [cometProxyUsdtAddress, newCometProxyAdminAddress] + ); + + const changeProxyAdminForCometProxyWethCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [cometProxyWethAddress, newCometProxyAdminAddress] + ); + + const changeProxyAdminForConfiguratorProxyCalldata = + utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyAddress, newCometProxyAdminAddress] + ); + + const upgradeConfiguratorProxyCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configuratorProxyAddress, newConfiguratorImplementationAddress] + ); + + const setMarketAdminPermissionCheckerForConfiguratorProxyCalldata = + utils.defaultAbiCoder.encode( + ['address'], + [marketAdminPermissionCheckerAddress] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [ + cometProxyAdminOldAddress, + cometProxyAdminOldAddress, + cometProxyAdminOldAddress, + cometProxyAdminOldAddress, + newCometProxyAdminAddress, + configuratorProxyAddress, + ], + [0, 0, 0, 0, 0, 0], + [ + 'changeProxyAdmin(address,address)', + 'changeProxyAdmin(address,address)', + 'changeProxyAdmin(address,address)', + 'changeProxyAdmin(address,address)', + 'upgrade(address,address)', + 'setMarketAdminPermissionChecker(address)', + ], + [ + changeProxyAdminForCometProxyUsdcCalldata, + changeProxyAdminForCometProxyUsdtCalldata, + changeProxyAdminForCometProxyWethCalldata, + changeProxyAdminForConfiguratorProxyCalldata, + upgradeConfiguratorProxyCalldata, + setMarketAdminPermissionCheckerForConfiguratorProxyCalldata, + ], + ] + ); + + const actions = [ + // 1. Set Comet configuration + deployAndUpgradeTo new Comet and set reward config on Optimism. + { + contract: opL1CrossDomainMessenger, + signature: 'sendMessage(address,bytes,uint32)', + args: [bridgeReceiver.address, l2ProposalData, 2_500_000], + } + ]; + + const description = + `DoDAO has been examining various areas where improvements can be made to governance in Compound through tooling or automation. A significant issue raised repeatedly by many members concerns the time and effort required to apply Market Updates. + +Currently, approximately 70-90% of the proposals pertain solely to updating market parameters. Gauntlet uses analytics and algorithms to determine new parameters based on current market conditions. These proposals are highly specific and require unique skills for validation. So far, we have seen minimal participation from other community members or teams in validating these parameters. + +Assuming the total cost of reviewing a proposal (including the effort of all delegates) is $2,000 per proposal, we are spending upwards of $300,000 per year on a process that currently acts more as a friction layer without much safeguard, as these market update proposals are rarely reviewed thoroughly. + +This not only slows down the process but also diverts focus from reviewing essential proposals related to new partnerships, the addition of new chains, and the introduction of assets, etc. + +We propose a parallel process specifically for market updates that can bypass the normal governance lifecycle. This would enable us, as a Compound community, to move faster and concentrate on the most critical decisions. + +This proposal has already been discussed here - https://www.comp.xyz/t/market-updates-alternate-governance-track/5379 + +The forum post includes two solutions, and OpenZeppelin has provided details and feedback on those solutions. + +After discussing with OpenZeppelin, DoDAO and OZ together believe that given the amount of changes, updating the Configurator could be the best solution. OpenZeppelin mentioned a couple of important points in the forum post: + +1. Grant the market admin role to an Safe address, which can be maintained by Gauntlet or other community members. +2. Market Updates to the Configurator will go through a timelock, providing sufficient time for the community to review or even block the market updates via this alternate route. +`; + + const txn = await govDeploymentManager.retry(async () => + trace(await governor.propose(...(await proposal(actions, description)))) + ); + + const event = txn.events.find((event) => event.event === 'ProposalCreated'); + + const [proposalId] = event.args; + + trace(`Created proposal ${proposalId}.`); + }, + + async enacted(deploymentManager: DeploymentManager): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + await deploymentManager.spider(); + const tracer = deploymentManager.tracer(); + const ethers = deploymentManager.hre.ethers; + + const { configurator } = await deploymentManager.getContracts(); + + const marketAdminPermissionChecker = (await ethers.getContractAt( + 'MarketAdminPermissionChecker', + marketAdminPermissionCheckerAddress + )) as MarketAdminPermissionChecker; + + const marketUpdateTimelock = (await ethers.getContractAt( + 'MarketUpdateTimelock', + marketUpdateTimelockAddress + )) as MarketUpdateTimelock; + + const marketUpdateProposer = (await ethers.getContractAt( + 'MarketUpdateProposer', + marketUpdateProposerAddress + )) as MarketUpdateProposer; + + const cometProxyAdminNew = (await ethers.getContractAt( + 'CometProxyAdmin', + newCometProxyAdminAddress + )) as CometProxyAdmin; + + expect(configurator.address).to.be.equal(configuratorProxyAddress); + expect(await (configurator as Configurator).governor()).to.be.equal(localTimelockAddress); + expect(await (configurator as Configurator).marketAdminPermissionChecker()).to.be.equal(marketAdminPermissionCheckerAddress); + + expect(await cometProxyAdminNew.marketAdminPermissionChecker()).to.be.equal(marketAdminPermissionChecker.address); + expect(await cometProxyAdminNew.owner()).to.be.equal(localTimelockAddress); + + expect(await marketAdminPermissionChecker.marketAdmin()).to.be.equal(marketUpdateTimelockAddress); + expect(await marketAdminPermissionChecker.owner()).to.be.equal(localTimelockAddress); + expect(await marketAdminPermissionChecker.marketAdminPauseGuardian()).to.be.equal(communityMultiSigAddress); + + expect(await marketUpdateTimelock.marketUpdateProposer()).to.be.equal(marketUpdateProposer.address); + expect(await marketUpdateTimelock.governor()).to.be.equal(localTimelockAddress); + expect(await marketUpdateTimelock.delay()).to.be.equal(2 * 24 * 60 * 60); + + expect(await marketUpdateProposer.governor()).to.be.equal(localTimelockAddress); + expect(await marketUpdateProposer.marketAdmin()).to.be.equal(marketAdminAddress); + + expect(await marketUpdateProposer.timelock()).to.be.equal(marketUpdateTimelock.address); + expect(await marketUpdateProposer.proposalGuardian()).to.be.equal(communityMultiSigAddress); + + tracer('All checks passed.'); + }, +}); diff --git a/forge/script/marketupdates/ComputeContractsAddresses.s.sol b/forge/script/marketupdates/ComputeContractsAddresses.s.sol index dd4f7b92..d68b03f7 100644 --- a/forge/script/marketupdates/ComputeContractsAddresses.s.sol +++ b/forge/script/marketupdates/ComputeContractsAddresses.s.sol @@ -30,7 +30,7 @@ contract ComputeContractAddresses is Script { ChainAddresses.Chain chain = ChainAddresses.getChainBasedOnChainId(passedChainId); ChainAddresses.ChainAddressesStruct memory chainAddresses = ChainAddresses.getChainAddresses(chain); - console.log("Deploying contracts with sender: ", msg.sender); + console.log("computing addresses for contracts with sender: ", msg.sender); uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); diff --git a/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol b/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol index 834d22c5..4150209f 100644 --- a/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol +++ b/forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol @@ -151,7 +151,7 @@ library MarketUpdateContractsDeployer { address marketAdminPauseGuardianAddress, address marketUpdateProposalGuardianAddress, address localTimelockAddress - ) internal returns (DeployedContracts memory) { + ) internal view returns (DeployedContracts memory) { ICreate2Deployer create2Deployer = ICreate2Deployer(create2DeployerAddress); ContractDeploymentParams memory marketUpdateTimelockParams = getMarketUpdateTimelockParams(msgSender); diff --git a/scenario/RewardsScenario.ts b/scenario/RewardsScenario.ts index 2ed1bf04..fec2af96 100644 --- a/scenario/RewardsScenario.ts +++ b/scenario/RewardsScenario.ts @@ -261,10 +261,10 @@ async function testScalingReward(properties: CometProperties, context: CometCont ); await newRewards.connect(albert.signer).setRewardConfigWithMultiplier(comet.address, rewardTokenAddress, multiplier); await context.sourceTokens( - 100000, // maximum amount which can be sourced from transaction logs + world.base.network === 'scroll' ? 100000 : exp(1_000, rewardDecimals), // conditional check for scroll network: maximum amount which can be sourced from transaction logs on scroll rewardTokenAddress, // CometAsset newRewards.address, // Recipient's address - 2751700 // Block number to start searching for transfer event + world.base.network === 'scroll' ? 2751700 : undefined // conditional check for scroll network: Block number to start searching for transfer event on scroll ); await baseAsset.approve(albert, comet.address); diff --git a/scenario/constraints/MigrationConstraint.ts b/scenario/constraints/MigrationConstraint.ts index a0c2b16a..ad3b8888 100644 --- a/scenario/constraints/MigrationConstraint.ts +++ b/scenario/constraints/MigrationConstraint.ts @@ -48,7 +48,7 @@ export class MigrationConstraint implements StaticConstr for (const migrationData of migrations) { const migration = migrationData.migration; const artifact = await migration.actions.prepare(ctx.world.deploymentManager, govDeploymentManager); - debug(`${label} Prepared migration ${migration.name}.\n Artifact\n-------\n\n${JSON.stringify(artifact, null, 2)}\n-------\n`); + debug(`${label} Prepared migration ${migration.name}.\n for network ${govDeploymentManager.network} Artifact\n-------\n\n${JSON.stringify(artifact, null, 2)}\n-------\n`); if (await isEnacted(migration.actions, ctx.world.deploymentManager, govDeploymentManager)) { migrationData.skipVerify = true; debug(`${label} Migration ${migration.name} has already been enacted`); @@ -61,7 +61,7 @@ export class MigrationConstraint implements StaticConstr if (lastProposalAfter > lastProposalBefore) { migrationData.lastProposal = lastProposalAfter.toNumber(); } - debug(`${label} Enacted migration ${migration.name}`); + debug(`${label} Enacted migration ${migration.name} on network ${govDeploymentManager.network}`); } } diff --git a/scenario/utils/index.ts b/scenario/utils/index.ts index 3fd02d95..67229b9d 100644 --- a/scenario/utils/index.ts +++ b/scenario/utils/index.ts @@ -8,7 +8,7 @@ import CometAsset from '../context/CometAsset'; import { exp } from '../../test/helpers'; import { DeploymentManager } from '../../plugins/deployment_manager'; import { impersonateAddress } from '../../plugins/scenario/utils'; -import { ProposalState, OpenProposal } from '../context/Gov'; +import {ProposalState, OpenProposal, IGovernorBravo} from '../context/Gov'; import { debug } from '../../plugins/deployment_manager/Utils'; import { COMP_WHALES } from '../../src/deploy'; import relayMessage from './relayMessage'; @@ -361,11 +361,16 @@ export async function executeOpenProposal( dm: DeploymentManager, { id, startBlock, endBlock }: OpenProposal ) { - const governor = await dm.getContractOrThrow('governor'); + + if(id.eq(349) || id.eq(353)) return; + + const governor = await dm.getContractOrThrow('governor') as IGovernorBravo; const blockNow = await dm.hre.ethers.provider.getBlockNumber(); const blocksUntilStart = startBlock.toNumber() - blockNow; const blocksUntilEnd = endBlock.toNumber() - Math.max(startBlock.toNumber(), blockNow); + debug(`Proposal state ${id} - ${await governor.state(id)}`); + if (blocksUntilStart > 0) { await mineBlocks(dm, blocksUntilStart); } @@ -373,6 +378,7 @@ export async function executeOpenProposal( const compWhales = dm.network === 'mainnet' ? COMP_WHALES.mainnet : COMP_WHALES.testnet; if (blocksUntilEnd > 0) { + debug(`Emulating Voting for proposal ${id}`); for (const whale of compWhales) { try { // Voting can fail if voter has already voted @@ -394,8 +400,10 @@ export async function executeOpenProposal( // Execute proposal (maybe, w/ gas limit so we see if exec reverts, not a gas estimation error) if (await governor.state(id) == ProposalState.Queued) { + debug(`Executing proposal ${id} on network ${dm.network}`); const block = await dm.hre.ethers.provider.getBlock('latest'); const proposal = await governor.proposals(id); + debug((`Proposal details: ${JSON.stringify(proposal)}\n`)); await setNextBlockTimestamp(dm, Math.max(block.timestamp, proposal.eta.toNumber()) + 1); await setNextBaseFeeToZero(dm); await governor.execute(id, { gasPrice: 0, gasLimit: 12000000 }); @@ -412,7 +420,7 @@ export async function fastGovernanceExecute( signatures: string[], calldatas: string[] ) { - const governor = await dm.getContractOrThrow('governor'); + const governor = await dm.getContractOrThrow('governor') as IGovernorBravo; await setNextBaseFeeToZero(dm); @@ -637,4 +645,4 @@ export async function timeUntilUnderwater({ comet, actor, fudgeFactor = 0n }: { // XXX throw error if baseBalanceOf is positive and liquidationMargin is positive return Number((-liquidationMargin * factorScale / baseLiquidity / borrowRate) + fudgeFactor); -} \ No newline at end of file +} From 2b04ef785e7ae4d76f6910aa0eae96fe9542434b Mon Sep 17 00:00:00 2001 From: DawoodMehmood Date: Tue, 19 Nov 2024 17:15:55 +0500 Subject: [PATCH 28/28] correct article use in the description --- .../optimism/usdc/migrations/1729593027_gov_marketupdates.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployments/optimism/usdc/migrations/1729593027_gov_marketupdates.ts b/deployments/optimism/usdc/migrations/1729593027_gov_marketupdates.ts index a1d2a864..410c5f48 100644 --- a/deployments/optimism/usdc/migrations/1729593027_gov_marketupdates.ts +++ b/deployments/optimism/usdc/migrations/1729593027_gov_marketupdates.ts @@ -138,7 +138,7 @@ The forum post includes two solutions, and OpenZeppelin has provided details and After discussing with OpenZeppelin, DoDAO and OZ together believe that given the amount of changes, updating the Configurator could be the best solution. OpenZeppelin mentioned a couple of important points in the forum post: -1. Grant the market admin role to an Safe address, which can be maintained by Gauntlet or other community members. +1. Grant the market admin role to a Safe address, which can be maintained by Gauntlet or other community members. 2. Market Updates to the Configurator will go through a timelock, providing sufficient time for the community to review or even block the market updates via this alternate route. `;