From bba7d99db28cdc04b7d90c33a5c3402b59ec0618 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Fri, 9 Aug 2024 23:45:26 +0300 Subject: [PATCH 01/45] feat: create comet with extended asset list --- contracts/AssetList.sol | 126 ++ contracts/AssetListFactory.sol | 17 + contracts/CometExt.sol | 5 +- contracts/CometExtendedAssetList.sol | 1225 +++++++++++++++++ contracts/CometFactoryExtendedAssetList.sol | 11 + contracts/IAssetList.sol | 12 + contracts/IAssetListFactory.sol | 13 + ...pdate_comet_to_support_more_collaterals.ts | 112 ++ scenario/LiquidationBotScenario.ts | 2 +- src/deploy/Network.ts | 4 +- test/asset-info-test-asset-list-comet.ts | 184 +++ test/constructor-test.ts | 10 +- test/helpers.ts | 29 +- test/liquidation/makeLiquidatableProtocol.ts | 9 +- 14 files changed, 1748 insertions(+), 11 deletions(-) create mode 100644 contracts/AssetList.sol create mode 100644 contracts/AssetListFactory.sol create mode 100644 contracts/CometExtendedAssetList.sol create mode 100644 contracts/CometFactoryExtendedAssetList.sol create mode 100644 contracts/IAssetList.sol create mode 100644 contracts/IAssetListFactory.sol create mode 100644 deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts create mode 100644 test/asset-info-test-asset-list-comet.ts diff --git a/contracts/AssetList.sol b/contracts/AssetList.sol new file mode 100644 index 000000000..7fc91c3bc --- /dev/null +++ b/contracts/AssetList.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "./CometConfiguration.sol"; +import "./IPriceFeed.sol"; +import "./IERC20NonStandard.sol"; +import "./CometMainInterface.sol"; +import "./CometCore.sol"; + +/** + * @title Compound's Asset List + * @author Compound + */ +contract AssetList { + /// @dev The decimals required for a price feed + uint8 internal constant PRICE_FEED_DECIMALS = 8; + + /// @dev The scale for factors + uint64 internal constant FACTOR_SCALE = 1e18; + + /// @dev The max value for a collateral factor (1) + uint64 internal constant MAX_COLLATERAL_FACTOR = FACTOR_SCALE; + + uint256[] internal assets_a; + uint256[] internal assets_b; + + /// @notice The number of assets this contract actually supports + uint8 public immutable numAssets; + + constructor(CometConfiguration.AssetConfig[] memory assetConfigs) { + numAssets = uint8(assetConfigs.length); + for (uint i = 0; i < assetConfigs.length; i++) { + (uint256 asset_a, uint256 asset_b) = getPackedAssetInternal(assetConfigs, i); + assets_a.push(asset_a); + assets_b.push(asset_b); + } + } + + /** + * @dev Checks and gets the packed asset info for storage + */ + function getPackedAssetInternal(CometConfiguration.AssetConfig[] memory assetConfigs, uint i) internal view returns (uint256, uint256) { + CometConfiguration.AssetConfig memory assetConfig; + if (i < assetConfigs.length) { + assembly { + assetConfig := mload(add(add(assetConfigs, 0x20), mul(i, 0x20))) + } + } else { + return (0, 0); + } + address asset = assetConfig.asset; + address priceFeed = assetConfig.priceFeed; + uint8 decimals_ = assetConfig.decimals; + + // Short-circuit if asset is nil + if (asset == address(0)) { + return (0, 0); + } + + // Sanity check price feed and asset decimals + if (IPriceFeed(priceFeed).decimals() != PRICE_FEED_DECIMALS) revert CometMainInterface.BadDecimals(); + if (IERC20NonStandard(asset).decimals() != decimals_) revert CometMainInterface.BadDecimals(); + + // Ensure collateral factors are within range + if (assetConfig.borrowCollateralFactor >= assetConfig.liquidateCollateralFactor) revert CometMainInterface.BorrowCFTooLarge(); + if (assetConfig.liquidateCollateralFactor > MAX_COLLATERAL_FACTOR) revert CometMainInterface.LiquidateCFTooLarge(); + + unchecked { + // Keep 4 decimals for each factor + uint64 descale = FACTOR_SCALE / 1e4; + uint16 borrowCollateralFactor = uint16(assetConfig.borrowCollateralFactor / descale); + uint16 liquidateCollateralFactor = uint16(assetConfig.liquidateCollateralFactor / descale); + uint16 liquidationFactor = uint16(assetConfig.liquidationFactor / descale); + + // Be nice and check descaled values are still within range + if (borrowCollateralFactor >= liquidateCollateralFactor) revert CometMainInterface.BorrowCFTooLarge(); + + // Keep whole units of asset for supply cap + uint64 supplyCap = uint64(assetConfig.supplyCap / (10 ** decimals_)); + + uint256 word_a = (uint160(asset) << 0 | + uint256(borrowCollateralFactor) << 160 | + uint256(liquidateCollateralFactor) << 176 | + uint256(liquidationFactor) << 192); + uint256 word_b = (uint160(priceFeed) << 0 | + uint256(decimals_) << 160 | + uint256(supplyCap) << 168); + + return (word_a, word_b); + } + } + + /** + * @notice Get the i-th asset info, according to the order they were passed in originally + * @param i The index of the asset info to get + * @return The asset info object + */ + function getAssetInfo(uint8 i) public view returns (CometCore.AssetInfo memory) { + if (i >= numAssets) revert CometMainInterface.BadAsset(); + + uint256 word_a = assets_a[i]; + uint256 word_b = assets_b[i]; + + address asset = address(uint160(word_a & type(uint160).max)); + uint64 rescale = FACTOR_SCALE / 1e4; + uint64 borrowCollateralFactor = uint64(((word_a >> 160) & type(uint16).max) * rescale); + uint64 liquidateCollateralFactor = uint64(((word_a >> 176) & type(uint16).max) * rescale); + uint64 liquidationFactor = uint64(((word_a >> 192) & type(uint16).max) * rescale); + + address priceFeed = address(uint160(word_b & type(uint160).max)); + uint8 decimals_ = uint8(((word_b >> 160) & type(uint8).max)); + uint64 scale = uint64(10 ** decimals_); + uint128 supplyCap = uint128(((word_b >> 168) & type(uint64).max) * scale); + + return CometCore.AssetInfo({ + offset: i, + asset: asset, + priceFeed: priceFeed, + scale: scale, + borrowCollateralFactor: borrowCollateralFactor, + liquidateCollateralFactor: liquidateCollateralFactor, + liquidationFactor: liquidationFactor, + supplyCap: supplyCap + }); + } +} \ No newline at end of file diff --git a/contracts/AssetListFactory.sol b/contracts/AssetListFactory.sol new file mode 100644 index 000000000..52c190adc --- /dev/null +++ b/contracts/AssetListFactory.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "./AssetList.sol"; + +/** + * @title Compound's Asset List Factory + * @author Compound + */ +contract AssetListFactory { + event AssetListCreated(address indexed assetList, CometCore.AssetConfig[] assetConfigs); + + function createAssetList(CometCore.AssetConfig[] memory assetConfigs) external returns (address assetList) { + assetList = address(new AssetList(assetConfigs)); + emit AssetListCreated(assetList, assetConfigs); + } +} \ No newline at end of file diff --git a/contracts/CometExt.sol b/contracts/CometExt.sol index 46962b3ad..67b7645e7 100644 --- a/contracts/CometExt.sol +++ b/contracts/CometExt.sol @@ -29,13 +29,16 @@ contract CometExt is CometExtInterface { /// @dev The ERC20 symbol for wrapped base token bytes32 internal immutable symbol32; + address immutable public assetListFactory; + /** * @notice Construct a new protocol instance * @param config The mapping of initial/constant parameters **/ - constructor(ExtConfiguration memory config) { + constructor(ExtConfiguration memory config, address assetListFactoryAddress) { name32 = config.name32; symbol32 = config.symbol32; + assetListFactory = assetListFactoryAddress; } /** External getters for internal constants **/ diff --git a/contracts/CometExtendedAssetList.sol b/contracts/CometExtendedAssetList.sol new file mode 100644 index 000000000..57d9d6c09 --- /dev/null +++ b/contracts/CometExtendedAssetList.sol @@ -0,0 +1,1225 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "./CometMainInterface.sol"; +import "./IERC20NonStandard.sol"; +import "./IPriceFeed.sol"; +import "./IAssetListFactory.sol"; +import "./IAssetList.sol"; + +/** + * @title Compound's Comet Contract + * @notice An efficient monolithic money market protocol + * @author Compound + */ +contract CometExtendedAssetList is CometMainInterface { + /** General configuration constants **/ + + /// @notice The admin of the protocol + address public override immutable governor; + + /// @notice The account which may trigger pauses + address public override immutable pauseGuardian; + + /// @notice The address of the base token contract + address public override immutable baseToken; + + /// @notice The address of the price feed for the base token + address public override immutable baseTokenPriceFeed; + + /// @notice The address of the extension contract delegate + address public override immutable extensionDelegate; + + /// @notice The point in the supply rates separating the low interest rate slope and the high interest rate slope (factor) + /// @dev uint64 + uint public override immutable supplyKink; + + /// @notice Per second supply interest rate slope applied when utilization is below kink (factor) + /// @dev uint64 + uint public override immutable supplyPerSecondInterestRateSlopeLow; + + /// @notice Per second supply interest rate slope applied when utilization is above kink (factor) + /// @dev uint64 + uint public override immutable supplyPerSecondInterestRateSlopeHigh; + + /// @notice Per second supply base interest rate (factor) + /// @dev uint64 + uint public override immutable supplyPerSecondInterestRateBase; + + /// @notice The point in the borrow rate separating the low interest rate slope and the high interest rate slope (factor) + /// @dev uint64 + uint public override immutable borrowKink; + + /// @notice Per second borrow interest rate slope applied when utilization is below kink (factor) + /// @dev uint64 + uint public override immutable borrowPerSecondInterestRateSlopeLow; + + /// @notice Per second borrow interest rate slope applied when utilization is above kink (factor) + /// @dev uint64 + uint public override immutable borrowPerSecondInterestRateSlopeHigh; + + /// @notice Per second borrow base interest rate (factor) + /// @dev uint64 + uint public override immutable borrowPerSecondInterestRateBase; + + /// @notice The fraction of the liquidation penalty that goes to buyers of collateral instead of the protocol + /// @dev uint64 + uint public override immutable storeFrontPriceFactor; + + /// @notice The scale for base token (must be less than 18 decimals) + /// @dev uint64 + uint public override immutable baseScale; + + /// @notice The scale for reward tracking + /// @dev uint64 + uint public override immutable trackingIndexScale; + + /// @notice The speed at which supply rewards are tracked (in trackingIndexScale) + /// @dev uint64 + uint public override immutable baseTrackingSupplySpeed; + + /// @notice The speed at which borrow rewards are tracked (in trackingIndexScale) + /// @dev uint64 + uint public override immutable baseTrackingBorrowSpeed; + + /// @notice The minimum amount of base principal wei for rewards to accrue + /// @dev This must be large enough so as to prevent division by base wei from overflowing the 64 bit indices + /// @dev uint104 + uint public override immutable baseMinForRewards; + + /// @notice The minimum base amount required to initiate a borrow + uint public override immutable baseBorrowMin; + + /// @notice The minimum base token reserves which must be held before collateral is hodled + uint public override immutable targetReserves; + + /// @notice The number of decimals for wrapped base token + uint8 public override immutable decimals; + + /// @notice The number of assets this contract actually supports + uint8 public override immutable numAssets; + + /// @notice Factor to divide by when accruing rewards in order to preserve 6 decimals (i.e. baseScale / 1e6) + uint internal immutable accrualDescaleFactor; + + /// @notice The address of the asset list + address immutable public assetList; + + /** + * @notice Construct a new protocol instance + * @param config The mapping of initial/constant parameters + **/ + constructor(Configuration memory config) { + // Sanity checks + uint8 decimals_ = IERC20NonStandard(config.baseToken).decimals(); + if (decimals_ > MAX_BASE_DECIMALS) revert BadDecimals(); + if (config.storeFrontPriceFactor > FACTOR_SCALE) revert BadDiscount(); + if (config.baseMinForRewards == 0) revert BadMinimum(); + if (IPriceFeed(config.baseTokenPriceFeed).decimals() != PRICE_FEED_DECIMALS) revert BadDecimals(); + + // Copy configuration + unchecked { + governor = config.governor; + pauseGuardian = config.pauseGuardian; + baseToken = config.baseToken; + baseTokenPriceFeed = config.baseTokenPriceFeed; + extensionDelegate = config.extensionDelegate; + storeFrontPriceFactor = config.storeFrontPriceFactor; + + decimals = decimals_; + baseScale = uint64(10 ** decimals_); + trackingIndexScale = config.trackingIndexScale; + if (baseScale < BASE_ACCRUAL_SCALE) revert BadDecimals(); + accrualDescaleFactor = baseScale / BASE_ACCRUAL_SCALE; + + baseMinForRewards = config.baseMinForRewards; + baseTrackingSupplySpeed = config.baseTrackingSupplySpeed; + baseTrackingBorrowSpeed = config.baseTrackingBorrowSpeed; + + baseBorrowMin = config.baseBorrowMin; + targetReserves = config.targetReserves; + } + + // Set interest rate model configs + unchecked { + supplyKink = config.supplyKink; + supplyPerSecondInterestRateSlopeLow = config.supplyPerYearInterestRateSlopeLow / SECONDS_PER_YEAR; + supplyPerSecondInterestRateSlopeHigh = config.supplyPerYearInterestRateSlopeHigh / SECONDS_PER_YEAR; + supplyPerSecondInterestRateBase = config.supplyPerYearInterestRateBase / SECONDS_PER_YEAR; + borrowKink = config.borrowKink; + borrowPerSecondInterestRateSlopeLow = config.borrowPerYearInterestRateSlopeLow / SECONDS_PER_YEAR; + borrowPerSecondInterestRateSlopeHigh = config.borrowPerYearInterestRateSlopeHigh / SECONDS_PER_YEAR; + borrowPerSecondInterestRateBase = config.borrowPerYearInterestRateBase / SECONDS_PER_YEAR; + } + + // Set asset info + numAssets = uint8(config.assetConfigs.length); + + assetList = IAssetListFactory(IAssetListFactory(extensionDelegate).assetListFactory()).createAssetList(config.assetConfigs); + } + + /** + * @dev Prevents marked functions from being reentered + * Note: this restrict contracts from calling comet functions in their hooks. + * Doing so will cause the transaction to revert. + */ + modifier nonReentrant() { + nonReentrantBefore(); + _; + nonReentrantAfter(); + } + + /** + * @dev Checks that the reentrancy flag is not set and then sets the flag + */ + function nonReentrantBefore() internal { + bytes32 slot = REENTRANCY_GUARD_FLAG_SLOT; + uint256 status; + assembly ("memory-safe") { + status := sload(slot) + } + + if (status == REENTRANCY_GUARD_ENTERED) revert ReentrantCallBlocked(); + assembly ("memory-safe") { + sstore(slot, REENTRANCY_GUARD_ENTERED) + } + } + + /** + * @dev Unsets the reentrancy flag + */ + function nonReentrantAfter() internal { + bytes32 slot = REENTRANCY_GUARD_FLAG_SLOT; + uint256 status; + assembly ("memory-safe") { + sstore(slot, REENTRANCY_GUARD_NOT_ENTERED) + } + } + + /** + * @notice Initialize storage for the contract + * @dev Can be used from constructor or proxy + */ + function initializeStorage() override external { + if (lastAccrualTime != 0) revert AlreadyInitialized(); + + // Initialize aggregates + lastAccrualTime = getNowInternal(); + baseSupplyIndex = BASE_INDEX_SCALE; + baseBorrowIndex = BASE_INDEX_SCALE; + + // Implicit initialization (not worth increasing contract size) + // trackingSupplyIndex = 0; + // trackingBorrowIndex = 0; + } + + /** + * @notice Get the i-th asset info, according to the order they were passed in originally + * @param i The index of the asset info to get + * @return The asset info object + */ + function getAssetInfo(uint8 i) override public view returns (AssetInfo memory) { + return IAssetList(assetList).getAssetInfo(i); + } + + /** + * @dev Determine index of asset that matches given address + */ + function getAssetInfoByAddress(address asset) override public view returns (AssetInfo memory) { + for (uint8 i = 0; i < numAssets; ) { + AssetInfo memory assetInfo = getAssetInfo(i); + if (assetInfo.asset == asset) { + return assetInfo; + } + unchecked { i++; } + } + revert BadAsset(); + } + + /** + * @return The current timestamp + **/ + function getNowInternal() virtual internal view returns (uint40) { + if (block.timestamp >= 2**40) revert TimestampTooLarge(); + return uint40(block.timestamp); + } + + /** + * @dev Calculate accrued interest indices for base token supply and borrows + **/ + function accruedInterestIndices(uint timeElapsed) internal view returns (uint64, uint64) { + uint64 baseSupplyIndex_ = baseSupplyIndex; + uint64 baseBorrowIndex_ = baseBorrowIndex; + if (timeElapsed > 0) { + uint utilization = getUtilization(); + uint supplyRate = getSupplyRate(utilization); + uint borrowRate = getBorrowRate(utilization); + baseSupplyIndex_ += safe64(mulFactor(baseSupplyIndex_, supplyRate * timeElapsed)); + baseBorrowIndex_ += safe64(mulFactor(baseBorrowIndex_, borrowRate * timeElapsed)); + } + return (baseSupplyIndex_, baseBorrowIndex_); + } + + /** + * @dev Accrue interest (and rewards) in base token supply and borrows + **/ + function accrueInternal() internal { + uint40 now_ = getNowInternal(); + uint timeElapsed = uint256(now_ - lastAccrualTime); + if (timeElapsed > 0) { + (baseSupplyIndex, baseBorrowIndex) = accruedInterestIndices(timeElapsed); + if (totalSupplyBase >= baseMinForRewards) { + trackingSupplyIndex += safe64(divBaseWei(baseTrackingSupplySpeed * timeElapsed, totalSupplyBase)); + } + if (totalBorrowBase >= baseMinForRewards) { + trackingBorrowIndex += safe64(divBaseWei(baseTrackingBorrowSpeed * timeElapsed, totalBorrowBase)); + } + lastAccrualTime = now_; + } + } + + /** + * @notice Accrue interest and rewards for an account + **/ + function accrueAccount(address account) override external { + accrueInternal(); + + UserBasic memory basic = userBasic[account]; + updateBasePrincipal(account, basic, basic.principal); + } + + /** + * @dev Note: Does not accrue interest first + * @param utilization The utilization to check the supply rate for + * @return The per second supply rate at `utilization` + */ + function getSupplyRate(uint utilization) override public view returns (uint64) { + if (utilization <= supplyKink) { + // interestRateBase + interestRateSlopeLow * utilization + return safe64(supplyPerSecondInterestRateBase + mulFactor(supplyPerSecondInterestRateSlopeLow, utilization)); + } else { + // interestRateBase + interestRateSlopeLow * kink + interestRateSlopeHigh * (utilization - kink) + return safe64(supplyPerSecondInterestRateBase + mulFactor(supplyPerSecondInterestRateSlopeLow, supplyKink) + mulFactor(supplyPerSecondInterestRateSlopeHigh, (utilization - supplyKink))); + } + } + + /** + * @dev Note: Does not accrue interest first + * @param utilization The utilization to check the borrow rate for + * @return The per second borrow rate at `utilization` + */ + function getBorrowRate(uint utilization) override public view returns (uint64) { + if (utilization <= borrowKink) { + // interestRateBase + interestRateSlopeLow * utilization + return safe64(borrowPerSecondInterestRateBase + mulFactor(borrowPerSecondInterestRateSlopeLow, utilization)); + } else { + // interestRateBase + interestRateSlopeLow * kink + interestRateSlopeHigh * (utilization - kink) + return safe64(borrowPerSecondInterestRateBase + mulFactor(borrowPerSecondInterestRateSlopeLow, borrowKink) + mulFactor(borrowPerSecondInterestRateSlopeHigh, (utilization - borrowKink))); + } + } + + /** + * @dev Note: Does not accrue interest first + * @return The utilization rate of the base asset + */ + function getUtilization() override public view returns (uint) { + uint totalSupply_ = presentValueSupply(baseSupplyIndex, totalSupplyBase); + uint totalBorrow_ = presentValueBorrow(baseBorrowIndex, totalBorrowBase); + if (totalSupply_ == 0) { + return 0; + } else { + return totalBorrow_ * FACTOR_SCALE / totalSupply_; + } + } + + /** + * @notice Get the current price from a feed + * @param priceFeed The address of a price feed + * @return The price, scaled by `PRICE_SCALE` + */ + function getPrice(address priceFeed) override public view returns (uint256) { + (, int price, , , ) = IPriceFeed(priceFeed).latestRoundData(); + if (price <= 0) revert BadPrice(); + return uint256(price); + } + + /** + * @notice Gets the total balance of protocol collateral reserves for an asset + * @dev Note: Reverts if collateral reserves are somehow negative, which should not be possible + * @param asset The collateral asset + */ + function getCollateralReserves(address asset) override public view returns (uint) { + return IERC20NonStandard(asset).balanceOf(address(this)) - totalsCollateral[asset].totalSupplyAsset; + } + + /** + * @notice Gets the total amount of protocol reserves of the base asset + */ + function getReserves() override public view returns (int) { + (uint64 baseSupplyIndex_, uint64 baseBorrowIndex_) = accruedInterestIndices(getNowInternal() - lastAccrualTime); + uint balance = IERC20NonStandard(baseToken).balanceOf(address(this)); + uint totalSupply_ = presentValueSupply(baseSupplyIndex_, totalSupplyBase); + uint totalBorrow_ = presentValueBorrow(baseBorrowIndex_, totalBorrowBase); + return signed256(balance) - signed256(totalSupply_) + signed256(totalBorrow_); + } + + /** + * @notice Check whether an account has enough collateral to borrow + * @param account The address to check + * @return Whether the account is minimally collateralized enough to borrow + */ + function isBorrowCollateralized(address account) override public view returns (bool) { + int104 principal = userBasic[account].principal; + + if (principal >= 0) { + return true; + } + + uint16 assetsIn = userBasic[account].assetsIn; + int liquidity = signedMulPrice( + presentValue(principal), + getPrice(baseTokenPriceFeed), + uint64(baseScale) + ); + + for (uint8 i = 0; i < numAssets; ) { + if (isInAsset(assetsIn, i)) { + if (liquidity >= 0) { + return true; + } + + AssetInfo memory asset = getAssetInfo(i); + uint newAmount = mulPrice( + userCollateral[account][asset.asset].balance, + getPrice(asset.priceFeed), + asset.scale + ); + liquidity += signed256(mulFactor( + newAmount, + asset.borrowCollateralFactor + )); + } + unchecked { i++; } + } + + return liquidity >= 0; + } + + /** + * @notice Check whether an account has enough collateral to not be liquidated + * @param account The address to check + * @return Whether the account is minimally collateralized enough to not be liquidated + */ + function isLiquidatable(address account) override public view returns (bool) { + int104 principal = userBasic[account].principal; + + if (principal >= 0) { + return false; + } + + uint16 assetsIn = userBasic[account].assetsIn; + int liquidity = signedMulPrice( + presentValue(principal), + getPrice(baseTokenPriceFeed), + uint64(baseScale) + ); + + for (uint8 i = 0; i < numAssets; ) { + if (isInAsset(assetsIn, i)) { + if (liquidity >= 0) { + return false; + } + + AssetInfo memory asset = getAssetInfo(i); + uint newAmount = mulPrice( + userCollateral[account][asset.asset].balance, + getPrice(asset.priceFeed), + asset.scale + ); + liquidity += signed256(mulFactor( + newAmount, + asset.liquidateCollateralFactor + )); + } + unchecked { i++; } + } + + return liquidity < 0; + } + + /** + * @dev The change in principal broken into repay and supply amounts + */ + function repayAndSupplyAmount(int104 oldPrincipal, int104 newPrincipal) internal pure returns (uint104, uint104) { + // If the new principal is less than the old principal, then no amount has been repaid or supplied + if (newPrincipal < oldPrincipal) return (0, 0); + + if (newPrincipal <= 0) { + return (uint104(newPrincipal - oldPrincipal), 0); + } else if (oldPrincipal >= 0) { + return (0, uint104(newPrincipal - oldPrincipal)); + } else { + return (uint104(-oldPrincipal), uint104(newPrincipal)); + } + } + + /** + * @dev The change in principal broken into withdraw and borrow amounts + */ + function withdrawAndBorrowAmount(int104 oldPrincipal, int104 newPrincipal) internal pure returns (uint104, uint104) { + // If the new principal is greater than the old principal, then no amount has been withdrawn or borrowed + if (newPrincipal > oldPrincipal) return (0, 0); + + if (newPrincipal >= 0) { + return (uint104(oldPrincipal - newPrincipal), 0); + } else if (oldPrincipal <= 0) { + return (0, uint104(oldPrincipal - newPrincipal)); + } else { + return (uint104(oldPrincipal), uint104(-newPrincipal)); + } + } + + /** + * @notice Pauses different actions within Comet + * @param supplyPaused Boolean for pausing supply actions + * @param transferPaused Boolean for pausing transfer actions + * @param withdrawPaused Boolean for pausing withdraw actions + * @param absorbPaused Boolean for pausing absorb actions + * @param buyPaused Boolean for pausing buy actions + */ + function pause( + bool supplyPaused, + bool transferPaused, + bool withdrawPaused, + bool absorbPaused, + bool buyPaused + ) override external { + if (msg.sender != governor && msg.sender != pauseGuardian) revert Unauthorized(); + + pauseFlags = + uint8(0) | + (toUInt8(supplyPaused) << PAUSE_SUPPLY_OFFSET) | + (toUInt8(transferPaused) << PAUSE_TRANSFER_OFFSET) | + (toUInt8(withdrawPaused) << PAUSE_WITHDRAW_OFFSET) | + (toUInt8(absorbPaused) << PAUSE_ABSORB_OFFSET) | + (toUInt8(buyPaused) << PAUSE_BUY_OFFSET); + + emit PauseAction(supplyPaused, transferPaused, withdrawPaused, absorbPaused, buyPaused); + } + + /** + * @return Whether or not supply actions are paused + */ + function isSupplyPaused() override public view returns (bool) { + return toBool(pauseFlags & (uint8(1) << PAUSE_SUPPLY_OFFSET)); + } + + /** + * @return Whether or not transfer actions are paused + */ + function isTransferPaused() override public view returns (bool) { + return toBool(pauseFlags & (uint8(1) << PAUSE_TRANSFER_OFFSET)); + } + + /** + * @return Whether or not withdraw actions are paused + */ + function isWithdrawPaused() override public view returns (bool) { + return toBool(pauseFlags & (uint8(1) << PAUSE_WITHDRAW_OFFSET)); + } + + /** + * @return Whether or not absorb actions are paused + */ + function isAbsorbPaused() override public view returns (bool) { + return toBool(pauseFlags & (uint8(1) << PAUSE_ABSORB_OFFSET)); + } + + /** + * @return Whether or not buy actions are paused + */ + function isBuyPaused() override public view returns (bool) { + return toBool(pauseFlags & (uint8(1) << PAUSE_BUY_OFFSET)); + } + + /** + * @dev Multiply a number by a factor + */ + function mulFactor(uint n, uint factor) internal pure returns (uint) { + return n * factor / FACTOR_SCALE; + } + + /** + * @dev Divide a number by an amount of base + */ + function divBaseWei(uint n, uint baseWei) internal view returns (uint) { + return n * baseScale / baseWei; + } + + /** + * @dev Multiply a `fromScale` quantity by a price, returning a common price quantity + */ + function mulPrice(uint n, uint price, uint64 fromScale) internal pure returns (uint) { + return n * price / fromScale; + } + + /** + * @dev Multiply a signed `fromScale` quantity by a price, returning a common price quantity + */ + function signedMulPrice(int n, uint price, uint64 fromScale) internal pure returns (int) { + return n * signed256(price) / int256(uint256(fromScale)); + } + + /** + * @dev Divide a common price quantity by a price, returning a `toScale` quantity + */ + function divPrice(uint n, uint price, uint64 toScale) internal pure returns (uint) { + return n * toScale / price; + } + + /** + * @dev Whether user has a non-zero balance of an asset, given assetsIn flags + */ + function isInAsset(uint16 assetsIn, uint8 assetOffset) internal pure returns (bool) { + return (assetsIn & (uint16(1) << assetOffset) != 0); + } + + /** + * @dev Update assetsIn bit vector if user has entered or exited an asset + */ + function updateAssetsIn( + address account, + AssetInfo memory assetInfo, + uint128 initialUserBalance, + uint128 finalUserBalance + ) internal { + if (initialUserBalance == 0 && finalUserBalance != 0) { + // set bit for asset + userBasic[account].assetsIn |= (uint16(1) << assetInfo.offset); + } else if (initialUserBalance != 0 && finalUserBalance == 0) { + // clear bit for asset + userBasic[account].assetsIn &= ~(uint16(1) << assetInfo.offset); + } + } + + /** + * @dev Write updated principal to store and tracking participation + */ + function updateBasePrincipal(address account, UserBasic memory basic, int104 principalNew) internal { + int104 principal = basic.principal; + basic.principal = principalNew; + + if (principal >= 0) { + uint indexDelta = uint256(trackingSupplyIndex - basic.baseTrackingIndex); + basic.baseTrackingAccrued += safe64(uint104(principal) * indexDelta / trackingIndexScale / accrualDescaleFactor); + } else { + uint indexDelta = uint256(trackingBorrowIndex - basic.baseTrackingIndex); + basic.baseTrackingAccrued += safe64(uint104(-principal) * indexDelta / trackingIndexScale / accrualDescaleFactor); + } + + if (principalNew >= 0) { + basic.baseTrackingIndex = trackingSupplyIndex; + } else { + basic.baseTrackingIndex = trackingBorrowIndex; + } + + userBasic[account] = basic; + } + + /** + * @dev Safe ERC20 transfer in and returns the final amount transferred (taking into account any fees) + * @dev Note: Safely handles non-standard ERC-20 tokens that do not return a value. See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca + */ + function doTransferIn(address asset, address from, uint amount) internal returns (uint) { + uint256 preTransferBalance = IERC20NonStandard(asset).balanceOf(address(this)); + IERC20NonStandard(asset).transferFrom(from, address(this), amount); + bool success; + assembly ("memory-safe") { + switch returndatasize() + case 0 { // This is a non-standard ERC-20 + success := not(0) // set success to true + } + case 32 { // This is a compliant ERC-20 + returndatacopy(0, 0, 32) + success := mload(0) // Set `success = returndata` of override external call + } + default { // This is an excessively non-compliant ERC-20, revert. + revert(0, 0) + } + } + if (!success) revert TransferInFailed(); + return IERC20NonStandard(asset).balanceOf(address(this)) - preTransferBalance; + } + + /** + * @dev Safe ERC20 transfer out + * @dev Note: Safely handles non-standard ERC-20 tokens that do not return a value. See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca + */ + function doTransferOut(address asset, address to, uint amount) internal { + IERC20NonStandard(asset).transfer(to, amount); + bool success; + assembly ("memory-safe") { + switch returndatasize() + case 0 { // This is a non-standard ERC-20 + success := not(0) // set success to true + } + case 32 { // This is a compliant ERC-20 + returndatacopy(0, 0, 32) + success := mload(0) // Set `success = returndata` of override external call + } + default { // This is an excessively non-compliant ERC-20, revert. + revert(0, 0) + } + } + if (!success) revert TransferOutFailed(); + } + + /** + * @notice Supply an amount of asset to the protocol + * @param asset The asset to supply + * @param amount The quantity to supply + */ + function supply(address asset, uint amount) override external { + return supplyInternal(msg.sender, msg.sender, msg.sender, asset, amount); + } + + /** + * @notice Supply an amount of asset to dst + * @param dst The address which will hold the balance + * @param asset The asset to supply + * @param amount The quantity to supply + */ + function supplyTo(address dst, address asset, uint amount) override external { + return supplyInternal(msg.sender, msg.sender, dst, asset, amount); + } + + /** + * @notice Supply an amount of asset from `from` to dst, if allowed + * @param from The supplier address + * @param dst The address which will hold the balance + * @param asset The asset to supply + * @param amount The quantity to supply + */ + function supplyFrom(address from, address dst, address asset, uint amount) override external { + return supplyInternal(msg.sender, from, dst, asset, amount); + } + + /** + * @dev Supply either collateral or base asset, depending on the asset, if operator is allowed + * @dev Note: Specifying an `amount` of uint256.max will repay all of `dst`'s accrued base borrow balance + */ + function supplyInternal(address operator, address from, address dst, address asset, uint amount) internal nonReentrant { + if (isSupplyPaused()) revert Paused(); + if (!hasPermission(from, operator)) revert Unauthorized(); + + if (asset == baseToken) { + if (amount == type(uint256).max) { + amount = borrowBalanceOf(dst); + } + return supplyBase(from, dst, amount); + } else { + return supplyCollateral(from, dst, asset, safe128(amount)); + } + } + + /** + * @dev Supply an amount of base asset from `from` to dst + */ + function supplyBase(address from, address dst, uint256 amount) internal { + amount = doTransferIn(baseToken, from, amount); + + accrueInternal(); + + UserBasic memory dstUser = userBasic[dst]; + int104 dstPrincipal = dstUser.principal; + int256 dstBalance = presentValue(dstPrincipal) + signed256(amount); + int104 dstPrincipalNew = principalValue(dstBalance); + + (uint104 repayAmount, uint104 supplyAmount) = repayAndSupplyAmount(dstPrincipal, dstPrincipalNew); + + totalSupplyBase += supplyAmount; + totalBorrowBase -= repayAmount; + + updateBasePrincipal(dst, dstUser, dstPrincipalNew); + + emit Supply(from, dst, amount); + + if (supplyAmount > 0) { + emit Transfer(address(0), dst, presentValueSupply(baseSupplyIndex, supplyAmount)); + } + } + + /** + * @dev Supply an amount of collateral asset from `from` to dst + */ + function supplyCollateral(address from, address dst, address asset, uint128 amount) internal { + amount = safe128(doTransferIn(asset, from, amount)); + + AssetInfo memory assetInfo = getAssetInfoByAddress(asset); + TotalsCollateral memory totals = totalsCollateral[asset]; + totals.totalSupplyAsset += amount; + if (totals.totalSupplyAsset > assetInfo.supplyCap) revert SupplyCapExceeded(); + + uint128 dstCollateral = userCollateral[dst][asset].balance; + uint128 dstCollateralNew = dstCollateral + amount; + + totalsCollateral[asset] = totals; + userCollateral[dst][asset].balance = dstCollateralNew; + + updateAssetsIn(dst, assetInfo, dstCollateral, dstCollateralNew); + + emit SupplyCollateral(from, dst, asset, amount); + } + + /** + * @notice ERC20 transfer an amount of base token to dst + * @param dst The recipient address + * @param amount The quantity to transfer + * @return true + */ + function transfer(address dst, uint amount) override external returns (bool) { + transferInternal(msg.sender, msg.sender, dst, baseToken, amount); + return true; + } + + /** + * @notice ERC20 transfer an amount of base token from src to dst, if allowed + * @param src The sender address + * @param dst The recipient address + * @param amount The quantity to transfer + * @return true + */ + function transferFrom(address src, address dst, uint amount) override external returns (bool) { + transferInternal(msg.sender, src, dst, baseToken, amount); + return true; + } + + /** + * @notice Transfer an amount of asset to dst + * @param dst The recipient address + * @param asset The asset to transfer + * @param amount The quantity to transfer + */ + function transferAsset(address dst, address asset, uint amount) override external { + return transferInternal(msg.sender, msg.sender, dst, asset, amount); + } + + /** + * @notice Transfer an amount of asset from src to dst, if allowed + * @param src The sender address + * @param dst The recipient address + * @param asset The asset to transfer + * @param amount The quantity to transfer + */ + function transferAssetFrom(address src, address dst, address asset, uint amount) override external { + return transferInternal(msg.sender, src, dst, asset, amount); + } + + /** + * @dev Transfer either collateral or base asset, depending on the asset, if operator is allowed + * @dev Note: Specifying an `amount` of uint256.max will transfer all of `src`'s accrued base balance + */ + function transferInternal(address operator, address src, address dst, address asset, uint amount) internal nonReentrant { + if (isTransferPaused()) revert Paused(); + if (!hasPermission(src, operator)) revert Unauthorized(); + if (src == dst) revert NoSelfTransfer(); + + if (asset == baseToken) { + if (amount == type(uint256).max) { + amount = balanceOf(src); + } + return transferBase(src, dst, amount); + } else { + return transferCollateral(src, dst, asset, safe128(amount)); + } + } + + /** + * @dev Transfer an amount of base asset from src to dst, borrowing if possible/necessary + */ + function transferBase(address src, address dst, uint256 amount) internal { + accrueInternal(); + + UserBasic memory srcUser = userBasic[src]; + UserBasic memory dstUser = userBasic[dst]; + + int104 srcPrincipal = srcUser.principal; + int104 dstPrincipal = dstUser.principal; + int256 srcBalance = presentValue(srcPrincipal) - signed256(amount); + int256 dstBalance = presentValue(dstPrincipal) + signed256(amount); + int104 srcPrincipalNew = principalValue(srcBalance); + int104 dstPrincipalNew = principalValue(dstBalance); + + (uint104 withdrawAmount, uint104 borrowAmount) = withdrawAndBorrowAmount(srcPrincipal, srcPrincipalNew); + (uint104 repayAmount, uint104 supplyAmount) = repayAndSupplyAmount(dstPrincipal, dstPrincipalNew); + + // Note: Instead of `total += addAmount - subAmount` to avoid underflow errors. + totalSupplyBase = totalSupplyBase + supplyAmount - withdrawAmount; + totalBorrowBase = totalBorrowBase + borrowAmount - repayAmount; + + updateBasePrincipal(src, srcUser, srcPrincipalNew); + updateBasePrincipal(dst, dstUser, dstPrincipalNew); + + if (srcBalance < 0) { + if (uint256(-srcBalance) < baseBorrowMin) revert BorrowTooSmall(); + if (!isBorrowCollateralized(src)) revert NotCollateralized(); + } + + if (withdrawAmount > 0) { + emit Transfer(src, address(0), presentValueSupply(baseSupplyIndex, withdrawAmount)); + } + + if (supplyAmount > 0) { + emit Transfer(address(0), dst, presentValueSupply(baseSupplyIndex, supplyAmount)); + } + } + + /** + * @dev Transfer an amount of collateral asset from src to dst + */ + function transferCollateral(address src, address dst, address asset, uint128 amount) internal { + uint128 srcCollateral = userCollateral[src][asset].balance; + uint128 dstCollateral = userCollateral[dst][asset].balance; + uint128 srcCollateralNew = srcCollateral - amount; + uint128 dstCollateralNew = dstCollateral + amount; + + userCollateral[src][asset].balance = srcCollateralNew; + userCollateral[dst][asset].balance = dstCollateralNew; + + AssetInfo memory assetInfo = getAssetInfoByAddress(asset); + updateAssetsIn(src, assetInfo, srcCollateral, srcCollateralNew); + updateAssetsIn(dst, assetInfo, dstCollateral, dstCollateralNew); + + // Note: no accrue interest, BorrowCF < LiquidationCF covers small changes + if (!isBorrowCollateralized(src)) revert NotCollateralized(); + + emit TransferCollateral(src, dst, asset, amount); + } + + /** + * @notice Withdraw an amount of asset from the protocol + * @param asset The asset to withdraw + * @param amount The quantity to withdraw + */ + function withdraw(address asset, uint amount) override external { + return withdrawInternal(msg.sender, msg.sender, msg.sender, asset, amount); + } + + /** + * @notice Withdraw an amount of asset to `to` + * @param to The recipient address + * @param asset The asset to withdraw + * @param amount The quantity to withdraw + */ + function withdrawTo(address to, address asset, uint amount) override external { + return withdrawInternal(msg.sender, msg.sender, to, asset, amount); + } + + /** + * @notice Withdraw an amount of asset from src to `to`, if allowed + * @param src The sender address + * @param to The recipient address + * @param asset The asset to withdraw + * @param amount The quantity to withdraw + */ + function withdrawFrom(address src, address to, address asset, uint amount) override external { + return withdrawInternal(msg.sender, src, to, asset, amount); + } + + /** + * @dev Withdraw either collateral or base asset, depending on the asset, if operator is allowed + * @dev Note: Specifying an `amount` of uint256.max will withdraw all of `src`'s accrued base balance + */ + function withdrawInternal(address operator, address src, address to, address asset, uint amount) internal nonReentrant { + if (isWithdrawPaused()) revert Paused(); + if (!hasPermission(src, operator)) revert Unauthorized(); + + if (asset == baseToken) { + if (amount == type(uint256).max) { + amount = balanceOf(src); + } + return withdrawBase(src, to, amount); + } else { + return withdrawCollateral(src, to, asset, safe128(amount)); + } + } + + /** + * @dev Withdraw an amount of base asset from src to `to`, borrowing if possible/necessary + */ + function withdrawBase(address src, address to, uint256 amount) internal { + accrueInternal(); + + UserBasic memory srcUser = userBasic[src]; + int104 srcPrincipal = srcUser.principal; + int256 srcBalance = presentValue(srcPrincipal) - signed256(amount); + int104 srcPrincipalNew = principalValue(srcBalance); + + (uint104 withdrawAmount, uint104 borrowAmount) = withdrawAndBorrowAmount(srcPrincipal, srcPrincipalNew); + + totalSupplyBase -= withdrawAmount; + totalBorrowBase += borrowAmount; + + updateBasePrincipal(src, srcUser, srcPrincipalNew); + + if (srcBalance < 0) { + if (uint256(-srcBalance) < baseBorrowMin) revert BorrowTooSmall(); + if (!isBorrowCollateralized(src)) revert NotCollateralized(); + } + + doTransferOut(baseToken, to, amount); + + emit Withdraw(src, to, amount); + + if (withdrawAmount > 0) { + emit Transfer(src, address(0), presentValueSupply(baseSupplyIndex, withdrawAmount)); + } + } + + /** + * @dev Withdraw an amount of collateral asset from src to `to` + */ + function withdrawCollateral(address src, address to, address asset, uint128 amount) internal { + uint128 srcCollateral = userCollateral[src][asset].balance; + uint128 srcCollateralNew = srcCollateral - amount; + + totalsCollateral[asset].totalSupplyAsset -= amount; + userCollateral[src][asset].balance = srcCollateralNew; + + AssetInfo memory assetInfo = getAssetInfoByAddress(asset); + updateAssetsIn(src, assetInfo, srcCollateral, srcCollateralNew); + + // Note: no accrue interest, BorrowCF < LiquidationCF covers small changes + if (!isBorrowCollateralized(src)) revert NotCollateralized(); + + doTransferOut(asset, to, amount); + + emit WithdrawCollateral(src, to, asset, amount); + } + + /** + * @notice Absorb a list of underwater accounts onto the protocol balance sheet + * @param absorber The recipient of the incentive paid to the caller of absorb + * @param accounts The list of underwater accounts to absorb + */ + function absorb(address absorber, address[] calldata accounts) override external { + if (isAbsorbPaused()) revert Paused(); + + uint startGas = gasleft(); + accrueInternal(); + for (uint i = 0; i < accounts.length; ) { + absorbInternal(absorber, accounts[i]); + unchecked { i++; } + } + uint gasUsed = startGas - gasleft(); + + // Note: liquidator points are an imperfect tool for governance, + // to be used while evaluating strategies for incentivizing absorption. + // Using gas price instead of base fee would more accurately reflect spend, + // but is also subject to abuse if refunds were to be given automatically. + LiquidatorPoints memory points = liquidatorPoints[absorber]; + points.numAbsorbs++; + points.numAbsorbed += safe64(accounts.length); + points.approxSpend += safe128(gasUsed * block.basefee); + liquidatorPoints[absorber] = points; + } + + /** + * @dev Transfer user's collateral and debt to the protocol itself. + */ + function absorbInternal(address absorber, address account) internal { + if (!isLiquidatable(account)) revert NotLiquidatable(); + + UserBasic memory accountUser = userBasic[account]; + int104 oldPrincipal = accountUser.principal; + int256 oldBalance = presentValue(oldPrincipal); + uint16 assetsIn = accountUser.assetsIn; + + uint256 basePrice = getPrice(baseTokenPriceFeed); + uint256 deltaValue = 0; + + for (uint8 i = 0; i < numAssets; ) { + if (isInAsset(assetsIn, i)) { + AssetInfo memory assetInfo = getAssetInfo(i); + address asset = assetInfo.asset; + uint128 seizeAmount = userCollateral[account][asset].balance; + userCollateral[account][asset].balance = 0; + totalsCollateral[asset].totalSupplyAsset -= seizeAmount; + + uint256 value = mulPrice(seizeAmount, getPrice(assetInfo.priceFeed), assetInfo.scale); + deltaValue += mulFactor(value, assetInfo.liquidationFactor); + + emit AbsorbCollateral(absorber, account, asset, seizeAmount, value); + } + unchecked { i++; } + } + + uint256 deltaBalance = divPrice(deltaValue, basePrice, uint64(baseScale)); + int256 newBalance = oldBalance + signed256(deltaBalance); + // New balance will not be negative, all excess debt absorbed by reserves + if (newBalance < 0) { + newBalance = 0; + } + + int104 newPrincipal = principalValue(newBalance); + updateBasePrincipal(account, accountUser, newPrincipal); + + // reset assetsIn + userBasic[account].assetsIn = 0; + + (uint104 repayAmount, uint104 supplyAmount) = repayAndSupplyAmount(oldPrincipal, newPrincipal); + + // Reserves are decreased by increasing total supply and decreasing borrows + // the amount of debt repaid by reserves is `newBalance - oldBalance` + totalSupplyBase += supplyAmount; + totalBorrowBase -= repayAmount; + + uint256 basePaidOut = unsigned256(newBalance - oldBalance); + uint256 valueOfBasePaidOut = mulPrice(basePaidOut, basePrice, uint64(baseScale)); + emit AbsorbDebt(absorber, account, basePaidOut, valueOfBasePaidOut); + + if (newPrincipal > 0) { + emit Transfer(address(0), account, presentValueSupply(baseSupplyIndex, unsigned104(newPrincipal))); + } + } + + /** + * @notice Buy collateral from the protocol using base tokens, increasing protocol reserves + A minimum collateral amount should be specified to indicate the maximum slippage acceptable for the buyer. + * @param asset The asset to buy + * @param minAmount The minimum amount of collateral tokens that should be received by the buyer + * @param baseAmount The amount of base tokens used to buy the collateral + * @param recipient The recipient address + */ + function buyCollateral(address asset, uint minAmount, uint baseAmount, address recipient) override external nonReentrant { + if (isBuyPaused()) revert Paused(); + + int reserves = getReserves(); + if (reserves >= 0 && uint(reserves) >= targetReserves) revert NotForSale(); + + // Note: Re-entrancy can skip the reserves check above on a second buyCollateral call. + baseAmount = doTransferIn(baseToken, msg.sender, baseAmount); + + uint collateralAmount = quoteCollateral(asset, baseAmount); + if (collateralAmount < minAmount) revert TooMuchSlippage(); + if (collateralAmount > getCollateralReserves(asset)) revert InsufficientReserves(); + + // Note: Pre-transfer hook can re-enter buyCollateral with a stale collateral ERC20 balance. + // Assets should not be listed which allow re-entry from pre-transfer now, as too much collateral could be bought. + // This is also a problem if quoteCollateral derives its discount from the collateral ERC20 balance. + doTransferOut(asset, recipient, safe128(collateralAmount)); + + emit BuyCollateral(msg.sender, asset, baseAmount, collateralAmount); + } + + /** + * @notice Gets the quote for a collateral asset in exchange for an amount of base asset + * @param asset The collateral asset to get the quote for + * @param baseAmount The amount of the base asset to get the quote for + * @return The quote in terms of the collateral asset + */ + function quoteCollateral(address asset, uint baseAmount) override public view returns (uint) { + AssetInfo memory assetInfo = getAssetInfoByAddress(asset); + uint256 assetPrice = getPrice(assetInfo.priceFeed); + // Store front discount is derived from the collateral asset's liquidationFactor and storeFrontPriceFactor + // discount = storeFrontPriceFactor * (1e18 - liquidationFactor) + uint256 discountFactor = mulFactor(storeFrontPriceFactor, FACTOR_SCALE - assetInfo.liquidationFactor); + uint256 assetPriceDiscounted = mulFactor(assetPrice, FACTOR_SCALE - discountFactor); + uint256 basePrice = getPrice(baseTokenPriceFeed); + // # of collateral assets + // = (TotalValueOfBaseAmount / DiscountedPriceOfCollateralAsset) * assetScale + // = ((basePrice * baseAmount / baseScale) / assetPriceDiscounted) * assetScale + return basePrice * baseAmount * assetInfo.scale / assetPriceDiscounted / baseScale; + } + + /** + * @notice Withdraws base token reserves if called by the governor + * @param to An address of the receiver of withdrawn reserves + * @param amount The amount of reserves to be withdrawn from the protocol + */ + function withdrawReserves(address to, uint amount) override external { + if (msg.sender != governor) revert Unauthorized(); + + int reserves = getReserves(); + if (reserves < 0 || amount > unsigned256(reserves)) revert InsufficientReserves(); + + doTransferOut(baseToken, to, amount); + + emit WithdrawReserves(to, amount); + } + + /** + * @notice Sets Comet's ERC20 allowance of an asset for a manager + * @dev Only callable by governor + * @dev Note: Setting the `asset` as Comet's address will allow the manager + * to withdraw from Comet's Comet balance + * @dev Note: For USDT, if there is non-zero prior allowance, it must be reset to 0 first before setting a new value in proposal + * @param asset The asset that the manager will gain approval of + * @param manager The account which will be allowed or disallowed + * @param amount The amount of an asset to approve + */ + function approveThis(address manager, address asset, uint amount) override external { + if (msg.sender != governor) revert Unauthorized(); + + IERC20NonStandard(asset).approve(manager, amount); + } + + /** + * @notice Get the total number of tokens in circulation + * @dev Note: uses updated interest indices to calculate + * @return The supply of tokens + **/ + function totalSupply() override external view returns (uint256) { + (uint64 baseSupplyIndex_, ) = accruedInterestIndices(getNowInternal() - lastAccrualTime); + return presentValueSupply(baseSupplyIndex_, totalSupplyBase); + } + + /** + * @notice Get the total amount of debt + * @dev Note: uses updated interest indices to calculate + * @return The amount of debt + **/ + function totalBorrow() override external view returns (uint256) { + (, uint64 baseBorrowIndex_) = accruedInterestIndices(getNowInternal() - lastAccrualTime); + return presentValueBorrow(baseBorrowIndex_, totalBorrowBase); + } + + /** + * @notice Query the current positive base balance of an account or zero + * @dev Note: uses updated interest indices to calculate + * @param account The account whose balance to query + * @return The present day base balance magnitude of the account, if positive + */ + function balanceOf(address account) override public view returns (uint256) { + (uint64 baseSupplyIndex_, ) = accruedInterestIndices(getNowInternal() - lastAccrualTime); + int104 principal = userBasic[account].principal; + return principal > 0 ? presentValueSupply(baseSupplyIndex_, unsigned104(principal)) : 0; + } + + /** + * @notice Query the current negative base balance of an account or zero + * @dev Note: uses updated interest indices to calculate + * @param account The account whose balance to query + * @return The present day base balance magnitude of the account, if negative + */ + function borrowBalanceOf(address account) override public view returns (uint256) { + (, uint64 baseBorrowIndex_) = accruedInterestIndices(getNowInternal() - lastAccrualTime); + int104 principal = userBasic[account].principal; + return principal < 0 ? presentValueBorrow(baseBorrowIndex_, unsigned104(-principal)) : 0; + } + + /** + * @notice Fallback to calling the extension delegate for everything else + */ + fallback() external payable { + address delegate = extensionDelegate; + assembly { + calldatacopy(0, 0, calldatasize()) + let result := delegatecall(gas(), delegate, 0, calldatasize(), 0, 0) + returndatacopy(0, 0, returndatasize()) + switch result + case 0 { revert(0, returndatasize()) } + default { return(0, returndatasize()) } + } + } +} \ No newline at end of file diff --git a/contracts/CometFactoryExtendedAssetList.sol b/contracts/CometFactoryExtendedAssetList.sol new file mode 100644 index 000000000..5d30705f7 --- /dev/null +++ b/contracts/CometFactoryExtendedAssetList.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "./CometExtendedAssetList.sol"; +import "./CometConfiguration.sol"; + +contract CometFactoryExtendedAssetList is CometConfiguration { + function clone(Configuration calldata config) external returns (address) { + return address(new CometExtendedAssetList(config)); + } +} \ No newline at end of file diff --git a/contracts/IAssetList.sol b/contracts/IAssetList.sol new file mode 100644 index 000000000..584e6cc2b --- /dev/null +++ b/contracts/IAssetList.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "./CometCore.sol"; + +/** + * @title Compound's Asset List + * @author Compound + */ +interface IAssetList { + function getAssetInfo(uint8 i) external view returns (CometCore.AssetInfo memory); +} \ No newline at end of file diff --git a/contracts/IAssetListFactory.sol b/contracts/IAssetListFactory.sol new file mode 100644 index 000000000..e1cd91288 --- /dev/null +++ b/contracts/IAssetListFactory.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; +import "./CometCore.sol"; + +/** + * @title Compound's Asset List Factory + * @author Compound + */ +interface IAssetListFactory { + function createAssetList(CometCore.AssetConfig[] memory assetConfigs) external returns (address assetList); + // add it here to save space in Comet + function assetListFactory() external view returns (address); +} \ No newline at end of file diff --git a/deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..1d971dbfa --- /dev/null +++ b/deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,112 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1723198576_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + + const _newCometExt = await deploymentManager.deploy( + 'CometExt', + 'CometExt.sol', + [ + { + name32: ethers.utils.formatBytes32String('Compound WETH'), + symbol32: ethers.utils.formatBytes32String('cWETHv3') + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, _, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + governor, + comet, + cometAdmin, + configurator, + } = await deploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const mainnetActions = [ + // 1. Set the factory in the Configurator + { + contract: configurator, + signature: 'setFactory(address,address)', + args: [comet.address, cometFactoryExtendedAssetList], + }, + // 2. Set new CometExt as the extension delegate + { + contract: configurator, + signature: 'setExtensionDelegate(address,address)', + args: [comet.address, newCometExt], + }, + // 3. Deploy and upgrade to a new version of Comet + { + contract: cometAdmin, + signature: 'deployAndUpgradeTo(address,address)', + args: [configurator.address, comet.address], + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/scenario/LiquidationBotScenario.ts b/scenario/LiquidationBotScenario.ts index bf21963b7..77dbfe95c 100644 --- a/scenario/LiquidationBotScenario.ts +++ b/scenario/LiquidationBotScenario.ts @@ -767,7 +767,7 @@ scenario( const assetAmounts = { mainnet: { usdc: ' == 5000', // COMP - weth: ' == 7000', // CB_ETH + weth: ' == 3400', // CB_ETH usdt: ' == 5000', // COMP }, }; diff --git a/src/deploy/Network.ts b/src/deploy/Network.ts index 9f6f027d1..aebcc9d18 100644 --- a/src/deploy/Network.ts +++ b/src/deploy/Network.ts @@ -119,6 +119,8 @@ export async function deployNetworkComet( rewardTokenAddress } = await getConfiguration(deploymentManager, configOverrides); + const assetListFactory = await deploymentManager.deploy('assetListFactory', 'AssetListFactory.sol', [], maybeForce()); + /* Deploy contracts */ const cometAdmin = await deploymentManager.deploy( @@ -135,7 +137,7 @@ export async function deployNetworkComet( const cometExt = await deploymentManager.deploy( 'comet:implementation:implementation', 'CometExt.sol', - [extConfiguration], + [extConfiguration, assetListFactory.address], maybeForce(deploySpec.cometExt) ); diff --git a/test/asset-info-test-asset-list-comet.ts b/test/asset-info-test-asset-list-comet.ts new file mode 100644 index 000000000..dd1388074 --- /dev/null +++ b/test/asset-info-test-asset-list-comet.ts @@ -0,0 +1,184 @@ +import { expect, exp, makeConfigurator, ONE } from './helpers'; +import { SimplePriceFeed__factory, FaucetToken__factory, CometExt__factory, CometExtendedAssetList__factory, AssetListFactory__factory } from '../build/types'; + +import { ethers } from 'hardhat'; +describe('asset info', function () { + it('initializes protocol', async () => { + const { cometExtendedAssetList: comet, tokens } = await makeConfigurator({ + assets: { + USDC: {}, + ASSET1: {}, + ASSET2: {}, + ASSET3: {}, + }, + reward: 'ASSET1', + }); + + const cometNumAssets = await comet.numAssets(); + expect(cometNumAssets).to.be.equal(3); + + const assetInfo00 = await comet.getAssetInfo(0); + expect(assetInfo00.asset).to.be.equal(tokens['ASSET1'].address); + expect(assetInfo00.borrowCollateralFactor).to.equal(ONE - exp(1, 14)); + expect(assetInfo00.liquidateCollateralFactor).to.equal(ONE); + + const assetInfo01 = await comet.getAssetInfo(1); + expect(assetInfo01.asset).to.be.equal(tokens['ASSET2'].address); + expect(assetInfo01.borrowCollateralFactor).to.equal(ONE - exp(1, 14)); + expect(assetInfo01.liquidateCollateralFactor).to.equal(ONE); + + const assetInfo02 = await comet.getAssetInfo(2); + expect(assetInfo02.asset).to.be.equal(tokens['ASSET3'].address); + expect(assetInfo02.borrowCollateralFactor).to.equal(ONE - exp(1, 14)); + expect(assetInfo02.liquidateCollateralFactor).to.equal(ONE); + }); + + it('do NOT reverts if too many assets are passed', async () => { + const signers = await ethers.getSigners(); + + const assets = { + USDC: {}, + ASSET1: {}, + ASSET2: {}, + ASSET3: {}, + ASSET4: {}, + ASSET5: {}, + ASSET6: {}, + ASSET7: {}, + ASSET8: {}, + ASSET9: {}, + ASSET10: {}, + ASSET11: {}, + ASSET12: {}, + ASSET13: {}, + ASSET14: {}, + ASSET15: {}, + ASSET16: {}, + ASSET17: {}, + ASSET18: {}, + ASSET19: {}, + ASSET20: {}, + }; + let priceFeeds = {}; + const PriceFeedFactory = (await ethers.getContractFactory('SimplePriceFeed')) as SimplePriceFeed__factory; + for (const asset in assets) { + const initialPrice = exp(assets[asset].initialPrice || 1, 8); + const priceFeedDecimals = assets[asset].priceFeedDecimals || 8; + const priceFeed = await PriceFeedFactory.deploy(initialPrice, priceFeedDecimals); + await priceFeed.deployed(); + priceFeeds[asset] = priceFeed; + } + + const name32 = ethers.utils.formatBytes32String(('Compound Comet')); + const symbol32 = ethers.utils.formatBytes32String(('📈BASE')); + const governor = signers[0]; + const pauseGuardian = signers[1]; + const base = 'USDC'; + const supplyKink = exp(0.8, 18); + const supplyPerYearInterestRateBase = exp(0.0, 18); + const supplyPerYearInterestRateSlopeLow = exp(0.05, 18); + const supplyPerYearInterestRateSlopeHigh = exp(2, 18); + const borrowKink = exp(0.8, 18); + const borrowPerYearInterestRateBase = exp(0.005, 18); + const borrowPerYearInterestRateSlopeLow = exp(0.1, 18); + const borrowPerYearInterestRateSlopeHigh = exp(3, 18); + const storeFrontPriceFactor = ONE; + const trackingIndexScale = exp(1, 15); + const baseTrackingSupplySpeed = trackingIndexScale; + const baseTrackingBorrowSpeed = trackingIndexScale; + const baseMinForRewards = exp(1, 18); + const baseBorrowMin = exp(1, 18); + const targetReserves = 0; + + const FaucetFactory = (await ethers.getContractFactory('FaucetToken')) as FaucetToken__factory; + const tokens = {}; + for (const symbol in assets) { + const config = assets[symbol]; + const decimals = config.decimals || 18; + const initial = config.initial || 1e6; + const name = config.name || symbol; + const factory = config.factory || FaucetFactory; + let token = (tokens[symbol] = await factory.deploy(initial, name, decimals, symbol)); + await token.deployed(); + } + const AssetListFactory = (await ethers.getContractFactory('AssetListFactory')) as AssetListFactory__factory; + const assetListFactory = await AssetListFactory.deploy(); + await assetListFactory.deployed(); + + const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; + const extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }, assetListFactory.address); + await extensionDelegate.deployed(); + + + const config = { + governor: governor.address, + pauseGuardian: pauseGuardian.address, + extensionDelegate: extensionDelegate.address, + baseToken: tokens[base].address, + baseTokenPriceFeed: priceFeeds[base].address, + supplyKink, + supplyPerYearInterestRateBase, + supplyPerYearInterestRateSlopeLow, + supplyPerYearInterestRateSlopeHigh, + borrowKink, + borrowPerYearInterestRateBase, + borrowPerYearInterestRateSlopeLow, + borrowPerYearInterestRateSlopeHigh, + storeFrontPriceFactor, + trackingIndexScale, + baseTrackingSupplySpeed, + baseTrackingBorrowSpeed, + baseMinForRewards, + baseBorrowMin, + targetReserves, + assetConfigs: Object.entries(assets).reduce((acc, [symbol], _i) => { + if (symbol != base) { + acc.push({ + asset: tokens[symbol].address, + priceFeed: priceFeeds[symbol].address, + decimals: 18, + borrowCollateralFactor: ONE - 1n, + liquidateCollateralFactor: ONE, + liquidationFactor: ONE, + supplyCap: exp(100, 18), + }); + } + return acc; + }, []), + }; + const CometExtendedAssetList = (await ethers.getContractFactory('CometExtendedAssetList')) as CometExtendedAssetList__factory; + await expect(CometExtendedAssetList.deploy(config)).to.not.be.reverted; + }); + + it('reverts if index is greater than numAssets', async () => { + const { cometExtendedAssetList } = await makeConfigurator(); + await expect(cometExtendedAssetList.getAssetInfo(3)).to.be.revertedWith("custom error 'BadAsset()'"); + }); + + it('reverts if collateral factors are out of range', async () => { + await expect(makeConfigurator({ + assets: { + USDC: {}, + ASSET1: {borrowCF: exp(0.9, 18), liquidateCF: exp(0.9, 18)}, + ASSET2: {}, + }, + })).to.be.revertedWith("custom error 'BorrowCFTooLarge()'"); + + // check descaled factors + await expect(makeConfigurator({ + assets: { + USDC: {}, + ASSET1: {borrowCF: exp(0.9, 18), liquidateCF: exp(0.9, 18) + 1n}, + ASSET2: {}, + }, + })).to.be.revertedWith("custom error 'BorrowCFTooLarge()'"); + + await expect(makeConfigurator({ + assets: { + USDC: {}, + ASSET1: {borrowCF: exp(0.99, 18), liquidateCF: exp(1.1, 18)}, + ASSET2: {}, + }, + })).to.be.revertedWith("custom error 'LiquidateCFTooLarge()'"); + }); +}); diff --git a/test/constructor-test.ts b/test/constructor-test.ts index 3adfc8d89..8c070d70d 100644 --- a/test/constructor-test.ts +++ b/test/constructor-test.ts @@ -4,6 +4,7 @@ import { CometHarness__factory, FaucetToken__factory, SimplePriceFeed__factory, + AssetListFactory__factory, } from '../build/types'; describe('constructor', function () { @@ -16,13 +17,16 @@ describe('constructor', function () { it('verifies asset scales', async function () { const [governor, pauseGuardian] = await ethers.getSigners(); - + const AssetListFactory = (await ethers.getContractFactory('AssetListFactory')) as AssetListFactory__factory; + const assetListFactory = await AssetListFactory.deploy(); + await assetListFactory.deployed(); + // extension delegate const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; const extensionDelegate = await CometExtFactory.deploy({ name32: ethers.utils.formatBytes32String('Compound Comet'), - symbol32: ethers.utils.formatBytes32String('📈BASE') - }); + symbol32: ethers.utils.formatBytes32String('📈BASE'), + }, assetListFactory.address); await extensionDelegate.deployed(); // tokens diff --git a/test/helpers.ts b/test/helpers.ts index 58acf19af..01df1b12b 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -32,6 +32,10 @@ import { CometInterface, NonStandardFaucetFeeToken, NonStandardFaucetFeeToken__factory, + CometExtendedAssetList, + CometExtendedAssetList__factory, + AssetListFactory, + AssetListFactory__factory, } from '../build/types'; import { BigNumber } from 'ethers'; import { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider'; @@ -98,6 +102,8 @@ export type Protocol = { base: string; reward: string; comet: Comet; + cometExtendedAssetList: CometExtendedAssetList; + assetListFactory: AssetListFactory; tokens: { [symbol: string]: FaucetToken | NonStandardFaucetFeeToken; }; @@ -270,15 +276,19 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { const unsupportedToken = await FaucetFactory.deploy(1e6, 'Unsupported Token', 6, 'USUP'); + const AssetListFactory = (await ethers.getContractFactory('AssetListFactory')) as AssetListFactory__factory; + const assetListFactory = await AssetListFactory.deploy(); + await assetListFactory.deployed(); + let extensionDelegate = opts.extensionDelegate; if (extensionDelegate === undefined) { const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; - extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }); + extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }, assetListFactory.address); await extensionDelegate.deployed(); } const CometFactory = (await ethers.getContractFactory('CometHarness')) as CometHarness__factory; - const comet = await CometFactory.deploy({ + const config = { governor: governor.address, pauseGuardian: pauseGuardian.address, extensionDelegate: extensionDelegate.address, @@ -313,12 +323,19 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { } return acc; }, []), - }); + }; + const comet = await CometFactory.deploy(config); await comet.deployed(); + const CometExtendedAssetList = (await ethers.getContractFactory('CometExtendedAssetList')) as CometExtendedAssetList__factory; + const cometExtendedAssetList = await CometExtendedAssetList.deploy(config); + await cometExtendedAssetList.deployed(); + if (opts.start) await ethers.provider.send('evm_setNextBlockTimestamp', [opts.start]); await comet.initializeStorage(); + await cometExtendedAssetList.initializeStorage(); + const baseTokenBalance = opts.baseTokenBalance; if (baseTokenBalance) { const baseToken = tokens[base]; @@ -334,6 +351,8 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { base, reward, comet: await ethers.getContractAt('CometHarnessInterface', comet.address) as Comet, + cometExtendedAssetList: cometExtendedAssetList, + assetListFactory: assetListFactory, tokens, unsupportedToken, priceFeeds, @@ -352,6 +371,8 @@ export async function makeConfigurator(opts: ProtocolOpts = {}): Promise Date: Mon, 12 Aug 2024 12:14:09 +0300 Subject: [PATCH 02/45] feat: move new cometExt to its own contract --- contracts/CometExt.sol | 5 +---- contracts/CometExtAssetList.sol | 17 ++++++++++++++ contracts/CometExtendedAssetList.sol | 3 ++- contracts/IAssetListFactory.sol | 2 -- contracts/IAssetListFactoryHolder.sol | 10 +++++++++ ...pdate_comet_to_support_more_collaterals.ts | 22 +++++++++++++++---- src/deploy/Network.ts | 4 +--- test/asset-info-test-asset-list-comet.ts | 10 +++++++-- test/constructor-test.ts | 7 +----- test/helpers.ts | 4 ++-- test/liquidation/makeLiquidatableProtocol.ts | 6 +---- test/tracking-index-bounds-test.ts | 8 +++---- 12 files changed, 65 insertions(+), 33 deletions(-) create mode 100644 contracts/CometExtAssetList.sol create mode 100644 contracts/IAssetListFactoryHolder.sol diff --git a/contracts/CometExt.sol b/contracts/CometExt.sol index 67b7645e7..46962b3ad 100644 --- a/contracts/CometExt.sol +++ b/contracts/CometExt.sol @@ -29,16 +29,13 @@ contract CometExt is CometExtInterface { /// @dev The ERC20 symbol for wrapped base token bytes32 internal immutable symbol32; - address immutable public assetListFactory; - /** * @notice Construct a new protocol instance * @param config The mapping of initial/constant parameters **/ - constructor(ExtConfiguration memory config, address assetListFactoryAddress) { + constructor(ExtConfiguration memory config) { name32 = config.name32; symbol32 = config.symbol32; - assetListFactory = assetListFactoryAddress; } /** External getters for internal constants **/ diff --git a/contracts/CometExtAssetList.sol b/contracts/CometExtAssetList.sol new file mode 100644 index 000000000..faf7f955f --- /dev/null +++ b/contracts/CometExtAssetList.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "./CometExt.sol"; + +contract CometExtAssetList is CometExt { + + address immutable public assetListFactory; + + /** + * @notice Construct a new protocol instance + * @param config The mapping of initial/constant parameters + **/ + constructor(ExtConfiguration memory config, address assetListFactoryAddress) CometExt(config) { + assetListFactory = assetListFactoryAddress; + } +} \ No newline at end of file diff --git a/contracts/CometExtendedAssetList.sol b/contracts/CometExtendedAssetList.sol index 57d9d6c09..d80c1ac35 100644 --- a/contracts/CometExtendedAssetList.sol +++ b/contracts/CometExtendedAssetList.sol @@ -5,6 +5,7 @@ import "./CometMainInterface.sol"; import "./IERC20NonStandard.sol"; import "./IPriceFeed.sol"; import "./IAssetListFactory.sol"; +import "./IAssetListFactoryHolder.sol"; import "./IAssetList.sol"; /** @@ -155,7 +156,7 @@ contract CometExtendedAssetList is CometMainInterface { // Set asset info numAssets = uint8(config.assetConfigs.length); - assetList = IAssetListFactory(IAssetListFactory(extensionDelegate).assetListFactory()).createAssetList(config.assetConfigs); + assetList = IAssetListFactory(IAssetListFactoryHolder(extensionDelegate).assetListFactory()).createAssetList(config.assetConfigs); } /** diff --git a/contracts/IAssetListFactory.sol b/contracts/IAssetListFactory.sol index e1cd91288..9f41c28a5 100644 --- a/contracts/IAssetListFactory.sol +++ b/contracts/IAssetListFactory.sol @@ -8,6 +8,4 @@ import "./CometCore.sol"; */ interface IAssetListFactory { function createAssetList(CometCore.AssetConfig[] memory assetConfigs) external returns (address assetList); - // add it here to save space in Comet - function assetListFactory() external view returns (address); } \ No newline at end of file diff --git a/contracts/IAssetListFactoryHolder.sol b/contracts/IAssetListFactoryHolder.sol new file mode 100644 index 000000000..0691cada7 --- /dev/null +++ b/contracts/IAssetListFactoryHolder.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +/** + * @title Compound's Asset List Factory Holder Interface + * @author Compound + */ +interface IAssetListFactoryHolder { + function assetListFactory() external view returns (address); +} \ No newline at end of file diff --git a/deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts index 1d971dbfa..7235fba0c 100644 --- a/deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts +++ b/deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts @@ -20,14 +20,28 @@ export default migration('1723198576_update_comet_to_support_more_collaterals', 'CometFactoryExtendedAssetList.sol', [] ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); const _newCometExt = await deploymentManager.deploy( - 'CometExt', - 'CometExt.sol', + 'CometExtAssetList', + 'CometExtAssetList.sol', [ { - name32: ethers.utils.formatBytes32String('Compound WETH'), - symbol32: ethers.utils.formatBytes32String('cWETHv3') + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) }, _assetListFactory.address ] diff --git a/src/deploy/Network.ts b/src/deploy/Network.ts index aebcc9d18..9f6f027d1 100644 --- a/src/deploy/Network.ts +++ b/src/deploy/Network.ts @@ -119,8 +119,6 @@ export async function deployNetworkComet( rewardTokenAddress } = await getConfiguration(deploymentManager, configOverrides); - const assetListFactory = await deploymentManager.deploy('assetListFactory', 'AssetListFactory.sol', [], maybeForce()); - /* Deploy contracts */ const cometAdmin = await deploymentManager.deploy( @@ -137,7 +135,7 @@ export async function deployNetworkComet( const cometExt = await deploymentManager.deploy( 'comet:implementation:implementation', 'CometExt.sol', - [extConfiguration, assetListFactory.address], + [extConfiguration], maybeForce(deploySpec.cometExt) ); diff --git a/test/asset-info-test-asset-list-comet.ts b/test/asset-info-test-asset-list-comet.ts index dd1388074..0e0a0fe4d 100644 --- a/test/asset-info-test-asset-list-comet.ts +++ b/test/asset-info-test-asset-list-comet.ts @@ -1,5 +1,11 @@ import { expect, exp, makeConfigurator, ONE } from './helpers'; -import { SimplePriceFeed__factory, FaucetToken__factory, CometExt__factory, CometExtendedAssetList__factory, AssetListFactory__factory } from '../build/types'; +import { + SimplePriceFeed__factory, + FaucetToken__factory, + CometExtAssetList__factory, + CometExtendedAssetList__factory, + AssetListFactory__factory +} from '../build/types'; import { ethers } from 'hardhat'; describe('asset info', function () { @@ -105,7 +111,7 @@ describe('asset info', function () { const assetListFactory = await AssetListFactory.deploy(); await assetListFactory.deployed(); - const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; + const CometExtFactory = (await ethers.getContractFactory('CometExtAssetList')) as CometExtAssetList__factory; const extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }, assetListFactory.address); await extensionDelegate.deployed(); diff --git a/test/constructor-test.ts b/test/constructor-test.ts index 8c070d70d..74a53d073 100644 --- a/test/constructor-test.ts +++ b/test/constructor-test.ts @@ -4,7 +4,6 @@ import { CometHarness__factory, FaucetToken__factory, SimplePriceFeed__factory, - AssetListFactory__factory, } from '../build/types'; describe('constructor', function () { @@ -17,16 +16,12 @@ describe('constructor', function () { it('verifies asset scales', async function () { const [governor, pauseGuardian] = await ethers.getSigners(); - const AssetListFactory = (await ethers.getContractFactory('AssetListFactory')) as AssetListFactory__factory; - const assetListFactory = await AssetListFactory.deploy(); - await assetListFactory.deployed(); - // extension delegate const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; const extensionDelegate = await CometExtFactory.deploy({ name32: ethers.utils.formatBytes32String('Compound Comet'), symbol32: ethers.utils.formatBytes32String('📈BASE'), - }, assetListFactory.address); + }); await extensionDelegate.deployed(); // tokens diff --git a/test/helpers.ts b/test/helpers.ts index 01df1b12b..4c85339a2 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -7,7 +7,7 @@ import { BaseBulker, BaseBulker__factory, CometExt, - CometExt__factory, + CometExtAssetList__factory, CometHarness__factory, CometHarnessInterface as Comet, CometRewards, @@ -282,7 +282,7 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { let extensionDelegate = opts.extensionDelegate; if (extensionDelegate === undefined) { - const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; + const CometExtFactory = (await ethers.getContractFactory('CometExtAssetList')) as CometExtAssetList__factory; extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }, assetListFactory.address); await extensionDelegate.deployed(); } diff --git a/test/liquidation/makeLiquidatableProtocol.ts b/test/liquidation/makeLiquidatableProtocol.ts index 2712276e8..ef15f7dee 100644 --- a/test/liquidation/makeLiquidatableProtocol.ts +++ b/test/liquidation/makeLiquidatableProtocol.ts @@ -6,7 +6,6 @@ import { CometHarness__factory, CometHarnessInterface, OnChainLiquidator__factory, - AssetListFactory__factory, } from '../../build/types'; import { BALANCER_VAULT, @@ -52,15 +51,12 @@ export enum Exchange { } export async function makeProtocol() { - const AssetListFactory = (await ethers.getContractFactory('AssetListFactory')) as AssetListFactory__factory; - const assetListFactory = await AssetListFactory.deploy(); - await assetListFactory.deployed(); // build Comet const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; const name32 = ethers.utils.formatBytes32String('Compound Comet'); const symbol32 = ethers.utils.formatBytes32String('📈BASE'); - const extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }, assetListFactory.address); + const extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }); await extensionDelegate.deployed(); const CometFactory = (await ethers.getContractFactory('CometHarness')) as CometHarness__factory; diff --git a/test/tracking-index-bounds-test.ts b/test/tracking-index-bounds-test.ts index 8897e26ab..c4055b105 100644 --- a/test/tracking-index-bounds-test.ts +++ b/test/tracking-index-bounds-test.ts @@ -26,7 +26,7 @@ describe('total tracking index bounds', function () { totalSupplyBase: BigNumber.from(baseMinForRewards), // 10k USDC base units }); - await fastForward(secondsUntilOverflow-1); + await fastForward(secondsUntilOverflow-2); // First accrue is successful without overflow await comet.accrue(); @@ -58,7 +58,7 @@ describe('total tracking index bounds', function () { totalBorrowBase: BigNumber.from(baseMinForRewards), // 10k USDC base units }); - await fastForward(secondsUntilOverflow-1); + await fastForward(secondsUntilOverflow-2); // First accrue is successful without overflow await comet.accrue(); @@ -153,7 +153,7 @@ describe('total tracking index bounds', function () { totalSupplyBase: BigNumber.from(baseMinForRewards), // 100 WETH base units }); - await fastForward(secondsUntilOverflow-1); + await fastForward(secondsUntilOverflow-2); // First accrue is successful without overflow await comet.accrue(); @@ -186,7 +186,7 @@ describe('total tracking index bounds', function () { totalBorrowBase: BigNumber.from(baseMinForRewards), // 10k USDC base units }); - await fastForward(secondsUntilOverflow-1); + await fastForward(secondsUntilOverflow-2); // First accrue is successful without overflow await comet.accrue(); From 6b62ee6c8950d2e1ad5df8f42249cde64b058c2d Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 12 Aug 2024 12:20:33 +0300 Subject: [PATCH 03/45] fix: clean up --- test/constructor-test.ts | 3 ++- test/liquidation/makeLiquidatableProtocol.ts | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/constructor-test.ts b/test/constructor-test.ts index 74a53d073..3adfc8d89 100644 --- a/test/constructor-test.ts +++ b/test/constructor-test.ts @@ -16,11 +16,12 @@ describe('constructor', function () { it('verifies asset scales', async function () { const [governor, pauseGuardian] = await ethers.getSigners(); + // extension delegate const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; const extensionDelegate = await CometExtFactory.deploy({ name32: ethers.utils.formatBytes32String('Compound Comet'), - symbol32: ethers.utils.formatBytes32String('📈BASE'), + symbol32: ethers.utils.formatBytes32String('📈BASE') }); await extensionDelegate.deployed(); diff --git a/test/liquidation/makeLiquidatableProtocol.ts b/test/liquidation/makeLiquidatableProtocol.ts index ef15f7dee..9561a58cb 100644 --- a/test/liquidation/makeLiquidatableProtocol.ts +++ b/test/liquidation/makeLiquidatableProtocol.ts @@ -5,7 +5,7 @@ import { CometExt__factory, CometHarness__factory, CometHarnessInterface, - OnChainLiquidator__factory, + OnChainLiquidator__factory } from '../../build/types'; import { BALANCER_VAULT, @@ -51,7 +51,6 @@ export enum Exchange { } export async function makeProtocol() { - // build Comet const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; const name32 = ethers.utils.formatBytes32String('Compound Comet'); From d06a3f67e73815c56c566ce634debf902d5b2509 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 12 Aug 2024 12:55:35 +0300 Subject: [PATCH 04/45] fix: gas optimization --- contracts/AssetList.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/AssetList.sol b/contracts/AssetList.sol index 7fc91c3bc..99eb2fb30 100644 --- a/contracts/AssetList.sol +++ b/contracts/AssetList.sol @@ -28,8 +28,9 @@ contract AssetList { uint8 public immutable numAssets; constructor(CometConfiguration.AssetConfig[] memory assetConfigs) { - numAssets = uint8(assetConfigs.length); - for (uint i = 0; i < assetConfigs.length; i++) { + uint8 _numAssets = uint8(assetConfigs.length); + numAssets = _numAssets; + for (uint i = 0; i < _numAssets; i++) { (uint256 asset_a, uint256 asset_b) = getPackedAssetInternal(assetConfigs, i); assets_a.push(asset_a); assets_b.push(asset_b); From d2873adcc4a161a1cbaf7f797a32877d33185e92 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 12 Aug 2024 13:04:04 +0300 Subject: [PATCH 05/45] fix: more gas optimization --- contracts/AssetList.sol | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/AssetList.sol b/contracts/AssetList.sol index 99eb2fb30..127894222 100644 --- a/contracts/AssetList.sol +++ b/contracts/AssetList.sol @@ -30,11 +30,15 @@ contract AssetList { constructor(CometConfiguration.AssetConfig[] memory assetConfigs) { uint8 _numAssets = uint8(assetConfigs.length); numAssets = _numAssets; + uint256[] memory _assets_a = new uint256[](_numAssets); + uint256[] memory _assets_b = new uint256[](_numAssets); for (uint i = 0; i < _numAssets; i++) { (uint256 asset_a, uint256 asset_b) = getPackedAssetInternal(assetConfigs, i); - assets_a.push(asset_a); - assets_b.push(asset_b); + _assets_a[i] = asset_a; + _assets_b[i] = asset_b; } + assets_a = _assets_a; + assets_b = _assets_b; } /** From 5e867a01a4d97e5db3004ff90146c8cd96b0b08c Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 12 Aug 2024 13:06:16 +0300 Subject: [PATCH 06/45] fix: linter fix --- contracts/AssetList.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/AssetList.sol b/contracts/AssetList.sol index 127894222..518dff9fc 100644 --- a/contracts/AssetList.sol +++ b/contracts/AssetList.sol @@ -32,10 +32,11 @@ contract AssetList { numAssets = _numAssets; uint256[] memory _assets_a = new uint256[](_numAssets); uint256[] memory _assets_b = new uint256[](_numAssets); - for (uint i = 0; i < _numAssets; i++) { + for (uint i = 0; i < _numAssets; ) { (uint256 asset_a, uint256 asset_b) = getPackedAssetInternal(assetConfigs, i); _assets_a[i] = asset_a; _assets_b[i] = asset_b; + unchecked { i++; } } assets_a = _assets_a; assets_b = _assets_b; From 8ab17862d8fae405a10533b30b21d746e984ba9c Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 12 Aug 2024 13:08:30 +0300 Subject: [PATCH 07/45] fix: natspec --- contracts/CometExtAssetList.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/CometExtAssetList.sol b/contracts/CometExtAssetList.sol index faf7f955f..3f500be4b 100644 --- a/contracts/CometExtAssetList.sol +++ b/contracts/CometExtAssetList.sol @@ -10,6 +10,7 @@ contract CometExtAssetList is CometExt { /** * @notice Construct a new protocol instance * @param config The mapping of initial/constant parameters + * @param assetListFactoryAddress The address of the asset list factory **/ constructor(ExtConfiguration memory config, address assetListFactoryAddress) CometExt(config) { assetListFactory = assetListFactoryAddress; From 171eb7a5d6d9f5e1f0d20637b4abcde009f588e3 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 12 Aug 2024 13:11:52 +0300 Subject: [PATCH 08/45] fix: more natspec --- contracts/CometExtAssetList.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/CometExtAssetList.sol b/contracts/CometExtAssetList.sol index 3f500be4b..c863eabab 100644 --- a/contracts/CometExtAssetList.sol +++ b/contracts/CometExtAssetList.sol @@ -5,6 +5,7 @@ import "./CometExt.sol"; contract CometExtAssetList is CometExt { + /// @notice The address of the asset list factory address immutable public assetListFactory; /** From 53f15136dc4f037c63bfe5eeabe917327fade461 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Fri, 23 Aug 2024 19:06:16 +0300 Subject: [PATCH 09/45] Update index.ts --- scenario/utils/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenario/utils/index.ts b/scenario/utils/index.ts index 03f59d4d8..742b57830 100644 --- a/scenario/utils/index.ts +++ b/scenario/utils/index.ts @@ -19,7 +19,7 @@ import { isBridgeProposal } from './isBridgeProposal'; export { mineBlocks, setNextBaseFeeToZero, setNextBlockTimestamp }; -export const MAX_ASSETS = 15; +export const MAX_ASSETS = 30; export const UINT256_MAX = 2n ** 256n - 1n; export interface ComparativeAmount { From 8df38e60ca737b0b1956e7efdb34ab6198eb59e7 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 26 Aug 2024 18:02:22 +0300 Subject: [PATCH 10/45] fix: remove unused iterface --- contracts/AssetList.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/AssetList.sol b/contracts/AssetList.sol index 518dff9fc..467de215c 100644 --- a/contracts/AssetList.sol +++ b/contracts/AssetList.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.15; -import "./CometConfiguration.sol"; import "./IPriceFeed.sol"; import "./IERC20NonStandard.sol"; import "./CometMainInterface.sol"; From 70e8a73100636c9efe161d3640120fd3a8da4541 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 26 Aug 2024 18:31:51 +0300 Subject: [PATCH 11/45] feat: add prepare and enact for simulation --- .github/workflows/enact-migration.yaml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index f3a5e4524..4792878dc 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -119,6 +119,7 @@ jobs: GOV_NETWORK: ${{ env.GOV_NETWORK }} REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} if: github.event.inputs.impersonateAccount == '' + - name: Run Enact Migration (impersonate) run: | yarn hardhat migrate --network ${{ github.event.inputs.network }} --deployment ${{ github.event.inputs.deployment }} --enact --overwrite ${{ fromJSON('["", "--simulate"]')[github.event.inputs.simulate == 'true'] }} ${{ fromJSON('["", "--no-enacted"]')[github.event.inputs.no_enacted == 'true'] }} ${{ github.event.inputs.migration }} --impersonate ${{ github.event.inputs.impersonateAccount }} @@ -130,6 +131,26 @@ jobs: GOV_NETWORK: ${{ env.GOV_NETWORK }} REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} if: github.event.inputs.impersonateAccount != '' + - name: Commit changes + if: ${{ github.event.inputs.simulate == 'false' }} + run: | + git config user.name "GitHub Actions Bot" + 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 + + - name: Run Prepare and Enact Migration (impersonate) + run: | + yarn hardhat migrate --network ${{ github.event.inputs.network }} --deployment ${{ github.event.inputs.deployment }} --prepare --enact --overwrite ${{ fromJSON('["", "--simulate"]')[github.event.inputs.simulate == 'true'] }} ${{ fromJSON('["", "--no-enacted"]')[github.event.inputs.no_enacted == 'true'] }} ${{ github.event.inputs.migration }} --impersonate ${{ github.event.inputs.impersonateAccount }} + env: + DEBUG: true + ETH_PK: "${{ inputs.eth_pk }}" + NETWORK_PROVIDER: ${{ fromJSON('["", "http://localhost:8585"]')[github.event.inputs.eth_pk == ''] }} + GOV_NETWORK_PROVIDER: ${{ fromJSON('["", "http://localhost:8685"]')[github.event.inputs.eth_pk == '' && env.GOV_NETWORK != ''] }} + GOV_NETWORK: ${{ env.GOV_NETWORK }} + REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} + if: github.event.inputs.impersonateAccount != '' && github.event.inputs.simulate == 'true' && github.event.inputs.run_id == '0' - name: Commit changes if: ${{ github.event.inputs.simulate == 'false' }} run: | From 4c0a8f426feda48e759eeeb1c73e0d61d27d56b9 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 26 Aug 2024 19:07:39 +0300 Subject: [PATCH 12/45] fix: fix to workflow --- .github/workflows/enact-migration.yaml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index 4792878dc..fa9beada6 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -119,7 +119,6 @@ jobs: GOV_NETWORK: ${{ env.GOV_NETWORK }} REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} if: github.event.inputs.impersonateAccount == '' - - name: Run Enact Migration (impersonate) run: | yarn hardhat migrate --network ${{ github.event.inputs.network }} --deployment ${{ github.event.inputs.deployment }} --enact --overwrite ${{ fromJSON('["", "--simulate"]')[github.event.inputs.simulate == 'true'] }} ${{ fromJSON('["", "--no-enacted"]')[github.event.inputs.no_enacted == 'true'] }} ${{ github.event.inputs.migration }} --impersonate ${{ github.event.inputs.impersonateAccount }} @@ -139,7 +138,6 @@ jobs: 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 - - name: Run Prepare and Enact Migration (impersonate) run: | yarn hardhat migrate --network ${{ github.event.inputs.network }} --deployment ${{ github.event.inputs.deployment }} --prepare --enact --overwrite ${{ fromJSON('["", "--simulate"]')[github.event.inputs.simulate == 'true'] }} ${{ fromJSON('["", "--no-enacted"]')[github.event.inputs.no_enacted == 'true'] }} ${{ github.event.inputs.migration }} --impersonate ${{ github.event.inputs.impersonateAccount }} @@ -150,12 +148,4 @@ jobs: GOV_NETWORK_PROVIDER: ${{ fromJSON('["", "http://localhost:8685"]')[github.event.inputs.eth_pk == '' && env.GOV_NETWORK != ''] }} GOV_NETWORK: ${{ env.GOV_NETWORK }} REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} - if: github.event.inputs.impersonateAccount != '' && github.event.inputs.simulate == 'true' && github.event.inputs.run_id == '0' - - name: Commit changes - if: ${{ github.event.inputs.simulate == 'false' }} - run: | - git config user.name "GitHub Actions Bot" - 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 + if: github.event.inputs.impersonateAccount != '' && github.event.inputs.simulate == 'true' && github.event.inputs.run_id == '0' \ No newline at end of file From c29f4b906f7dd3a6764d45a09d8398cd7c6b1171 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 26 Aug 2024 19:11:49 +0300 Subject: [PATCH 13/45] Update enact-migration.yaml --- .github/workflows/enact-migration.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index fa9beada6..b466632b5 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -139,7 +139,7 @@ jobs: git commit -m "Modified migration from GitHub Actions" || echo "No changes to commit" git push origin - name: Run Prepare and Enact Migration (impersonate) - run: | + run: | yarn hardhat migrate --network ${{ github.event.inputs.network }} --deployment ${{ github.event.inputs.deployment }} --prepare --enact --overwrite ${{ fromJSON('["", "--simulate"]')[github.event.inputs.simulate == 'true'] }} ${{ fromJSON('["", "--no-enacted"]')[github.event.inputs.no_enacted == 'true'] }} ${{ github.event.inputs.migration }} --impersonate ${{ github.event.inputs.impersonateAccount }} env: DEBUG: true From cf08c19cbb3b68cf98cf12ed8a00b3a9b0edc845 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 26 Aug 2024 19:14:18 +0300 Subject: [PATCH 14/45] fix: reverse --- .github/workflows/enact-migration.yaml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index b466632b5..f3a5e4524 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -137,15 +137,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 - - name: Run Prepare and Enact Migration (impersonate) - run: | - yarn hardhat migrate --network ${{ github.event.inputs.network }} --deployment ${{ github.event.inputs.deployment }} --prepare --enact --overwrite ${{ fromJSON('["", "--simulate"]')[github.event.inputs.simulate == 'true'] }} ${{ fromJSON('["", "--no-enacted"]')[github.event.inputs.no_enacted == 'true'] }} ${{ github.event.inputs.migration }} --impersonate ${{ github.event.inputs.impersonateAccount }} - env: - DEBUG: true - ETH_PK: "${{ inputs.eth_pk }}" - NETWORK_PROVIDER: ${{ fromJSON('["", "http://localhost:8585"]')[github.event.inputs.eth_pk == ''] }} - GOV_NETWORK_PROVIDER: ${{ fromJSON('["", "http://localhost:8685"]')[github.event.inputs.eth_pk == '' && env.GOV_NETWORK != ''] }} - GOV_NETWORK: ${{ env.GOV_NETWORK }} - REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} - if: github.event.inputs.impersonateAccount != '' && github.event.inputs.simulate == 'true' && github.event.inputs.run_id == '0' \ No newline at end of file + git push origin \ No newline at end of file From 71fee7b4da8fb8e41559986219b8695133cbe0b1 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 26 Aug 2024 19:21:44 +0300 Subject: [PATCH 15/45] feat: add prepare and enact workflow --- .github/workflows/enact-migration.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index f3a5e4524..706536bcf 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -130,6 +130,17 @@ jobs: GOV_NETWORK: ${{ env.GOV_NETWORK }} REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} if: github.event.inputs.impersonateAccount != '' + - name: Run Prepare and Enact Migration (impersonate) + run: | + yarn hardhat migrate --network ${{ github.event.inputs.network }} --deployment ${{ github.event.inputs.deployment }} --prepare --enact --overwrite ${{ fromJSON('["", "--simulate"]')[github.event.inputs.simulate == 'true'] }} ${{ fromJSON('["", "--no-enacted"]')[github.event.inputs.no_enacted == 'true'] }} ${{ github.event.inputs.migration }} --impersonate ${{ github.event.inputs.impersonateAccount }} + env: + DEBUG: true + ETH_PK: "${{ inputs.eth_pk }}" + NETWORK_PROVIDER: ${{ fromJSON('["", "http://localhost:8585"]')[github.event.inputs.eth_pk == ''] }} + GOV_NETWORK_PROVIDER: ${{ fromJSON('["", "http://localhost:8685"]')[github.event.inputs.eth_pk == '' && env.GOV_NETWORK != ''] }} + GOV_NETWORK: ${{ env.GOV_NETWORK }} + REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} + if: github.event.inputs.impersonateAccount != '' && github.event.inputs.run_id == '0' - name: Commit changes if: ${{ github.event.inputs.simulate == 'false' }} run: | From 57d04f76ebbbb2d7ebeee1d70a5e7898febfcfd1 Mon Sep 17 00:00:00 2001 From: dmitriy-woof-software Date: Mon, 26 Aug 2024 19:04:48 +0200 Subject: [PATCH 16/45] feat: update enact migration script --- .github/workflows/enact-migration.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index 706536bcf..e36e392f8 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -129,7 +129,7 @@ jobs: GOV_NETWORK_PROVIDER: ${{ fromJSON('["", "http://localhost:8685"]')[github.event.inputs.eth_pk == '' && env.GOV_NETWORK != ''] }} GOV_NETWORK: ${{ env.GOV_NETWORK }} REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} - if: github.event.inputs.impersonateAccount != '' + if: github.event.inputs.impersonateAccount != '' && github.event.inputs.run_id != '0' - name: Run Prepare and Enact Migration (impersonate) run: | yarn hardhat migrate --network ${{ github.event.inputs.network }} --deployment ${{ github.event.inputs.deployment }} --prepare --enact --overwrite ${{ fromJSON('["", "--simulate"]')[github.event.inputs.simulate == 'true'] }} ${{ fromJSON('["", "--no-enacted"]')[github.event.inputs.no_enacted == 'true'] }} ${{ github.event.inputs.migration }} --impersonate ${{ github.event.inputs.impersonateAccount }} From f0c33a185d4363df011eaf9807ed367cc6339958 Mon Sep 17 00:00:00 2001 From: dmitriy-woof-software Date: Mon, 26 Aug 2024 19:12:49 +0200 Subject: [PATCH 17/45] feat: update enact migration script --- .github/workflows/enact-migration.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index e36e392f8..75742f6fc 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -106,7 +106,7 @@ jobs: run_id: ${{ github.event.inputs.run_id }} name: ${{ github.event.inputs.network }}-${{ github.event.inputs.deployment }}-${{ github.event.inputs.migration }} path: deployments/${{ github.event.inputs.network }}/${{ github.event.inputs.deployment }}/artifacts/ - if: github.event.inputs.run_id != '' + if: github.event.inputs.run_id != '' || github.event.inputs.run_id != '0' - name: Run Enact Migration run: | From df2d152158ca2193cb4cbe570cfae4fbdf6c4264 Mon Sep 17 00:00:00 2001 From: dmitriy-woof-software Date: Mon, 26 Aug 2024 19:18:59 +0200 Subject: [PATCH 18/45] feat: update enact migration script --- .github/workflows/enact-migration.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index 75742f6fc..6efde642e 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -106,7 +106,7 @@ jobs: run_id: ${{ github.event.inputs.run_id }} name: ${{ github.event.inputs.network }}-${{ github.event.inputs.deployment }}-${{ github.event.inputs.migration }} path: deployments/${{ github.event.inputs.network }}/${{ github.event.inputs.deployment }}/artifacts/ - if: github.event.inputs.run_id != '' || github.event.inputs.run_id != '0' + if: github.event.inputs.run_id != '' || github.event.inputs.run_id != 0 - name: Run Enact Migration run: | @@ -129,7 +129,7 @@ jobs: GOV_NETWORK_PROVIDER: ${{ fromJSON('["", "http://localhost:8685"]')[github.event.inputs.eth_pk == '' && env.GOV_NETWORK != ''] }} GOV_NETWORK: ${{ env.GOV_NETWORK }} REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} - if: github.event.inputs.impersonateAccount != '' && github.event.inputs.run_id != '0' + if: github.event.inputs.impersonateAccount != '' && github.event.inputs.run_id != 0 - name: Run Prepare and Enact Migration (impersonate) run: | yarn hardhat migrate --network ${{ github.event.inputs.network }} --deployment ${{ github.event.inputs.deployment }} --prepare --enact --overwrite ${{ fromJSON('["", "--simulate"]')[github.event.inputs.simulate == 'true'] }} ${{ fromJSON('["", "--no-enacted"]')[github.event.inputs.no_enacted == 'true'] }} ${{ github.event.inputs.migration }} --impersonate ${{ github.event.inputs.impersonateAccount }} @@ -140,7 +140,7 @@ jobs: GOV_NETWORK_PROVIDER: ${{ fromJSON('["", "http://localhost:8685"]')[github.event.inputs.eth_pk == '' && env.GOV_NETWORK != ''] }} GOV_NETWORK: ${{ env.GOV_NETWORK }} REMOTE_ACCOUNTS: ${{ fromJSON('["", "true"]')[github.event.inputs.eth_pk == ''] }} - if: github.event.inputs.impersonateAccount != '' && github.event.inputs.run_id == '0' + if: github.event.inputs.impersonateAccount != '' && github.event.inputs.run_id == 0 - name: Commit changes if: ${{ github.event.inputs.simulate == 'false' }} run: | From 92937aa7f1625ff726bc7576531015b91b54703f Mon Sep 17 00:00:00 2001 From: dmitriy-woof-software Date: Mon, 26 Aug 2024 19:22:37 +0200 Subject: [PATCH 19/45] feat: update enact migration script --- .github/workflows/enact-migration.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index 6efde642e..16fa7a657 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -106,7 +106,7 @@ jobs: run_id: ${{ github.event.inputs.run_id }} name: ${{ github.event.inputs.network }}-${{ github.event.inputs.deployment }}-${{ github.event.inputs.migration }} path: deployments/${{ github.event.inputs.network }}/${{ github.event.inputs.deployment }}/artifacts/ - if: github.event.inputs.run_id != '' || github.event.inputs.run_id != 0 + if: github.event.inputs.run_id != '' && github.event.inputs.run_id != 0 - name: Run Enact Migration run: | From b72092c799053f407eaf3f346898bdd3a4e2c9b1 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Tue, 27 Aug 2024 12:48:46 +0300 Subject: [PATCH 20/45] fix: remove verification from simulatative migration --- tasks/deployment_manager/task.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tasks/deployment_manager/task.ts b/tasks/deployment_manager/task.ts index f68286910..7718ca44d 100644 --- a/tasks/deployment_manager/task.ts +++ b/tasks/deployment_manager/task.ts @@ -215,6 +215,12 @@ task('migrate', 'Runs migration') governanceDm._signers.unshift(signer); } + if(simulate) { + console.log('Simulating migration without verification'); + dm.setVerificationStrategy('lazy'); + governanceDm.setVerificationStrategy('lazy'); + } + const migrationPath = `${__dirname}/../../deployments/${network}/${deployment}/migrations/${migrationName}.ts`; const [migration] = await loadMigrations([migrationPath]); if (!migration) { From dfe98c94c309f80c31002eb0e8ca3fa69c5e793f Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Thu, 19 Sep 2024 17:31:26 +0300 Subject: [PATCH 21/45] feat: fixes after audit --- contracts/CometExt.sol | 2 +- contracts/CometExtAssetList.sol | 4 + contracts/CometExtendedAssetList.sol | 41 ++++- .../test/CometHarnessExtendedAssetList.sol | 85 ++++++++++ ...CometHarnessInterfaceExtendedAssetList.sol | 17 ++ scenario/constraints/ProposalConstraint.ts | 6 + test/absorb-test.ts | 84 +++++++++ test/asset-info-test-asset-list-comet.ts | 159 ++++-------------- test/bulker-test.ts | 157 +++++++++++++++++ test/helpers.ts | 28 ++- 10 files changed, 445 insertions(+), 138 deletions(-) create mode 100644 contracts/test/CometHarnessExtendedAssetList.sol create mode 100644 contracts/test/CometHarnessInterfaceExtendedAssetList.sol diff --git a/contracts/CometExt.sol b/contracts/CometExt.sol index 46962b3ad..a5a75c68e 100644 --- a/contracts/CometExt.sol +++ b/contracts/CometExt.sol @@ -44,7 +44,7 @@ contract CometExt is CometExtInterface { function baseIndexScale() override external pure returns (uint64) { return BASE_INDEX_SCALE; } function factorScale() override external pure returns (uint64) { return FACTOR_SCALE; } function priceScale() override external pure returns (uint64) { return PRICE_SCALE; } - function maxAssets() override external pure returns (uint8) { return MAX_ASSETS; } + function maxAssets() override virtual external pure returns (uint8) { return MAX_ASSETS; } /** * @notice Aggregate variables tracked for the entire market diff --git a/contracts/CometExtAssetList.sol b/contracts/CometExtAssetList.sol index c863eabab..bd6d454c0 100644 --- a/contracts/CometExtAssetList.sol +++ b/contracts/CometExtAssetList.sol @@ -16,4 +16,8 @@ contract CometExtAssetList is CometExt { constructor(ExtConfiguration memory config, address assetListFactoryAddress) CometExt(config) { assetListFactory = assetListFactoryAddress; } + + uint8 internal constant MAX_ASSETS_FOR_ASSET_LIST = 24; + + function maxAssets() override external pure returns (uint8) { return MAX_ASSETS_FOR_ASSET_LIST; } } \ No newline at end of file diff --git a/contracts/CometExtendedAssetList.sol b/contracts/CometExtendedAssetList.sol index d80c1ac35..71af9774d 100644 --- a/contracts/CometExtendedAssetList.sol +++ b/contracts/CometExtendedAssetList.sol @@ -106,6 +106,8 @@ contract CometExtendedAssetList is CometMainInterface { /// @notice The address of the asset list address immutable public assetList; + uint8 internal constant MAX_ASSETS_FOR_ASSET_LIST = 24; + /** * @notice Construct a new protocol instance * @param config The mapping of initial/constant parameters @@ -115,6 +117,7 @@ contract CometExtendedAssetList is CometMainInterface { uint8 decimals_ = IERC20NonStandard(config.baseToken).decimals(); if (decimals_ > MAX_BASE_DECIMALS) revert BadDecimals(); if (config.storeFrontPriceFactor > FACTOR_SCALE) revert BadDiscount(); + if (config.assetConfigs.length > MAX_ASSETS_FOR_ASSET_LIST) revert TooManyAssets(); if (config.baseMinForRewards == 0) revert BadMinimum(); if (IPriceFeed(config.baseTokenPriceFeed).decimals() != PRICE_FEED_DECIMALS) revert BadDecimals(); @@ -377,6 +380,7 @@ contract CometExtendedAssetList is CometMainInterface { } uint16 assetsIn = userBasic[account].assetsIn; + uint8 _reserved = userBasic[account]._reserved; int liquidity = signedMulPrice( presentValue(principal), getPrice(baseTokenPriceFeed), @@ -384,7 +388,7 @@ contract CometExtendedAssetList is CometMainInterface { ); for (uint8 i = 0; i < numAssets; ) { - if (isInAsset(assetsIn, i)) { + if (isInAsset(assetsIn, i, _reserved)) { if (liquidity >= 0) { return true; } @@ -419,6 +423,7 @@ contract CometExtendedAssetList is CometMainInterface { } uint16 assetsIn = userBasic[account].assetsIn; + uint8 _reserved = userBasic[account]._reserved; int liquidity = signedMulPrice( presentValue(principal), getPrice(baseTokenPriceFeed), @@ -426,7 +431,7 @@ contract CometExtendedAssetList is CometMainInterface { ); for (uint8 i = 0; i < numAssets; ) { - if (isInAsset(assetsIn, i)) { + if (isInAsset(assetsIn, i, _reserved)) { if (liquidity >= 0) { return false; } @@ -580,9 +585,17 @@ contract CometExtendedAssetList is CometMainInterface { /** * @dev Whether user has a non-zero balance of an asset, given assetsIn flags + * @dev _reserved is used to check bits 16-23 of assetsIn */ - function isInAsset(uint16 assetsIn, uint8 assetOffset) internal pure returns (bool) { - return (assetsIn & (uint16(1) << assetOffset) != 0); + function isInAsset(uint16 assetsIn, uint8 assetOffset, uint8 _reserved) internal pure returns (bool) { + if (assetOffset < 16) { + // check bit in assetsIn (for bits 0-15) + return (assetsIn & (uint16(1) << assetOffset)) != 0; + } else if (assetOffset < 24) { + // check bit in reserved (for bits 16-23) + return (_reserved & (uint8(1) << (assetOffset - 16))) != 0; + } + return false; // if assetOffset >= 24 (should not happen) } /** @@ -596,10 +609,22 @@ contract CometExtendedAssetList is CometMainInterface { ) internal { if (initialUserBalance == 0 && finalUserBalance != 0) { // set bit for asset - userBasic[account].assetsIn |= (uint16(1) << assetInfo.offset); + if (assetInfo.offset < 16) { + // set bit in assetsIn for bits 0-15 + userBasic[account].assetsIn |= (uint16(1) << assetInfo.offset); + } else if (assetInfo.offset < 24) { + // set bit in _reserved for bits 16-23 + userBasic[account]._reserved |= (uint8(1) << (assetInfo.offset - 16)); + } } else if (initialUserBalance != 0 && finalUserBalance == 0) { // clear bit for asset - userBasic[account].assetsIn &= ~(uint16(1) << assetInfo.offset); + if (assetInfo.offset < 16) { + // clear bit in assetsIn for bits 0-15 + userBasic[account].assetsIn &= ~(uint16(1) << assetInfo.offset); + } else if (assetInfo.offset < 24) { + // clear bit in _reserved for bits 16-23 + userBasic[account]._reserved &= ~(uint8(1) << (assetInfo.offset - 16)); + } } } @@ -1035,12 +1060,13 @@ contract CometExtendedAssetList is CometMainInterface { int104 oldPrincipal = accountUser.principal; int256 oldBalance = presentValue(oldPrincipal); uint16 assetsIn = accountUser.assetsIn; + uint8 _reserved = accountUser._reserved; uint256 basePrice = getPrice(baseTokenPriceFeed); uint256 deltaValue = 0; for (uint8 i = 0; i < numAssets; ) { - if (isInAsset(assetsIn, i)) { + if (isInAsset(assetsIn, i, _reserved)) { AssetInfo memory assetInfo = getAssetInfo(i); address asset = assetInfo.asset; uint128 seizeAmount = userCollateral[account][asset].balance; @@ -1067,6 +1093,7 @@ contract CometExtendedAssetList is CometMainInterface { // reset assetsIn userBasic[account].assetsIn = 0; + userBasic[account]._reserved = 0; (uint104 repayAmount, uint104 supplyAmount) = repayAndSupplyAmount(oldPrincipal, newPrincipal); diff --git a/contracts/test/CometHarnessExtendedAssetList.sol b/contracts/test/CometHarnessExtendedAssetList.sol new file mode 100644 index 000000000..73bc27b94 --- /dev/null +++ b/contracts/test/CometHarnessExtendedAssetList.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "../CometExtendedAssetList.sol"; + +contract CometHarnessExtendedAssetList is CometExtendedAssetList { + uint public nowOverride; + + constructor(Configuration memory config) CometExtendedAssetList(config) {} + + function getNowInternal() override internal view returns (uint40) { + return nowOverride > 0 ? uint40(nowOverride) : super.getNowInternal(); + } + + function getNow() public view returns (uint40) { + return getNowInternal(); + } + + function setNow(uint now_) external { + nowOverride = now_; + } + + function setTotalsBasic(TotalsBasic memory totals) external { + baseSupplyIndex = totals.baseSupplyIndex; + baseBorrowIndex = totals.baseBorrowIndex; + trackingSupplyIndex = totals.trackingSupplyIndex; + trackingBorrowIndex = totals.trackingBorrowIndex; + totalSupplyBase = totals.totalSupplyBase; + totalBorrowBase = totals.totalBorrowBase; + lastAccrualTime = totals.lastAccrualTime; + } + + function setTotalsCollateral(address asset, TotalsCollateral memory totals) external { + totalsCollateral[asset] = totals; + } + + function setBasePrincipal(address account, int104 principal) external { + userBasic[account].principal = principal; + } + + function setCollateralBalance(address account, address asset, uint128 balance) external { + uint128 oldBalance = userCollateral[account][asset].balance; + userCollateral[account][asset].balance = balance; + AssetInfo memory assetInfo = getAssetInfoByAddress(asset); + updateAssetsIn(account, assetInfo, oldBalance, balance); + } + + function updateAssetsInExternal( + address account, + address asset, + uint128 initialUserBalance, + uint128 finalUserBalance + ) external { + AssetInfo memory assetInfo = getAssetInfoByAddress(asset); + updateAssetsIn(account, assetInfo, initialUserBalance, finalUserBalance); + } + + function getAssetList(address account) external view returns (address[] memory result) { + uint16 assetsIn = userBasic[account].assetsIn; + uint8 _reserved = userBasic[account]._reserved; + + uint8 count = 0; + for (uint8 i = 0; i < numAssets; i++) { + if (isInAsset(assetsIn, i, _reserved)) { + count++; + } + } + + result = new address[](count); + + uint j = 0; + for (uint8 i = 0; i < numAssets; i++) { + if (isInAsset(assetsIn, i, _reserved)) { + result[j] = getAssetInfo(i).asset; + j++; + } + } + + return result; + } + + function accrue() external { + accrueInternal(); + } +} \ No newline at end of file diff --git a/contracts/test/CometHarnessInterfaceExtendedAssetList.sol b/contracts/test/CometHarnessInterfaceExtendedAssetList.sol new file mode 100644 index 000000000..7c53d1353 --- /dev/null +++ b/contracts/test/CometHarnessInterfaceExtendedAssetList.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.15; + +import "../CometInterface.sol"; + +abstract contract CometHarnessInterfaceExtendedAssetList is CometInterface { + function accrue() virtual external; + function getNow() virtual external view returns (uint40); + function setNow(uint now_) virtual external; + function setTotalsBasic(TotalsBasic memory totals) virtual external; + function setTotalsCollateral(address asset, TotalsCollateral memory totals) virtual external; + function setBasePrincipal(address account, int104 principal) virtual external; + function setCollateralBalance(address account, address asset, uint128 balance) virtual external; + function updateAssetsInExternal(address account, address asset, uint128 initialUserBalance, uint128 finalUserBalance) virtual external; + function getAssetList(address account) virtual external view returns (address[] memory); + function assetList() virtual external view returns (address); +} diff --git a/scenario/constraints/ProposalConstraint.ts b/scenario/constraints/ProposalConstraint.ts index 83c309740..4c0b970d1 100644 --- a/scenario/constraints/ProposalConstraint.ts +++ b/scenario/constraints/ProposalConstraint.ts @@ -62,6 +62,12 @@ export class ProposalConstraint implements StaticConstra ); } + // temporary hack to skip proposal 329 + if (proposal.id.eq(329)) { + console.log('Skipping proposal 329'); + continue; + } + try { // Execute the proposal debug(`${label} Processing pending proposal ${proposal.id}`); diff --git a/test/absorb-test.ts b/test/absorb-test.ts index 88ae85c5a..8b0fe708b 100644 --- a/test/absorb-test.ts +++ b/test/absorb-test.ts @@ -532,4 +532,88 @@ describe('absorb', function () { expect(await comet.getAssetList(underwater.address)).to.be.empty; }); + + it('updates assetsIn for liquidated account in 24 assets', async () => { + const protocol = await makeProtocol({ + assets: { + // 24 assets + COMP: { + initial: 1e7, + decimals: 18, + initialPrice: 175, + }, + WETH: { + initial: 1e4, + decimals: 18, + initialPrice: 3000, + }, + WBTC: { + initial: 1e3, + decimals: 8, + initialPrice: 41000, + }, + ASSET3: {}, + ASSET4: {}, + ASSET5: {}, + ASSET6: {}, + ASSET7: {}, + ASSET8: {}, + ASSET9: {}, + ASSET10: {}, + ASSET11: {}, + ASSET12: {}, + ASSET13: {}, + ASSET14: {}, + ASSET15: {}, + ASSET16: {}, + ASSET17: {}, + ASSET18: {}, + ASSET19: {}, + ASSET20: {}, + ASSET21: {}, + ASSET22: {}, + ASSET23: {}, + USDC: { + initial: 1e6, + decimals: 6, + }, + }, + reward: 'COMP', + }); + const { cometExtendedAssetList : comet, tokens: { + COMP, + WETH, + }, users: [absorber, underwater] } = protocol; + + await bumpTotalsCollateral(comet, COMP, exp(1, 18)); + await bumpTotalsCollateral(comet, WETH, exp(1, 18)); + + await comet.setCollateralBalance(underwater.address, COMP.address, exp(1, 18)); + await comet.setCollateralBalance(underwater.address, WETH.address, exp(1, 18)); + + + for (let i = 3; i < 24; i++) { + const asset = `ASSET${i}`; + await bumpTotalsCollateral(comet, protocol.tokens[asset], exp(1, 18)); + await comet.setCollateralBalance(underwater.address, protocol.tokens[asset].address, exp(1, 18)); + } + + expect(await comet.getAssetList(underwater.address)).to.deep.equal([ + COMP.address, + WETH.address, + ...Array.from({ length: 21 }, (_, i) => protocol.tokens[`ASSET${i + 3}`].address), + ]); + + const borrowAmount = exp(4000, 6); // borrow of $4k > collateral of $3k + $175 + await comet.setBasePrincipal(underwater.address, -borrowAmount); + await setTotalsBasic(comet, { totalBorrowBase: borrowAmount }); + + const isLiquidatable = await comet.isLiquidatable(underwater.address); + + expect(isLiquidatable).to.be.true; + + await comet.absorb(absorber.address, [underwater.address]); + + expect(await comet.getAssetList(underwater.address)).to.be.empty; + }); }); \ No newline at end of file diff --git a/test/asset-info-test-asset-list-comet.ts b/test/asset-info-test-asset-list-comet.ts index 0e0a0fe4d..14f511b31 100644 --- a/test/asset-info-test-asset-list-comet.ts +++ b/test/asset-info-test-asset-list-comet.ts @@ -1,13 +1,5 @@ -import { expect, exp, makeConfigurator, ONE } from './helpers'; -import { - SimplePriceFeed__factory, - FaucetToken__factory, - CometExtAssetList__factory, - CometExtendedAssetList__factory, - AssetListFactory__factory -} from '../build/types'; +import { expect, exp, makeConfigurator, ONE, makeProtocol } from './helpers'; -import { ethers } from 'hardhat'; describe('asset info', function () { it('initializes protocol', async () => { const { cometExtendedAssetList: comet, tokens } = await makeConfigurator({ @@ -39,121 +31,40 @@ describe('asset info', function () { expect(assetInfo02.liquidateCollateralFactor).to.equal(ONE); }); - it('do NOT reverts if too many assets are passed', async () => { - const signers = await ethers.getSigners(); - - const assets = { - USDC: {}, - ASSET1: {}, - ASSET2: {}, - ASSET3: {}, - ASSET4: {}, - ASSET5: {}, - ASSET6: {}, - ASSET7: {}, - ASSET8: {}, - ASSET9: {}, - ASSET10: {}, - ASSET11: {}, - ASSET12: {}, - ASSET13: {}, - ASSET14: {}, - ASSET15: {}, - ASSET16: {}, - ASSET17: {}, - ASSET18: {}, - ASSET19: {}, - ASSET20: {}, - }; - let priceFeeds = {}; - const PriceFeedFactory = (await ethers.getContractFactory('SimplePriceFeed')) as SimplePriceFeed__factory; - for (const asset in assets) { - const initialPrice = exp(assets[asset].initialPrice || 1, 8); - const priceFeedDecimals = assets[asset].priceFeedDecimals || 8; - const priceFeed = await PriceFeedFactory.deploy(initialPrice, priceFeedDecimals); - await priceFeed.deployed(); - priceFeeds[asset] = priceFeed; - } - - const name32 = ethers.utils.formatBytes32String(('Compound Comet')); - const symbol32 = ethers.utils.formatBytes32String(('📈BASE')); - const governor = signers[0]; - const pauseGuardian = signers[1]; - const base = 'USDC'; - const supplyKink = exp(0.8, 18); - const supplyPerYearInterestRateBase = exp(0.0, 18); - const supplyPerYearInterestRateSlopeLow = exp(0.05, 18); - const supplyPerYearInterestRateSlopeHigh = exp(2, 18); - const borrowKink = exp(0.8, 18); - const borrowPerYearInterestRateBase = exp(0.005, 18); - const borrowPerYearInterestRateSlopeLow = exp(0.1, 18); - const borrowPerYearInterestRateSlopeHigh = exp(3, 18); - const storeFrontPriceFactor = ONE; - const trackingIndexScale = exp(1, 15); - const baseTrackingSupplySpeed = trackingIndexScale; - const baseTrackingBorrowSpeed = trackingIndexScale; - const baseMinForRewards = exp(1, 18); - const baseBorrowMin = exp(1, 18); - const targetReserves = 0; - - const FaucetFactory = (await ethers.getContractFactory('FaucetToken')) as FaucetToken__factory; - const tokens = {}; - for (const symbol in assets) { - const config = assets[symbol]; - const decimals = config.decimals || 18; - const initial = config.initial || 1e6; - const name = config.name || symbol; - const factory = config.factory || FaucetFactory; - let token = (tokens[symbol] = await factory.deploy(initial, name, decimals, symbol)); - await token.deployed(); - } - const AssetListFactory = (await ethers.getContractFactory('AssetListFactory')) as AssetListFactory__factory; - const assetListFactory = await AssetListFactory.deploy(); - await assetListFactory.deployed(); - - const CometExtFactory = (await ethers.getContractFactory('CometExtAssetList')) as CometExtAssetList__factory; - const extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }, assetListFactory.address); - await extensionDelegate.deployed(); - - - const config = { - governor: governor.address, - pauseGuardian: pauseGuardian.address, - extensionDelegate: extensionDelegate.address, - baseToken: tokens[base].address, - baseTokenPriceFeed: priceFeeds[base].address, - supplyKink, - supplyPerYearInterestRateBase, - supplyPerYearInterestRateSlopeLow, - supplyPerYearInterestRateSlopeHigh, - borrowKink, - borrowPerYearInterestRateBase, - borrowPerYearInterestRateSlopeLow, - borrowPerYearInterestRateSlopeHigh, - storeFrontPriceFactor, - trackingIndexScale, - baseTrackingSupplySpeed, - baseTrackingBorrowSpeed, - baseMinForRewards, - baseBorrowMin, - targetReserves, - assetConfigs: Object.entries(assets).reduce((acc, [symbol], _i) => { - if (symbol != base) { - acc.push({ - asset: tokens[symbol].address, - priceFeed: priceFeeds[symbol].address, - decimals: 18, - borrowCollateralFactor: ONE - 1n, - liquidateCollateralFactor: ONE, - liquidationFactor: ONE, - supplyCap: exp(100, 18), - }); - } - return acc; - }, []), - }; - const CometExtendedAssetList = (await ethers.getContractFactory('CometExtendedAssetList')) as CometExtendedAssetList__factory; - await expect(CometExtendedAssetList.deploy(config)).to.not.be.reverted; + it('reverts if too many assets are passed', async () => { + await expect( + makeProtocol({ + assets: { + USDC: {}, + ASSET1: {}, + ASSET2: {}, + ASSET3: {}, + ASSET4: {}, + ASSET5: {}, + ASSET6: {}, + ASSET7: {}, + ASSET8: {}, + ASSET9: {}, + ASSET10: {}, + ASSET11: {}, + ASSET12: {}, + ASSET13: {}, + ASSET14: {}, + ASSET15: {}, + ASSET16: {}, + ASSET17: {}, + ASSET18: {}, + ASSET19: {}, + ASSET20: {}, + ASSET21: {}, + ASSET22: {}, + ASSET23: {}, + ASSET24: {}, + ASSET25: {}, + }, + reward: 'ASSET1', + }) + ).to.be.revertedWith("custom error 'TooManyAssets()'"); }); it('reverts if index is greater than numAssets', async () => { diff --git a/test/bulker-test.ts b/test/bulker-test.ts index 3af444693..ca5c380de 100644 --- a/test/bulker-test.ts +++ b/test/bulker-test.ts @@ -46,6 +46,82 @@ describe('bulker', function () { expect(await comet.collateralBalanceOf(alice.address, COMP.address)).to.be.equal(supplyAmount); }); + it('supply 24 collateral assets', async () => { + const protocol = await makeProtocol({ + assets: { + // 24 assets + USDC: {}, + COMP: {}, + WETH: {}, + ASSET3: {}, + ASSET4: {}, + ASSET5: {}, + ASSET6: {}, + ASSET7: {}, + ASSET8: {}, + ASSET9: {}, + ASSET10: {}, + ASSET11: {}, + ASSET12: {}, + ASSET13: {}, + ASSET14: {}, + ASSET15: {}, + ASSET16: {}, + ASSET17: {}, + ASSET18: {}, + ASSET19: {}, + ASSET20: {}, + ASSET21: {}, + ASSET22: {}, + ASSET23: {}, + }, + reward: 'COMP', + }); + const { cometExtendedAssetList : comet, tokens: { + COMP, + WETH, + USDC, + }, users: [alice] } = protocol; + const bulkerInfo = await makeBulker({ weth: WETH.address }); + const { bulker } = bulkerInfo; + + // Alice approves 10 COMP to Comet + const supplyAmount = exp(10, 18); + await COMP.allocateTo(alice.address, supplyAmount); + await COMP.connect(alice).approve(comet.address, ethers.constants.MaxUint256); + + await USDC.connect(alice).approve(comet.address, ethers.constants.MaxUint256); + + for (let i = 3; i < 24; i++) { + const asset = `ASSET${i}`; + await protocol.tokens[asset].allocateTo(alice.address, supplyAmount); + await protocol.tokens[asset].connect(alice).approve(comet.address, ethers.constants.MaxUint256); + } + + // Alice gives the Bulker permission over her account + await comet.connect(alice).allow(bulker.address, true); + + + // Alice supplies 10 COMP through the bulker + const supplyCOMPCalldata = ethers.utils.defaultAbiCoder.encode(['address', 'address', 'address', 'uint'], [comet.address, alice.address, COMP.address, supplyAmount]); + const actions = [await bulker.ACTION_SUPPLY_ASSET()]; + const calldatas = [supplyCOMPCalldata]; + for(let i = 3; i < 24; i++) { + actions.push(await bulker.ACTION_SUPPLY_ASSET()); + const asset = `ASSET${i}`; + const supplyAssetCalldata = ethers.utils.defaultAbiCoder.encode(['address', 'address', 'address', 'uint'], [comet.address, alice.address, protocol.tokens[asset].address, supplyAmount]); + calldatas.push(supplyAssetCalldata); + } + + await bulker.connect(alice).invoke(actions, calldatas); + + expect(await comet.collateralBalanceOf(alice.address, COMP.address)).to.be.equal(supplyAmount); + for (let i = 3; i < 24; i++) { + const asset = `ASSET${i}`; + expect(await comet.collateralBalanceOf(alice.address, protocol.tokens[asset].address)).to.be.equal(supplyAmount); + } + }); + it('supply collateral asset to a different account', async () => { const protocol = await makeProtocol({}); const { comet, tokens: { COMP, WETH }, users: [alice, bob] } = protocol; @@ -285,6 +361,87 @@ describe('bulker', function () { expect(await COMP.balanceOf(alice.address)).to.be.equal(withdrawAmount); }); + it('withdraw 24 collateral assets', async () => { + const protocol = await makeProtocol({ + assets: { + // 24 assets + USDC: {}, + COMP: {}, + WETH: {}, + ASSET3: {}, + ASSET4: {}, + ASSET5: {}, + ASSET6: {}, + ASSET7: {}, + ASSET8: {}, + ASSET9: {}, + ASSET10: {}, + ASSET11: {}, + ASSET12: {}, + ASSET13: {}, + ASSET14: {}, + ASSET15: {}, + ASSET16: {}, + ASSET17: {}, + ASSET18: {}, + ASSET19: {}, + ASSET20: {}, + ASSET21: {}, + ASSET22: {}, + ASSET23: {}, + }, + reward: 'COMP', + }); + const { cometExtendedAssetList : comet, tokens: { + COMP, + WETH, + }, users: [alice] } = protocol; + const bulkerInfo = await makeBulker({ weth: WETH.address }); + const { bulker } = bulkerInfo; + + // Allocate collateral asset to Comet and Alice's Comet balance + const withdrawAmount = exp(10, 18); + await COMP.allocateTo(comet.address, withdrawAmount); + const t0 = Object.assign({}, await comet.totalsCollateral(COMP.address), { + totalSupplyAsset: withdrawAmount, + }); + await wait(comet.setTotalsCollateral(COMP.address, t0)); + await comet.setCollateralBalance(alice.address, COMP.address, withdrawAmount); + + for(let i = 3; i < 24; i++) { + const asset = `ASSET${i}`; + await protocol.tokens[asset].allocateTo(comet.address, withdrawAmount); + const t1 = Object.assign({}, await comet.totalsCollateral(protocol.tokens[asset].address), { + totalSupplyAsset: withdrawAmount, + }); + await wait(comet.setTotalsCollateral(protocol.tokens[asset].address, t1)); + await comet.setCollateralBalance(alice.address, protocol.tokens[asset].address, withdrawAmount); + } + + // Alice gives the Bulker permission over her account + await comet.connect(alice).allow(bulker.address, true); + + // Alice withdraws 10 COMP through the bulker + const withdrawAssetCalldata = ethers.utils.defaultAbiCoder.encode(['address', 'address', 'address', 'uint'], [comet.address, alice.address, COMP.address, withdrawAmount]); + const actions = [await bulker.ACTION_WITHDRAW_ASSET()]; + const calldatas = [withdrawAssetCalldata]; + for(let i = 3; i < 24; i++) { + actions.push(await bulker.ACTION_WITHDRAW_ASSET()); + const asset = `ASSET${i}`; + const withdrawAssetCalldata = ethers.utils.defaultAbiCoder.encode(['address', 'address', 'address', 'uint'], [comet.address, alice.address, protocol.tokens[asset].address, withdrawAmount]); + calldatas.push(withdrawAssetCalldata); + } + await bulker.connect(alice).invoke(actions, calldatas); + + expect(await comet.collateralBalanceOf(alice.address, COMP.address)).to.be.equal(0); + expect(await COMP.balanceOf(alice.address)).to.be.equal(withdrawAmount); + for (let i = 3; i < 24; i++) { + const asset = `ASSET${i}`; + expect(await comet.collateralBalanceOf(alice.address, protocol.tokens[asset].address)).to.be.equal(0); + expect(await protocol.tokens[asset].balanceOf(alice.address)).to.be.equal(withdrawAmount); + } + }); + it('withdraw collateral asset to a different account', async () => { const protocol = await makeProtocol({}); const { comet, tokens: { COMP, WETH }, users: [alice, bob] } = protocol; diff --git a/test/helpers.ts b/test/helpers.ts index 4c85339a2..8aba14fa8 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -32,10 +32,10 @@ import { CometInterface, NonStandardFaucetFeeToken, NonStandardFaucetFeeToken__factory, - CometExtendedAssetList, - CometExtendedAssetList__factory, AssetListFactory, AssetListFactory__factory, + CometHarnessExtendedAssetList__factory, + CometHarnessInterfaceExtendedAssetList as CometExtendedAssetList, } from '../build/types'; import { BigNumber } from 'ethers'; import { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider'; @@ -310,7 +310,7 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { baseBorrowMin, targetReserves, assetConfigs: Object.entries(assets).reduce((acc, [symbol, config], _i) => { - if (symbol != base) { + if (symbol != base && _i < 12) { acc.push({ asset: tokens[symbol].address, priceFeed: priceFeeds[symbol].address, @@ -327,8 +327,24 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { const comet = await CometFactory.deploy(config); await comet.deployed(); - const CometExtendedAssetList = (await ethers.getContractFactory('CometExtendedAssetList')) as CometExtendedAssetList__factory; - const cometExtendedAssetList = await CometExtendedAssetList.deploy(config); + config.assetConfigs = Object.entries(assets).reduce((acc, [symbol, config], _i) => { + if (symbol != base) { + acc.push({ + asset: tokens[symbol].address, + priceFeed: priceFeeds[symbol].address, + decimals: dfn(assets[symbol].decimals, 18), + borrowCollateralFactor: dfn(config.borrowCF, ONE - 1n), + liquidateCollateralFactor: dfn(config.liquidateCF, ONE), + liquidationFactor: dfn(config.liquidationFactor, ONE), + supplyCap: dfn(config.supplyCap, exp(100, dfn(config.decimals, 18))), + }); + } + return acc; + }, []); + + const CometFactoryExtendedAssetList = (await ethers.getContractFactory('CometHarnessExtendedAssetList')) as CometHarnessExtendedAssetList__factory; + + const cometExtendedAssetList = await CometFactoryExtendedAssetList.deploy(config); await cometExtendedAssetList.deployed(); if (opts.start) await ethers.provider.send('evm_setNextBlockTimestamp', [opts.start]); @@ -351,7 +367,7 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { base, reward, comet: await ethers.getContractAt('CometHarnessInterface', comet.address) as Comet, - cometExtendedAssetList: cometExtendedAssetList, + cometExtendedAssetList: await ethers.getContractAt('CometHarnessInterfaceExtendedAssetList', cometExtendedAssetList.address) as CometExtendedAssetList, assetListFactory: assetListFactory, tokens, unsupportedToken, From 4f2ba04a2ea5ea09b5eaedc6dd7e4391cf8e2225 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Thu, 19 Sep 2024 19:43:47 +0300 Subject: [PATCH 22/45] fix: working tests --- test/asset-info-test.ts | 107 +++++++++++++++++++++++++++++++--------- test/helpers.ts | 15 ++++-- 2 files changed, 96 insertions(+), 26 deletions(-) diff --git a/test/asset-info-test.ts b/test/asset-info-test.ts index 686da6ac1..228ab3667 100644 --- a/test/asset-info-test.ts +++ b/test/asset-info-test.ts @@ -1,4 +1,10 @@ import { expect, exp, makeProtocol, ONE } from './helpers'; +import { ethers } from 'hardhat'; +import { + SimplePriceFeed__factory, + FaucetToken__factory, + CometHarness__factory +} from '../build/types'; describe('asset info', function () { it('initializes protocol', async () => { @@ -34,29 +40,86 @@ describe('asset info', function () { }); it('reverts if too many assets are passed', async () => { + let priceFeeds = {}; + const assets = { + USDC: {}, + ASSET1: {}, + ASSET2: {}, + ASSET3: {}, + ASSET4: {}, + ASSET5: {}, + ASSET6: {}, + ASSET7: {}, + ASSET8: {}, + ASSET9: {}, + ASSET10: {}, + ASSET11: {}, + ASSET12: {}, + ASSET13: {}, + ASSET14: {}, + ASSET15: {}, + ASSET16: {}, + }; + const base = 'USDC'; + const PriceFeedFactory = (await ethers.getContractFactory('SimplePriceFeed')) as SimplePriceFeed__factory; + for (const asset in assets) { + const initialPrice = exp(assets[asset].initialPrice || 1, 8); + const priceFeedDecimals = assets[asset].priceFeedDecimals || 8; + const priceFeed = await PriceFeedFactory.deploy(initialPrice, priceFeedDecimals); + await priceFeed.deployed(); + priceFeeds[asset] = priceFeed; + } + const FaucetFactory = (await ethers.getContractFactory('FaucetToken')) as FaucetToken__factory; + const tokens = {}; + for (const symbol in assets) { + const config = assets[symbol]; + const decimals = config.decimals || 18; + const initial = config.initial || 1e6; + const name = config.name || symbol; + const factory = config.factory || FaucetFactory; + let token; + token = (tokens[symbol] = await factory.deploy(initial, name, decimals, symbol)); + await token.deployed(); + } + const config = { + governor: ethers.constants.AddressZero, + pauseGuardian: ethers.constants.AddressZero, + extensionDelegate: ethers.constants.AddressZero, + baseToken: tokens[base].address, + baseTokenPriceFeed: priceFeeds[base].address, + supplyKink: 0, + supplyPerYearInterestRateBase: 0, + supplyPerYearInterestRateSlopeLow: 0, + supplyPerYearInterestRateSlopeHigh: 0, + borrowKink: 0, + borrowPerYearInterestRateBase: 0, + borrowPerYearInterestRateSlopeLow: 0, + borrowPerYearInterestRateSlopeHigh: 0, + storeFrontPriceFactor: 8, + trackingIndexScale: 0, + baseTrackingSupplySpeed: 0, + baseTrackingBorrowSpeed: 0, + baseMinForRewards: 0, + baseBorrowMin: 0, + targetReserves: 0, + assetConfigs: Object.entries(assets).reduce((acc, [symbol], _i) => { + if (symbol != base) { + acc.push({ + asset: tokens[symbol].address, + priceFeed: priceFeeds[symbol].address, + decimals: 18, + borrowCollateralFactor: ONE - 1n, + liquidateCollateralFactor: ONE, + liquidationFactor: ONE, + supplyCap: exp(100, 18), + }); + } + return acc; + }, []), + }; + const CometFactory = (await ethers.getContractFactory('CometHarness')) as CometHarness__factory; await expect( - makeProtocol({ - assets: { - USDC: {}, - ASSET1: {}, - ASSET2: {}, - ASSET3: {}, - ASSET4: {}, - ASSET5: {}, - ASSET6: {}, - ASSET7: {}, - ASSET8: {}, - ASSET9: {}, - ASSET10: {}, - ASSET11: {}, - ASSET12: {}, - ASSET13: {}, - ASSET14: {}, - ASSET15: {}, - ASSET16: {}, - }, - reward: 'ASSET1', - }) + CometFactory.deploy(config) ).to.be.revertedWith("custom error 'TooManyAssets()'"); }); diff --git a/test/helpers.ts b/test/helpers.ts index 8aba14fa8..1be6a7b06 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -7,6 +7,7 @@ import { BaseBulker, BaseBulker__factory, CometExt, + CometExt__factory, CometExtAssetList__factory, CometHarness__factory, CometHarnessInterface as Comet, @@ -282,8 +283,8 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { let extensionDelegate = opts.extensionDelegate; if (extensionDelegate === undefined) { - const CometExtFactory = (await ethers.getContractFactory('CometExtAssetList')) as CometExtAssetList__factory; - extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }, assetListFactory.address); + const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; + extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }); await extensionDelegate.deployed(); } @@ -310,7 +311,7 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { baseBorrowMin, targetReserves, assetConfigs: Object.entries(assets).reduce((acc, [symbol, config], _i) => { - if (symbol != base && _i < 12) { + if (symbol != base && _i <= 12) { acc.push({ asset: tokens[symbol].address, priceFeed: priceFeeds[symbol].address, @@ -341,7 +342,13 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { } return acc; }, []); - + let extensionDelegateAssetList = opts.extensionDelegate; + if (extensionDelegateAssetList === undefined) { + const CometExtFactory = (await ethers.getContractFactory('CometExtAssetList')) as CometExtAssetList__factory; + extensionDelegateAssetList = await CometExtFactory.deploy({ name32, symbol32 }, assetListFactory.address); + await extensionDelegateAssetList.deployed(); + } + config.extensionDelegate = extensionDelegateAssetList.address; const CometFactoryExtendedAssetList = (await ethers.getContractFactory('CometHarnessExtendedAssetList')) as CometHarnessExtendedAssetList__factory; const cometExtendedAssetList = await CometFactoryExtendedAssetList.deploy(config); From e641f95be678b3384b7eb575605ed33b496265f5 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Fri, 13 Dec 2024 13:43:11 +0200 Subject: [PATCH 23/45] fix: no network issue resolved --- hardhat.config.ts | 15 +++++--- plugins/scenario/Runner.ts | 55 +++++++++++++++++++++++----- plugins/scenario/World.ts | 10 +++-- plugins/scenario/utils/hreForBase.ts | 16 +++++--- tasks/deployment_manager/task.ts | 14 +++---- tasks/scenario/task.ts | 2 +- 6 files changed, 80 insertions(+), 32 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index f7a92ce4b..2e474d544 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -112,11 +112,16 @@ interface NetworkConfig { } const networkConfigs: NetworkConfig[] = [ - { network: 'mainnet', chainId: 1 }, - { network: 'ropsten', chainId: 3 }, - { network: 'rinkeby', chainId: 4 }, - { network: 'goerli', chainId: 5 }, - { network: 'sepolia', chainId: 11155111 }, + { + network: 'mainnet', + chainId: 1, + url: `https://rpc.ankr.com/eth/${ANKR_KEY}`, + }, + { + network: 'sepolia', + chainId: 11155111, + url: `https://rpc.ankr.com/eth_sepolia/${ANKR_KEY}`, + }, { network: 'polygon', chainId: 137, diff --git a/plugins/scenario/Runner.ts b/plugins/scenario/Runner.ts index da19c4ebc..1791e3198 100644 --- a/plugins/scenario/Runner.ts +++ b/plugins/scenario/Runner.ts @@ -153,6 +153,37 @@ export class Runner { } } + +async function retry(fn: () => Promise, retries: number = 10, timeLimit?: number, wait: number = 100) { + try { + return await asyncCallWithTimeout(fn(), timeLimit); + } catch (e) { + if (retries === 0) throw e; + if(e.reason !== 'could not detect network') + throw e; + + console.warn(`Retrying in ${wait}ms...`); + + await new Promise(ok => setTimeout(ok, wait)); + return retry(fn, retries - 1, timeLimit, wait >= 10000 ? 10000 : wait * 2); + } +} +async function asyncCallWithTimeout(asyncPromise: Promise, timeLimit: number = 5000_000) { + let timeoutHandle: string | number | NodeJS.Timeout; + + const timeoutPromise = new Promise((_resolve, reject) => { + timeoutHandle = setTimeout( + () => reject(new Error('Async call timeout limit reached')), + timeLimit + ); + }); + + return Promise.race([asyncPromise, timeoutPromise]).then(result => { + clearTimeout(timeoutHandle); + return result; + }); +} + export async function runScenarios(bases: ForkSpec[]) { const loader = await Loader.load(); const [runningScenarios, skippedScenarios] = loader.splitScenarios(); @@ -161,16 +192,20 @@ export async function runScenarios(bases: ForkSpec[]) { const results: Result[] = []; for (const base of bases) { - const world = new World(base), dm = world.deploymentManager; - const delta = await dm.runDeployScript({ allMissing: true }); - console.log(`[${base.name}] Deployed ${dm.counter} contracts, spent ${dm.spent} to initialize world 🗺`); - console.log(`[${base.name}]\n${dm.diffDelta(delta)}`); - - if (world.auxiliaryDeploymentManager) { - await world.auxiliaryDeploymentManager.spider(); - } - - const runner = new Runner(base, world); + let runner: Runner; + await retry(async () => { + const world = new World(base); + await world.initialize(base); + const dm = world.deploymentManager; + const delta = await dm.runDeployScript({ allMissing: true }); + console.log(`[${base.name}] Deployed ${dm.counter} contracts, spent ${dm.spent} to initialize world 🗺`); + console.log(`[${base.name}]\n${dm.diffDelta(delta)}`); + + if (world.auxiliaryDeploymentManager) { + await world.auxiliaryDeploymentManager.spider(); + } + runner = new Runner(base, world); + }); // NB: contexts are (still) a bit awkward // they prob dont even really need to get passed through here currently diff --git a/plugins/scenario/World.ts b/plugins/scenario/World.ts index ffc8bdb10..35c0b53c6 100644 --- a/plugins/scenario/World.ts +++ b/plugins/scenario/World.ts @@ -28,15 +28,17 @@ export class World { snapshotAuxiliaryDeploymentManager?: DeploymentManager; constructor(base: ForkSpec) { - // Q: should we really need to fork/snapshot the deployment manager? - const hre = hreForBase(base); this.base = base; + } + + async initialize(base: ForkSpec) { + const hre = await hreForBase(base); this.deploymentManager = new DeploymentManager(base.network, base.deployment, hre); + // Q: should we really need to fork/snapshot the deployment manager? this.snapshotDeploymentManager = this.deploymentManager; - if (this.base.auxiliaryBase) { const auxiliaryBase = hre.config.scenario.bases.find(b => b.name === this.base.auxiliaryBase); - this.auxiliaryDeploymentManager = new DeploymentManager(auxiliaryBase.network, auxiliaryBase.deployment, hreForBase(auxiliaryBase)); + this.auxiliaryDeploymentManager = new DeploymentManager(auxiliaryBase.network, auxiliaryBase.deployment, await hreForBase(auxiliaryBase)); this.snapshotAuxiliaryDeploymentManager = this.auxiliaryDeploymentManager; } } diff --git a/plugins/scenario/utils/hreForBase.ts b/plugins/scenario/utils/hreForBase.ts index 5609d9572..454af84e3 100644 --- a/plugins/scenario/utils/hreForBase.ts +++ b/plugins/scenario/utils/hreForBase.ts @@ -1,4 +1,4 @@ -import type { ethers } from 'ethers'; +import { ethers } from 'ethers'; import type { HardhatEthersHelpers } from '@nomiclabs/hardhat-ethers/types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { HardhatContext } from 'hardhat/internal/context'; @@ -36,7 +36,7 @@ declare module 'hardhat/internal/core/runtime-environment' { } } -export function nonForkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment { +export async function nonForkedHreForBase(base: ForkSpec): Promise { const ctx: HardhatContext = HardhatContext.getHardhatContext(); const hardhatArguments = getEnvHardhatArguments( @@ -61,7 +61,7 @@ export function nonForkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment { ); } -export function forkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment { +export async function forkedHreForBase(base: ForkSpec): Promise { const ctx: HardhatContext = HardhatContext.getHardhatContext(); const hardhatArguments = getEnvHardhatArguments(HARDHAT_PARAM_DEFINITIONS, process.env); @@ -73,6 +73,12 @@ export function forkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment { const baseNetwork = networks[base.network] as HttpNetworkUserConfig; + const provider = new ethers.providers.JsonRpcProvider(baseNetwork.url); + + // noNetwork otherwise + if(!base.blockNumber) + base.blockNumber = await provider.getBlockNumber() - 210; // arbitrary number of blocks to go back, about 1 hour + if (!baseNetwork) { throw new Error(`cannot find network config for network: ${base.network}`); } @@ -96,7 +102,7 @@ export function forkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment { defaultNetwork: 'hardhat', networks: { hardhat: forkedNetwork, - localhost + localhost: localhost }, }, }; @@ -111,7 +117,7 @@ export function forkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment { ); } -export default function hreForBase(base: ForkSpec, fork = true): HardhatRuntimeEnvironment { +export default async function hreForBase(base: ForkSpec, fork = true): Promise { if (fork) { return forkedHreForBase(base); } else { diff --git a/tasks/deployment_manager/task.ts b/tasks/deployment_manager/task.ts index 5e08b7e37..1a7d84997 100644 --- a/tasks/deployment_manager/task.ts +++ b/tasks/deployment_manager/task.ts @@ -7,12 +7,12 @@ import { impersonateAddress } from '../../plugins/scenario/utils'; import hreForBase from '../../plugins/scenario/utils/hreForBase'; // TODO: Don't depend on scenario's hreForBase -function getForkEnv(env: HardhatRuntimeEnvironment, deployment: string): HardhatRuntimeEnvironment { +async function getForkEnv(env: HardhatRuntimeEnvironment, deployment: string): Promise { const base = env.config.scenario.bases.find(b => b.network == env.network.name && b.deployment == deployment); if (!base) { throw new Error(`No fork spec for ${env.network.name}`); } - return hreForBase(base); + return await hreForBase(base); } function getDefaultDeployment(config: HardhatConfig, network: string): string { @@ -65,7 +65,7 @@ task('deploy', 'Deploys market') .addFlag('overwrite', 'overwrites cache') .addParam('deployment', 'The deployment to deploy') .setAction(async ({ simulate, noDeploy, noVerify, noVerifyImpl, overwrite, deployment }, env) => { - const maybeForkEnv = simulate ? getForkEnv(env, deployment) : env; + const maybeForkEnv = simulate ? await getForkEnv(env, deployment) : env; const network = env.network.name; const tag = `${network}/${deployment}`; const dm = new DeploymentManager( @@ -174,7 +174,7 @@ task('migrate', 'Runs migration') .addFlag('overwrite', 'overwrites artifact if exists, fails otherwise') .setAction( async ({ migration: migrationName, prepare, enact, noEnacted, simulate, overwrite, deployment, impersonate }, env) => { - const maybeForkEnv = simulate ? getForkEnv(env, deployment) : env; + const maybeForkEnv = simulate ? await getForkEnv(env, deployment) : env; const network = env.network.name; const dm = new DeploymentManager( network, @@ -193,7 +193,7 @@ task('migrate', 'Runs migration') const governanceBase = isBridgedDeployment ? env.config.scenario.bases.find(b => b.name === base.auxiliaryBase) : undefined; if (governanceBase) { - const governanceEnv = hreForBase(governanceBase, simulate); + const governanceEnv = await hreForBase(governanceBase, simulate); governanceDm = new DeploymentManager( governanceBase.network, governanceBase.deployment, @@ -246,7 +246,7 @@ task('deploy_and_migrate', 'Runs deploy and migration') .addParam('deployment', 'The deployment to deploy') .setAction( async ({ migration: migrationName, prepare, enact, noEnacted, simulate, overwrite, deployment, impersonate, noDeploy, noVerify, noVerifyImpl }, env) => { - const maybeForkEnv = simulate ? getForkEnv(env, deployment) : env; + const maybeForkEnv = simulate ? await getForkEnv(env, deployment) : env; const network = env.network.name; const tag = `${network}/${deployment}`; const dm = new DeploymentManager( @@ -314,7 +314,7 @@ task('deploy_and_migrate', 'Runs deploy and migration') const governanceBase = isBridgedDeployment ? env.config.scenario.bases.find(b => b.name === base.auxiliaryBase) : undefined; if (governanceBase) { - const governanceEnv = hreForBase(governanceBase, simulate); + const governanceEnv = await hreForBase(governanceBase, simulate); governanceDm = new DeploymentManager( governanceBase.network, governanceBase.deployment, diff --git a/tasks/scenario/task.ts b/tasks/scenario/task.ts index 658623144..36ddc1c1b 100644 --- a/tasks/scenario/task.ts +++ b/tasks/scenario/task.ts @@ -39,7 +39,7 @@ task('scenario:spider', 'Runs spider in preparation for scenarios') const bases: ForkSpec[] = getBasesFromTaskArgs(taskArgs.bases, env); await Promise.all(bases.map(async (base) => { if (base.network !== 'hardhat') { - let hre = hreForBase(base); + let hre = await hreForBase(base); let dm = new DeploymentManager( base.name, base.deployment, From 5c75787759f1a7b415512e9e4c47ab253ee07262 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 23 Dec 2024 14:35:33 +0200 Subject: [PATCH 24/45] fix: audit fixes --- contracts/AssetList.sol | 189 ++++++++++++++++-- contracts/AssetListFactory.sol | 5 + ... => CometFactoryWithExtendedAssetList.sol} | 6 +- ...ist.sol => CometWithExtendedAssetList.sol} | 4 +- contracts/IAssetList.sol | 1 + contracts/IAssetListFactory.sol | 5 + contracts/IAssetListFactoryHolder.sol | 4 + .../test/CometHarnessExtendedAssetList.sol | 6 +- test/helpers.ts | 25 ++- 9 files changed, 213 insertions(+), 32 deletions(-) rename contracts/{CometFactoryExtendedAssetList.sol => CometFactoryWithExtendedAssetList.sol} (51%) rename contracts/{CometExtendedAssetList.sol => CometWithExtendedAssetList.sol} (99%) diff --git a/contracts/AssetList.sol b/contracts/AssetList.sol index 467de215c..6ca5c74da 100644 --- a/contracts/AssetList.sol +++ b/contracts/AssetList.sol @@ -20,8 +20,54 @@ contract AssetList { /// @dev The max value for a collateral factor (1) uint64 internal constant MAX_COLLATERAL_FACTOR = FACTOR_SCALE; - uint256[] internal assets_a; - uint256[] internal assets_b; + uint256 internal immutable asset00_a; + uint256 internal immutable asset00_b; + uint256 internal immutable asset01_a; + uint256 internal immutable asset01_b; + uint256 internal immutable asset02_a; + uint256 internal immutable asset02_b; + uint256 internal immutable asset03_a; + uint256 internal immutable asset03_b; + uint256 internal immutable asset04_a; + uint256 internal immutable asset04_b; + uint256 internal immutable asset05_a; + uint256 internal immutable asset05_b; + uint256 internal immutable asset06_a; + uint256 internal immutable asset06_b; + uint256 internal immutable asset07_a; + uint256 internal immutable asset07_b; + uint256 internal immutable asset08_a; + uint256 internal immutable asset08_b; + uint256 internal immutable asset09_a; + uint256 internal immutable asset09_b; + uint256 internal immutable asset10_a; + uint256 internal immutable asset10_b; + uint256 internal immutable asset11_a; + uint256 internal immutable asset11_b; + uint256 internal immutable asset12_a; + uint256 internal immutable asset12_b; + uint256 internal immutable asset13_a; + uint256 internal immutable asset13_b; + uint256 internal immutable asset14_a; + uint256 internal immutable asset14_b; + uint256 internal immutable asset15_a; + uint256 internal immutable asset15_b; + uint256 internal immutable asset16_a; + uint256 internal immutable asset16_b; + uint256 internal immutable asset17_a; + uint256 internal immutable asset17_b; + uint256 internal immutable asset18_a; + uint256 internal immutable asset18_b; + uint256 internal immutable asset19_a; + uint256 internal immutable asset19_b; + uint256 internal immutable asset20_a; + uint256 internal immutable asset20_b; + uint256 internal immutable asset21_a; + uint256 internal immutable asset21_b; + uint256 internal immutable asset22_a; + uint256 internal immutable asset22_b; + uint256 internal immutable asset23_a; + uint256 internal immutable asset23_b; /// @notice The number of assets this contract actually supports uint8 public immutable numAssets; @@ -29,20 +75,38 @@ contract AssetList { constructor(CometConfiguration.AssetConfig[] memory assetConfigs) { uint8 _numAssets = uint8(assetConfigs.length); numAssets = _numAssets; - uint256[] memory _assets_a = new uint256[](_numAssets); - uint256[] memory _assets_b = new uint256[](_numAssets); - for (uint i = 0; i < _numAssets; ) { - (uint256 asset_a, uint256 asset_b) = getPackedAssetInternal(assetConfigs, i); - _assets_a[i] = asset_a; - _assets_b[i] = asset_b; - unchecked { i++; } - } - assets_a = _assets_a; - assets_b = _assets_b; + + (asset00_a, asset00_b) = getPackedAssetInternal(assetConfigs, 0); + (asset01_a, asset01_b) = getPackedAssetInternal(assetConfigs, 1); + (asset02_a, asset02_b) = getPackedAssetInternal(assetConfigs, 2); + (asset03_a, asset03_b) = getPackedAssetInternal(assetConfigs, 3); + (asset04_a, asset04_b) = getPackedAssetInternal(assetConfigs, 4); + (asset05_a, asset05_b) = getPackedAssetInternal(assetConfigs, 5); + (asset06_a, asset06_b) = getPackedAssetInternal(assetConfigs, 6); + (asset07_a, asset07_b) = getPackedAssetInternal(assetConfigs, 7); + (asset08_a, asset08_b) = getPackedAssetInternal(assetConfigs, 8); + (asset09_a, asset09_b) = getPackedAssetInternal(assetConfigs, 9); + (asset10_a, asset10_b) = getPackedAssetInternal(assetConfigs, 10); + (asset11_a, asset11_b) = getPackedAssetInternal(assetConfigs, 11); + (asset12_a, asset12_b) = getPackedAssetInternal(assetConfigs, 12); + (asset13_a, asset13_b) = getPackedAssetInternal(assetConfigs, 13); + (asset14_a, asset14_b) = getPackedAssetInternal(assetConfigs, 14); + (asset15_a, asset15_b) = getPackedAssetInternal(assetConfigs, 15); + (asset16_a, asset16_b) = getPackedAssetInternal(assetConfigs, 16); + (asset17_a, asset17_b) = getPackedAssetInternal(assetConfigs, 17); + (asset18_a, asset18_b) = getPackedAssetInternal(assetConfigs, 18); + (asset19_a, asset19_b) = getPackedAssetInternal(assetConfigs, 19); + (asset20_a, asset20_b) = getPackedAssetInternal(assetConfigs, 20); + (asset21_a, asset21_b) = getPackedAssetInternal(assetConfigs, 21); + (asset22_a, asset22_b) = getPackedAssetInternal(assetConfigs, 22); + (asset23_a, asset23_b) = getPackedAssetInternal(assetConfigs, 23); } /** * @dev Checks and gets the packed asset info for storage + * @param assetConfigs The asset configurations + * @param i The index of the asset info to get + * @return The packed asset info */ function getPackedAssetInternal(CometConfiguration.AssetConfig[] memory assetConfigs, uint i) internal view returns (uint256, uint256) { CometConfiguration.AssetConfig memory assetConfig; @@ -102,9 +166,104 @@ contract AssetList { */ function getAssetInfo(uint8 i) public view returns (CometCore.AssetInfo memory) { if (i >= numAssets) revert CometMainInterface.BadAsset(); - - uint256 word_a = assets_a[i]; - uint256 word_b = assets_b[i]; + uint256 word_a; + uint256 word_b; + if(i == 0){ + word_a = asset00_a; + word_b = asset00_b; + } + if(i == 1){ + word_a = asset01_a; + word_b = asset01_b; + } + if(i == 2){ + word_a = asset02_a; + word_b = asset02_b; + } + if(i == 3){ + word_a = asset03_a; + word_b = asset03_b; + } + if(i == 4){ + word_a = asset04_a; + word_b = asset04_b; + } + if(i == 5){ + word_a = asset05_a; + word_b = asset05_b; + } + if(i == 6){ + word_a = asset06_a; + word_b = asset06_b; + } + if(i == 7){ + word_a = asset07_a; + word_b = asset07_b; + } + if(i == 8){ + word_a = asset08_a; + word_b = asset08_b; + } + if(i == 9){ + word_a = asset09_a; + word_b = asset09_b; + } + if(i == 10){ + word_a = asset10_a; + word_b = asset10_b; + } + if(i == 11){ + word_a = asset11_a; + word_b = asset11_b; + } + if(i == 12){ + word_a = asset12_a; + word_b = asset12_b; + } + if(i == 13){ + word_a = asset13_a; + word_b = asset13_b; + } + if(i == 14){ + word_a = asset14_a; + word_b = asset14_b; + } + if(i == 15){ + word_a = asset15_a; + word_b = asset15_b; + } + if(i == 16){ + word_a = asset16_a; + word_b = asset16_b; + } + if(i == 17){ + word_a = asset17_a; + word_b = asset17_b; + } + if(i == 18){ + word_a = asset18_a; + word_b = asset18_b; + } + if(i == 19){ + word_a = asset19_a; + word_b = asset19_b; + } + if(i == 20){ + word_a = asset20_a; + word_b = asset20_b; + } + if(i == 21){ + word_a = asset21_a; + word_b = asset21_b; + } + if(i == 22){ + word_a = asset22_a; + word_b = asset22_b; + } + if(i == 23){ + word_a = asset23_a; + word_b = asset23_b; + } address asset = address(uint160(word_a & type(uint160).max)); uint64 rescale = FACTOR_SCALE / 1e4; diff --git a/contracts/AssetListFactory.sol b/contracts/AssetListFactory.sol index 52c190adc..ba3218ff0 100644 --- a/contracts/AssetListFactory.sol +++ b/contracts/AssetListFactory.sol @@ -10,6 +10,11 @@ import "./AssetList.sol"; contract AssetListFactory { event AssetListCreated(address indexed assetList, CometCore.AssetConfig[] assetConfigs); + /** + * @notice Create a new asset list + * @param assetConfigs The asset configurations + * @return assetList The address of the new asset list + */ function createAssetList(CometCore.AssetConfig[] memory assetConfigs) external returns (address assetList) { assetList = address(new AssetList(assetConfigs)); emit AssetListCreated(assetList, assetConfigs); diff --git a/contracts/CometFactoryExtendedAssetList.sol b/contracts/CometFactoryWithExtendedAssetList.sol similarity index 51% rename from contracts/CometFactoryExtendedAssetList.sol rename to contracts/CometFactoryWithExtendedAssetList.sol index 5d30705f7..d95244e2a 100644 --- a/contracts/CometFactoryExtendedAssetList.sol +++ b/contracts/CometFactoryWithExtendedAssetList.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.15; -import "./CometExtendedAssetList.sol"; +import "./CometWithExtendedAssetList.sol"; import "./CometConfiguration.sol"; -contract CometFactoryExtendedAssetList is CometConfiguration { +contract CometFactoryWithExtendedAssetList is CometConfiguration { function clone(Configuration calldata config) external returns (address) { - return address(new CometExtendedAssetList(config)); + return address(new CometWithExtendedAssetList(config)); } } \ No newline at end of file diff --git a/contracts/CometExtendedAssetList.sol b/contracts/CometWithExtendedAssetList.sol similarity index 99% rename from contracts/CometExtendedAssetList.sol rename to contracts/CometWithExtendedAssetList.sol index 71af9774d..8ca1e0735 100644 --- a/contracts/CometExtendedAssetList.sol +++ b/contracts/CometWithExtendedAssetList.sol @@ -13,7 +13,7 @@ import "./IAssetList.sol"; * @notice An efficient monolithic money market protocol * @author Compound */ -contract CometExtendedAssetList is CometMainInterface { +contract CometWithExtendedAssetList is CometMainInterface { /** General configuration constants **/ /// @notice The admin of the protocol @@ -1239,7 +1239,7 @@ contract CometExtendedAssetList is CometMainInterface { /** * @notice Fallback to calling the extension delegate for everything else */ - fallback() external payable { + fallback() external { address delegate = extensionDelegate; assembly { calldatacopy(0, 0, calldatasize()) diff --git a/contracts/IAssetList.sol b/contracts/IAssetList.sol index 584e6cc2b..bdc6b8aae 100644 --- a/contracts/IAssetList.sol +++ b/contracts/IAssetList.sol @@ -9,4 +9,5 @@ import "./CometCore.sol"; */ interface IAssetList { function getAssetInfo(uint8 i) external view returns (CometCore.AssetInfo memory); + function numAssets() external view returns (uint8); } \ No newline at end of file diff --git a/contracts/IAssetListFactory.sol b/contracts/IAssetListFactory.sol index 9f41c28a5..7e89c5da1 100644 --- a/contracts/IAssetListFactory.sol +++ b/contracts/IAssetListFactory.sol @@ -7,5 +7,10 @@ import "./CometCore.sol"; * @author Compound */ interface IAssetListFactory { + /** + * @notice Create a new asset list + * @param assetConfigs The asset configurations + * @return assetList The address of the new asset list + */ function createAssetList(CometCore.AssetConfig[] memory assetConfigs) external returns (address assetList); } \ No newline at end of file diff --git a/contracts/IAssetListFactoryHolder.sol b/contracts/IAssetListFactoryHolder.sol index 0691cada7..8ba2ab551 100644 --- a/contracts/IAssetListFactoryHolder.sol +++ b/contracts/IAssetListFactoryHolder.sol @@ -6,5 +6,9 @@ pragma solidity 0.8.15; * @author Compound */ interface IAssetListFactoryHolder { + /** + * @notice Get the asset list factory + * @return assetListFactory The asset list factory + */ function assetListFactory() external view returns (address); } \ No newline at end of file diff --git a/contracts/test/CometHarnessExtendedAssetList.sol b/contracts/test/CometHarnessExtendedAssetList.sol index 73bc27b94..0ab2845c8 100644 --- a/contracts/test/CometHarnessExtendedAssetList.sol +++ b/contracts/test/CometHarnessExtendedAssetList.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.15; -import "../CometExtendedAssetList.sol"; +import "../CometWithExtendedAssetList.sol"; -contract CometHarnessExtendedAssetList is CometExtendedAssetList { +contract CometHarnessExtendedAssetList is CometWithExtendedAssetList { uint public nowOverride; - constructor(Configuration memory config) CometExtendedAssetList(config) {} + constructor(Configuration memory config) CometWithExtendedAssetList(config) {} function getNowInternal() override internal view returns (uint40) { return nowOverride > 0 ? uint40(nowOverride) : super.getNowInternal(); diff --git a/test/helpers.ts b/test/helpers.ts index 8aba14fa8..535b4e178 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -7,6 +7,7 @@ import { BaseBulker, BaseBulker__factory, CometExt, + CometExt__factory, CometExtAssetList__factory, CometHarness__factory, CometHarnessInterface as Comet, @@ -35,7 +36,7 @@ import { AssetListFactory, AssetListFactory__factory, CometHarnessExtendedAssetList__factory, - CometHarnessInterfaceExtendedAssetList as CometExtendedAssetList, + CometHarnessInterfaceExtendedAssetList as CometWithExtendedAssetList, } from '../build/types'; import { BigNumber } from 'ethers'; import { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider'; @@ -102,7 +103,7 @@ export type Protocol = { base: string; reward: string; comet: Comet; - cometExtendedAssetList: CometExtendedAssetList; + cometWithExtendedAssetList: CometWithExtendedAssetList; assetListFactory: AssetListFactory; tokens: { [symbol: string]: FaucetToken | NonStandardFaucetFeeToken; @@ -282,8 +283,8 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { let extensionDelegate = opts.extensionDelegate; if (extensionDelegate === undefined) { - const CometExtFactory = (await ethers.getContractFactory('CometExtAssetList')) as CometExtAssetList__factory; - extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }, assetListFactory.address); + const CometExtFactory = (await ethers.getContractFactory('CometExt')) as CometExt__factory; + extensionDelegate = await CometExtFactory.deploy({ name32, symbol32 }); await extensionDelegate.deployed(); } @@ -310,7 +311,7 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { baseBorrowMin, targetReserves, assetConfigs: Object.entries(assets).reduce((acc, [symbol, config], _i) => { - if (symbol != base && _i < 12) { + if (symbol != base && _i <= 12) { acc.push({ asset: tokens[symbol].address, priceFeed: priceFeeds[symbol].address, @@ -341,7 +342,13 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { } return acc; }, []); - + let extensionDelegateAssetList = opts.extensionDelegate; + if (extensionDelegateAssetList === undefined) { + const CometExtFactory = (await ethers.getContractFactory('CometExtAssetList')) as CometExtAssetList__factory; + extensionDelegateAssetList = await CometExtFactory.deploy({ name32, symbol32 }, assetListFactory.address); + await extensionDelegateAssetList.deployed(); + } + config.extensionDelegate = extensionDelegateAssetList.address; const CometFactoryExtendedAssetList = (await ethers.getContractFactory('CometHarnessExtendedAssetList')) as CometHarnessExtendedAssetList__factory; const cometExtendedAssetList = await CometFactoryExtendedAssetList.deploy(config); @@ -367,7 +374,7 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { base, reward, comet: await ethers.getContractAt('CometHarnessInterface', comet.address) as Comet, - cometExtendedAssetList: await ethers.getContractAt('CometHarnessInterfaceExtendedAssetList', cometExtendedAssetList.address) as CometExtendedAssetList, + cometWithExtendedAssetList: await ethers.getContractAt('CometHarnessInterfaceExtendedAssetList', cometExtendedAssetList.address) as CometWithExtendedAssetList, assetListFactory: assetListFactory, tokens, unsupportedToken, @@ -387,7 +394,7 @@ export async function makeConfigurator(opts: ProtocolOpts = {}): Promise Date: Mon, 23 Dec 2024 15:25:10 +0200 Subject: [PATCH 25/45] fix --- contracts/CometWithExtendedAssetList.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/CometWithExtendedAssetList.sol b/contracts/CometWithExtendedAssetList.sol index 8ca1e0735..5e5659ec8 100644 --- a/contracts/CometWithExtendedAssetList.sol +++ b/contracts/CometWithExtendedAssetList.sol @@ -1239,7 +1239,7 @@ contract CometWithExtendedAssetList is CometMainInterface { /** * @notice Fallback to calling the extension delegate for everything else */ - fallback() external { + fallback() external payable { address delegate = extensionDelegate; assembly { calldatacopy(0, 0, calldatasize()) From 6635049a8315a7eb6412e0be29bc63a827699e84 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Thu, 26 Dec 2024 22:38:59 +0200 Subject: [PATCH 26/45] feat: working scenarios --- .github/workflows/deploy-market.yaml | 8 +- .github/workflows/enact-migration.yaml | 16 +- .github/workflows/prepare-migration.yaml | 6 +- .github/workflows/run-scenarios.yaml | 2 +- .github/workflows/run-slither.yaml | 2 +- MIGRATIONS.md | 16 +- README.md | 4 +- SCENARIO.md | 2 +- .../arbitrum-goerli/usdc.e/configuration.json | 56 ---- deployments/arbitrum-goerli/usdc.e/deploy.ts | 70 ----- .../1679518383_configurate_and_ens.ts | 296 ------------------ .../arbitrum-goerli/usdc.e/relations.ts | 29 -- deployments/arbitrum-goerli/usdc.e/roots.json | 7 - .../arbitrum-goerli/usdc/configuration.json | 56 ---- deployments/arbitrum-goerli/usdc/deploy.ts | 37 --- .../1689112067_configurate_and_ens.ts | 283 ----------------- deployments/arbitrum-goerli/usdc/relations.ts | 29 -- deployments/arbitrum-goerli/usdc/roots.json | 8 - deployments/arbitrum/usdc/relations.ts | 8 + .../base-goerli/usdc/configuration.json | 47 --- deployments/base-goerli/usdc/deploy.ts | 97 ------ .../1679592519_configurate_and_ens.ts | 206 ------------ deployments/base-goerli/usdc/relations.ts | 24 -- deployments/base-goerli/usdc/roots.json | 10 - .../base-goerli/weth/configuration.json | 38 --- deployments/base-goerli/weth/deploy.ts | 70 ----- .../1685486850_configurate_and_ens.ts | 235 -------------- deployments/base-goerli/weth/relations.ts | 24 -- deployments/base-goerli/weth/roots.json | 10 - deployments/goerli/usdc/configuration.json | 52 --- deployments/goerli/usdc/deploy.ts | 80 ----- .../usdc/migrations/1663870047_add_link.ts | 116 ------- ...sorb_transfer_event_and_auto_collateral.ts | 58 ---- .../1681942579_upgrade_governor_bravo.ts | 62 ---- deployments/goerli/usdc/relations.ts | 94 ------ deployments/goerli/usdc/roots.json | 22 -- deployments/goerli/weth/configuration.json | 44 --- deployments/goerli/weth/deploy.ts | 148 --------- .../1672860425_initialize_market.ts | 97 ------ ...48_set_up_ens_subdomain_and_text_record.ts | 103 ------ deployments/goerli/weth/relations.ts | 20 -- deployments/goerli/weth/roots.json | 8 - .../linea-goerli/usdc/configuration.json | 46 --- deployments/linea-goerli/usdc/deploy.ts | 91 ------ .../1686918613_configurate_and_ens.ts | 250 --------------- .../1687878801_increase_supply_caps.ts | 112 ------- deployments/linea-goerli/usdc/relations.ts | 37 --- deployments/linea-goerli/usdc/roots.json | 10 - deployments/mainnet/usdt/relations.ts | 8 + deployments/mumbai/usdc/configuration.json | 59 ---- deployments/mumbai/usdc/deploy.ts | 203 ------------ .../1676659582_configurate_and_ens.ts | 259 --------------- deployments/mumbai/usdc/relations.ts | 9 - deployments/mumbai/usdc/roots.json | 9 - deployments/optimism/usdc/relations.ts | 9 + deployments/relations.ts | 9 +- .../scroll-goerli/usdc/configuration.json | 37 --- deployments/scroll-goerli/usdc/deploy.ts | 98 ------ .../1694594095_configurate_and_ens.ts | 229 -------------- deployments/scroll-goerli/usdc/relations.ts | 42 --- deployments/scroll-goerli/usdc/roots.json | 12 - hardhat.config.ts | 156 +-------- plugins/deployment_manager/test/VerifyTest.ts | 10 +- plugins/import/etherscan.ts | 18 -- plugins/scenario/utils/hreForBase.ts | 2 +- scenario/AddMaticxCollateralScenario.ts | 10 +- scenario/BulkerScenario.ts | 170 ++++++---- scenario/CrossChainGovernanceScenario.ts | 8 +- scenario/InterestRateScenario.ts | 7 - scenario/SupplyScenario.ts | 2 + scenario/TransferScenario.ts | 30 +- scenario/WithdrawScenario.ts | 48 +-- scenario/constraints/ProposalConstraint.ts | 6 +- scenario/utils/index.ts | 38 +-- scenario/utils/isBridgeProposal.ts | 26 +- scenario/utils/relayArbitrumMessage.ts | 10 +- scenario/utils/relayBaseMessage.ts | 2 +- scenario/utils/relayMessage.ts | 6 +- scenario/utils/relayScrollMessage.ts | 17 +- scenario/utils/scenarioHelper.ts | 17 + scripts/CCTP-attestation.ts | 2 +- scripts/liquidation_bot/index.ts | 6 +- .../liquidateUnderwaterBorrowers.ts | 12 - src/deploy/index.ts | 22 +- 84 files changed, 296 insertions(+), 4458 deletions(-) delete mode 100644 deployments/arbitrum-goerli/usdc.e/configuration.json delete mode 100644 deployments/arbitrum-goerli/usdc.e/deploy.ts delete mode 100644 deployments/arbitrum-goerli/usdc.e/migrations/1679518383_configurate_and_ens.ts delete mode 100644 deployments/arbitrum-goerli/usdc.e/relations.ts delete mode 100644 deployments/arbitrum-goerli/usdc.e/roots.json delete mode 100644 deployments/arbitrum-goerli/usdc/configuration.json delete mode 100644 deployments/arbitrum-goerli/usdc/deploy.ts delete mode 100644 deployments/arbitrum-goerli/usdc/migrations/1689112067_configurate_and_ens.ts delete mode 100644 deployments/arbitrum-goerli/usdc/relations.ts delete mode 100644 deployments/arbitrum-goerli/usdc/roots.json delete mode 100644 deployments/base-goerli/usdc/configuration.json delete mode 100644 deployments/base-goerli/usdc/deploy.ts delete mode 100644 deployments/base-goerli/usdc/migrations/1679592519_configurate_and_ens.ts delete mode 100644 deployments/base-goerli/usdc/relations.ts delete mode 100644 deployments/base-goerli/usdc/roots.json delete mode 100644 deployments/base-goerli/weth/configuration.json delete mode 100644 deployments/base-goerli/weth/deploy.ts delete mode 100644 deployments/base-goerli/weth/migrations/1685486850_configurate_and_ens.ts delete mode 100644 deployments/base-goerli/weth/relations.ts delete mode 100644 deployments/base-goerli/weth/roots.json delete mode 100644 deployments/goerli/usdc/configuration.json delete mode 100644 deployments/goerli/usdc/deploy.ts delete mode 100644 deployments/goerli/usdc/migrations/1663870047_add_link.ts delete mode 100644 deployments/goerli/usdc/migrations/1665028496_absorb_transfer_event_and_auto_collateral.ts delete mode 100644 deployments/goerli/usdc/migrations/1681942579_upgrade_governor_bravo.ts delete mode 100644 deployments/goerli/usdc/relations.ts delete mode 100644 deployments/goerli/usdc/roots.json delete mode 100644 deployments/goerli/weth/configuration.json delete mode 100644 deployments/goerli/weth/deploy.ts delete mode 100644 deployments/goerli/weth/migrations/1672860425_initialize_market.ts delete mode 100644 deployments/goerli/weth/migrations/1675148548_set_up_ens_subdomain_and_text_record.ts delete mode 100644 deployments/goerli/weth/relations.ts delete mode 100644 deployments/goerli/weth/roots.json delete mode 100644 deployments/linea-goerli/usdc/configuration.json delete mode 100644 deployments/linea-goerli/usdc/deploy.ts delete mode 100644 deployments/linea-goerli/usdc/migrations/1686918613_configurate_and_ens.ts delete mode 100644 deployments/linea-goerli/usdc/migrations/1687878801_increase_supply_caps.ts delete mode 100644 deployments/linea-goerli/usdc/relations.ts delete mode 100644 deployments/linea-goerli/usdc/roots.json delete mode 100644 deployments/mumbai/usdc/configuration.json delete mode 100644 deployments/mumbai/usdc/deploy.ts delete mode 100644 deployments/mumbai/usdc/migrations/1676659582_configurate_and_ens.ts delete mode 100644 deployments/mumbai/usdc/relations.ts delete mode 100644 deployments/mumbai/usdc/roots.json delete mode 100644 deployments/scroll-goerli/usdc/configuration.json delete mode 100644 deployments/scroll-goerli/usdc/deploy.ts delete mode 100644 deployments/scroll-goerli/usdc/migrations/1694594095_configurate_and_ens.ts delete mode 100644 deployments/scroll-goerli/usdc/relations.ts delete mode 100644 deployments/scroll-goerli/usdc/roots.json diff --git a/.github/workflows/deploy-market.yaml b/.github/workflows/deploy-market.yaml index b3a563ec4..9fea27076 100644 --- a/.github/workflows/deploy-market.yaml +++ b/.github/workflows/deploy-market.yaml @@ -8,18 +8,12 @@ on: options: - fuji - mainnet - - goerli - sepolia - - mumbai - polygon - arbitrum - - arbitrum-goerli - base - - base-goerli - - linea-goerli - optimism - mantle - - scroll-goerli - scroll deployment: description: Deployment Name (e.g. "usdc") @@ -50,7 +44,7 @@ jobs: with: wallet_connect_project_id: ${{ secrets.WALLET_CONNECT_PROJECT_ID }} requested_network: "${{ inputs.network }}" - ethereum_url: "${{ fromJSON('{\"mantle\":\"https://mantle-mainnet.infura.io/v3/$INFURA_KEY\",\"optimism\":\"https://rpc.ankr.com/optimism/$ANKR_KEY\",\"fuji\":\"https://api.avax-test.network/ext/bc/C/rpc\",\"mainnet\":\"https://mainnet.infura.io/v3/$INFURA_KEY\",\"goerli\":\"https://goerli.infura.io/v3/$INFURA_KEY\",\"sepolia\":\"https://sepolia.infura.io/v3/$INFURA_KEY\",\"mumbai\":\"https://polygon-mumbai.infura.io/v3/$INFURA_KEY\",\"polygon\":\"https://polygon-mainnet.infura.io/v3/$INFURA_KEY\",\"arbitrum-goerli\":\"https://arbitrum-goerli.infura.io/v3/$INFURA_KEY\",\"arbitrum\":\"https://arbitrum-mainnet.infura.io/v3/$INFURA_KEY\",\"base\":\"https://rpc.ankr.com/base/$ANKR_KEY\",\"base-goerli\":\"https://base-goerli.infura.io/v3/$INFURA_KEY\",\"linea-goerli\":\"https://linea-goerli.infura.io/v3/$INFURA_KEY\",\"scroll-goerli\":\"https://alpha-rpc.scroll.io/l2\",\"scroll\":\"https://rpc.scroll.io\"}')[inputs.network] }}" + ethereum_url: "${{ fromJSON('{\"mantle\":\"https://mantle-mainnet.infura.io/v3/$INFURA_KEY\",\"optimism\":\"https://rpc.ankr.com/optimism/$ANKR_KEY\",\"fuji\":\"https://api.avax-test.network/ext/bc/C/rpc\",\"mainnet\":\"https://mainnet.infura.io/v3/$INFURA_KEY\",\"sepolia\":\"https://sepolia.infura.io/v3/$INFURA_KEY\",\"polygon\":\"https://polygon-mainnet.infura.io/v3/$INFURA_KEY\",\"arbitrum\":\"https://arbitrum-mainnet.infura.io/v3/$INFURA_KEY\",\"base\":\"https://rpc.ankr.com/base/$ANKR_KEY\",\"scroll\":\"https://rpc.scroll.io\"}')[inputs.network] }}" port: 8585 if: github.event.inputs.eth_pk == '' diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index cad8c4c66..3de7f204a 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -8,18 +8,12 @@ on: options: - fuji - mainnet - - goerli - sepolia - - mumbai - polygon - arbitrum - - arbitrum-goerli - base - - base-goerli - - linea-goerli - optimism - mantle - - scroll-goerli - scroll deployment: description: Deployment Name (e.g. "usdc") @@ -65,10 +59,10 @@ jobs: - name: Get governance network run: | case ${{ github.event.inputs.network }} in - polygon | arbitrum | base | optimism | mantle) + polygon | arbitrum | base | optimism | mantle | scroll) echo "GOV_NETWORK=mainnet" >> $GITHUB_ENV ;; - mumbai | arbitrum-goerli | base-goerli | linea-goerli | scroll-goerli | scroll) - echo "GOV_NETWORK=goerli" >> $GITHUB_ENV ;; + sepolia) + echo "GOV_NETWORK=sepolia" >> $GITHUB_ENV ;; *) echo "No governance network for selected network" ;; esac @@ -78,7 +72,7 @@ jobs: with: wallet_connect_project_id: ${{ secrets.WALLET_CONNECT_PROJECT_ID }} requested_network: "${{ inputs.network }}" - ethereum_url: "${{ fromJSON('{\"mantle\":\"https://mantle-mainnet.infura.io/v3/$INFURA_KEY\",\"optimism\":\"https://rpc.ankr.com/optimism/$ANKR_KEY\",\"fuji\":\"https://api.avax-test.network/ext/bc/C/rpc\",\"mainnet\":\"https://mainnet.infura.io/v3/$INFURA_KEY\",\"goerli\":\"https://goerli.infura.io/v3/$INFURA_KEY\",\"sepolia\":\"https://sepolia.infura.io/v3/$INFURA_KEY\",\"mumbai\":\"https://polygon-mumbai.infura.io/v3/$INFURA_KEY\",\"polygon\":\"https://polygon-mainnet.infura.io/v3/$INFURA_KEY\",\"arbitrum-goerli\":\"https://arbitrum-goerli.infura.io/v3/$INFURA_KEY\",\"arbitrum\":\"https://arbitrum-mainnet.infura.io/v3/$INFURA_KEY\",\"base\":\"https://rpc.ankr.com/base/$ANKR_KEY\",\"base-goerli\":\"https://base-goerli.infura.io/v3/$INFURA_KEY\",\"linea-goerli\":\"https://linea-goerli.infura.io/v3/$INFURA_KEY\",\"scroll-goerli\":\"https://alpha-rpc.scroll.io/l2\",\"scroll\":\"https://rpc.scroll.io\"}')[inputs.network] }}" + ethereum_url: "${{ fromJSON('{\"mantle\":\"https://mantle-mainnet.infura.io/v3/$INFURA_KEY\",\"optimism\":\"https://rpc.ankr.com/optimism/$ANKR_KEY\",\"fuji\":\"https://api.avax-test.network/ext/bc/C/rpc\",\"mainnet\":\"https://mainnet.infura.io/v3/$INFURA_KEY\",\"sepolia\":\"https://sepolia.infura.io/v3/$INFURA_KEY\",\"polygon\":\"https://polygon-mainnet.infura.io/v3/$INFURA_KEY\",\"arbitrum\":\"https://arbitrum-mainnet.infura.io/v3/$INFURA_KEY\",\"base\":\"https://rpc.ankr.com/base/$ANKR_KEY\",\"scroll\":\"https://rpc.scroll.io\"}')[inputs.network] }}" port: 8585 if: github.event.inputs.eth_pk == '' @@ -87,7 +81,7 @@ jobs: with: wallet_connect_project_id: ${{ secrets.WALLET_CONNECT_PROJECT_ID }} requested_network: "${{ env.GOV_NETWORK }}" - ethereum_url: "${{ fromJSON('{\"mantle\":\"https://mantle-mainnet.infura.io/v3/$INFURA_KEY\",\"optimism\":\"https://rpc.ankr.com/optimism/$ANKR_KEY\",\"fuji\":\"https://api.avax-test.network/ext/bc/C/rpc\",\"mainnet\":\"https://mainnet.infura.io/v3/$INFURA_KEY\",\"goerli\":\"https://goerli.infura.io/v3/$INFURA_KEY\",\"sepolia\":\"https://sepolia.infura.io/v3/$INFURA_KEY\",\"mumbai\":\"https://polygon-mumbai.infura.io/v3/$INFURA_KEY\",\"polygon\":\"https://polygon-mainnet.infura.io/v3/$INFURA_KEY\",\"arbitrum-goerli\":\"https://arbitrum-goerli.infura.io/v3/$INFURA_KEY\",\"arbitrum\":\"https://arbitrum-mainnet.infura.io/v3/$INFURA_KEY\"}')[env.GOV_NETWORK] }}" + ethereum_url: "${{ fromJSON('{\"mantle\":\"https://mantle-mainnet.infura.io/v3/$INFURA_KEY\",\"optimism\":\"https://rpc.ankr.com/optimism/$ANKR_KEY\",\"fuji\":\"https://api.avax-test.network/ext/bc/C/rpc\",\"mainnet\":\"https://mainnet.infura.io/v3/$INFURA_KEY\",\"sepolia\":\"https://sepolia.infura.io/v3/$INFURA_KEY\",\"polygon\":\"https://polygon-mainnet.infura.io/v3/$INFURA_KEY\",\"arbitrum\":\"https://arbitrum-mainnet.infura.io/v3/$INFURA_KEY\"}')[env.GOV_NETWORK] }}" port: 8685 if: github.event.inputs.eth_pk == '' && env.GOV_NETWORK != '' && github.event.inputs.impersonateAccount == '' diff --git a/.github/workflows/prepare-migration.yaml b/.github/workflows/prepare-migration.yaml index 88a156cf6..2ba4f7213 100644 --- a/.github/workflows/prepare-migration.yaml +++ b/.github/workflows/prepare-migration.yaml @@ -8,14 +8,10 @@ on: options: - fuji - mainnet - - goerli - sepolia - - mumbai - polygon - arbitrum - - arbitrum-goerli - base - - base-goerli - optimism - mantle deployment: @@ -50,7 +46,7 @@ jobs: with: wallet_connect_project_id: ${{ secrets.WALLET_CONNECT_PROJECT_ID }} requested_network: "${{ inputs.network }}" - ethereum_url: "${{ fromJSON('{\"mantle\":\"https://mantle-mainnet.infura.io/v3/$INFURA_KEY\",\"optimism\":\"https://rpc.ankr.com/optimism/$ANKR_KEY\",\"fuji\":\"https://api.avax-test.network/ext/bc/C/rpc\",\"mainnet\":\"https://mainnet.infura.io/v3/$INFURA_KEY\",\"goerli\":\"https://goerli.infura.io/v3/$INFURA_KEY\",\"sepolia\":\"https://sepolia.infura.io/v3/$INFURA_KEY\",\"mumbai\":\"https://polygon-mumbai.infura.io/v3/$INFURA_KEY\",\"polygon\":\"https://polygon-mainnet.infura.io/v3/$INFURA_KEY\",\"arbitrum-goerli\":\"https://arbitrum-goerli.infura.io/v3/$INFURA_KEY\",\"arbitrum\":\"https://arbitrum-mainnet.infura.io/v3/$INFURA_KEY\",\"base\":\"https://rpc.ankr.com/base/$ANKR_KEY\",\"base-goerli\":\"https://base-goerli.infura.io/v3/$INFURA_KEY\",\"linea-goerli\":\"https://linea-goerli.infura.io/v3/$INFURA_KEY\",\"scroll-goerli\":\"https://alpha-rpc.scroll.io/l2\",\"scroll\":\"https://rpc.scroll.io\"}')[inputs.network] }}" + ethereum_url: "${{ fromJSON('{\"mantle\":\"https://mantle-mainnet.infura.io/v3/$INFURA_KEY\",\"optimism\":\"https://rpc.ankr.com/optimism/$ANKR_KEY\",\"fuji\":\"https://api.avax-test.network/ext/bc/C/rpc\",\"mainnet\":\"https://mainnet.infura.io/v3/$INFURA_KEY\",\"sepolia\":\"https://sepolia.infura.io/v3/$INFURA_KEY\",\"polygon\":\"https://polygon-mainnet.infura.io/v3/$INFURA_KEY\",\"arbitrum\":\"https://arbitrum-mainnet.infura.io/v3/$INFURA_KEY\",\"base\":\"https://rpc.ankr.com/base/$ANKR_KEY\",\"scroll\":\"https://rpc.scroll.io\"}')[inputs.network] }}" port: 8585 if: github.event.inputs.eth_pk == '' diff --git a/.github/workflows/run-scenarios.yaml b/.github/workflows/run-scenarios.yaml index 4446b0b42..9590bd18c 100644 --- a/.github/workflows/run-scenarios.yaml +++ b/.github/workflows/run-scenarios.yaml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - bases: [ development, mainnet, mainnet-weth, mainnet-usdt, mainnet-wsteth, mainnet-usds, goerli, goerli-weth, sepolia-usdc, sepolia-weth, fuji, mumbai, polygon, polygon-usdt, arbitrum-usdc.e, arbitrum-usdc, arbitrum-weth, arbitrum-usdt, arbitrum-goerli-usdc, arbitrum-goerli-usdc.e, base-usdbc, base-weth, base-usdc, base-aero, base-goerli, base-goerli-weth, linea-goerli, optimism-usdc, optimism-usdt, optimism-weth, mantle-usde, scroll-goerli, scroll-usdc] + bases: [ development, mainnet, mainnet-weth, mainnet-usdt, mainnet-wsteth, mainnet-usds, sepolia-usdc, sepolia-weth, fuji, polygon, polygon-usdt, arbitrum-usdc.e, arbitrum-usdc, arbitrum-weth, arbitrum-usdt, base-usdbc, base-weth, base-usdc, base-aero, optimism-usdc, optimism-usdt, optimism-weth, mantle-usde, scroll-usdc] name: Run scenarios env: ETHERSCAN_KEY: ${{ secrets.ETHERSCAN_KEY }} diff --git a/.github/workflows/run-slither.yaml b/.github/workflows/run-slither.yaml index 2ca5a871d..bab788973 100644 --- a/.github/workflows/run-slither.yaml +++ b/.github/workflows/run-slither.yaml @@ -28,4 +28,4 @@ jobs: run: solc-select install 0.8.15;solc-select use 0.8.15 - name: Function clash analysis - run: yarn slither:fn-clashes &> tmp_res; cat tmp_res | grep 'Function id collision found' && exit 1 || exit 0 + run: yarn slither:fn-clashes &> tmp_res; cat tmp_res | { grep 'Function id collision found' || false; } && exit 1 || exit 0 diff --git a/MIGRATIONS.md b/MIGRATIONS.md index 702c8e297..b4dc00289 100644 --- a/MIGRATIONS.md +++ b/MIGRATIONS.md @@ -7,10 +7,10 @@ Migrations are simple scripts which deploy or modify contracts. The goal of migr To create a new migration, run: ```sh -yarn hardhat gen:migration --network goerli --deployment usdc my_migration +yarn hardhat gen:migration --network sepolia --deployment usdc my_migration ``` -This will create a new file, such as `deployments/goerli/usdc/migrations/164443237_my_migration.ts` with a base migration script. There are currently two steps to a migration script, but this is likely to change soon: +This will create a new file, such as `deployments/sepolia/usdc/migrations/164443237_my_migration.ts` with a base migration script. There are currently two steps to a migration script, but this is likely to change soon: 1. Prepare: steps used to create artifacts, such as new on-chain contracts. The output from this step is stored (e.g. "NewCometImplementation: 0x...") 2. Enact: steps used to make these artifacts current, such as upgrading the proxy to the address from the previous step. @@ -20,31 +20,31 @@ This will create a new file, such as `deployments/goerli/usdc/migrations/1644432 You can run the preparation for a migration locally via: ```sh -yarn hardhat migrate --network goerli --deployment usdc --prepare 164443237_my_migration +yarn hardhat migrate --network sepolia --deployment usdc --prepare 164443237_my_migration ``` or the enactment via: ```sh -yarn hardhat migrate --network goerli --deployment usdc --enact 164443237_my_migration +yarn hardhat migrate --network sepolia --deployment usdc --enact 164443237_my_migration ``` or both preparation and enactment via: ```sh -yarn hardhat migrate --network goerli --deployment usdc --prepare --enact 164443237_my_migration +yarn hardhat migrate --network sepolia --deployment usdc --prepare --enact 164443237_my_migration ``` Also, you can simulate either of the previous steps to see what effect they would have without actually modifying the on-chain state: ```sh -yarn hardhat migrate --network goerli --deployment usdc --prepare --simulate 164443237_my_migration +yarn hardhat migrate --network sepolia --deployment usdc --prepare --simulate 164443237_my_migration ``` When simulating a migration, you can also impersonate an address to run the migration as. This can be helpful when trying to test a migration that makes a proposal, which requires an address with enough COMP: ```sh -yarn hardhat migrate --network goerli --deployment usdc --prepare --simulate --impersonate ADDRESS_TO_IMPERSONATE 164443237_my_migration +yarn hardhat migrate --network sepolia --deployment usdc --prepare --simulate --impersonate ADDRESS_TO_IMPERSONATE 164443237_my_migration ``` ## Running a Migration in GitHub @@ -53,7 +53,7 @@ The preferred way to run a migration is in GitHub, via manual workflow dispatch. ## Migration Artifacts -After preparation, a migration stores some artifacts under `deployments/goerli/usdc/artifacts/164443237_my_migration.json`. These will be loaded and can be referenced in the enact step of that migration. +After preparation, a migration stores some artifacts under `deployments/sepolia/usdc/artifacts/164443237_my_migration.json`. These will be loaded and can be referenced in the enact step of that migration. ## Testing Migrations diff --git a/README.md b/README.md index 64f799814..cb8b93978 100644 --- a/README.md +++ b/README.md @@ -258,7 +258,7 @@ This can also be used together with `--overwrite`, to produce the verification a #### Other considerations Make sure that the deploying address has a sufficient amount of the chain's -native asset (i.e. 2 ETH for Goerli, 2 AVAX for Fuji) +native asset (i.e. 2 ETH for Sepolia, 2 AVAX for Fuji) ### Clone Multisig @@ -277,7 +277,7 @@ Uniswap for a profit. To run the bot, you'll need the address of a deployed version of the Liquidator contract (or you can deploy a new instance of it yourself): -`LIQUIDATOR_ADDRESS="0xABC..." DEPLOYMENT="usdc" yarn liquidation-bot --network goerli` +`LIQUIDATOR_ADDRESS="0xABC..." DEPLOYMENT="usdc" yarn liquidation-bot --network sepolia` Initiating transactions this way via the public mempool will [almost certainly get frontrun](https://youtu.be/UZ-NNd6yjFM), but you might be diff --git a/SCENARIO.md b/SCENARIO.md index 8bbc439f3..da681cbfa 100644 --- a/SCENARIO.md +++ b/SCENARIO.md @@ -8,7 +8,7 @@ Scenarios are high-level property and ad-hoc tests for the Comet protocol. To ru You can run scenarios against a given base as: -`npx hardhat scenario --bases development,goerli,fuji` +`npx hardhat scenario --bases development,sepolia,fuji` You can run spider persistently first if you wish: diff --git a/deployments/arbitrum-goerli/usdc.e/configuration.json b/deployments/arbitrum-goerli/usdc.e/configuration.json deleted file mode 100644 index 1d759f556..000000000 --- a/deployments/arbitrum-goerli/usdc.e/configuration.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "Compound USDC", - "symbol": "cUSDCv3", - "baseToken": "USDC.e", - "baseTokenAddress": "0x8FB1E3fC51F3b789dED7557E680551d93Ea9d892", - "baseTokenPriceFeed": "0x1692Bdd32F31b831caAc1b0c9fAF68613682813b", - "borrowMin": "100e6", - "pauseGuardian": "0x6C2fD6738e43ce0cc4A6f23a37e3a733516794A0", - "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": "0e15", - "baseBorrowSpeed": "0e15", - "baseMinForRewards": "10000e6" - }, - "assets": { - "LINK": { - "address": "0xbb7303602be1b9149b097aafb094ffce1860e532", - "priceFeed": "0xd28Ba6CA3bB72bF371b80a2a0a33cBcf9073C954", - "decimals": "18", - "borrowCF": 0.775, - "liquidateCF": 0.825, - "liquidationFactor": 0.95, - "supplyCap": "5000000e18" - }, - "WETH": { - "address": "0xe39ab88f8a4777030a534146a9ca3b52bd5d43a3", - "priceFeed": "0x62CAe0FA2da220f43a51F86Db2EDb36DcA9A5A08", - "decimals": "18", - "borrowCF": 0.775, - "liquidateCF": 0.825, - "liquidationFactor": 0.95, - "supplyCap": "5000e18" - }, - "WBTC": { - "address": "0x22d5e2dE578677791f6c90e0110Ec629be9d5Fb5", - "priceFeed": "0x6550bc2301936011c1334555e62A87705A81C12C", - "decimals": "8", - "borrowCF": 0.7, - "liquidateCF": 0.75, - "liquidationFactor": 0.93, - "supplyCap": "300e8" - } - } -} diff --git a/deployments/arbitrum-goerli/usdc.e/deploy.ts b/deployments/arbitrum-goerli/usdc.e/deploy.ts deleted file mode 100644 index 4d6e0cf67..000000000 --- a/deployments/arbitrum-goerli/usdc.e/deploy.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; -import { DeploySpec, deployComet } from '../../../src/deploy'; - -const SECONDS_PER_DAY = 24 * 60 * 60; - -const GOERLI_TIMELOCK = '0x8Fa336EB4bF58Cfc508dEA1B0aeC7336f55B1399'; - -export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { - const trace = deploymentManager.tracer() - const ethers = deploymentManager.hre.ethers; - - // pull in existing assets - const USDC = await deploymentManager.existing('USDC', '0x8FB1E3fC51F3b789dED7557E680551d93Ea9d892', 'arbitrum-goerli'); - const LINK = await deploymentManager.existing('LINK', '0xbb7303602be1b9149b097aafb094ffce1860e532', 'arbitrum-goerli'); - const WETH = await deploymentManager.existing('WETH', '0xe39ab88f8a4777030a534146a9ca3b52bd5d43a3', 'arbitrum-goerli'); - const WBTC = await deploymentManager.existing('WBTC', '0x22d5e2dE578677791f6c90e0110Ec629be9d5Fb5', 'arbitrum-goerli'); - - // Deploy ArbitrumBridgeReceiver - const bridgeReceiver = await deploymentManager.deploy( - 'bridgeReceiver', - 'bridges/arbitrum/ArbitrumBridgeReceiver.sol', - [] - ); - - // Deploy Local Timelock - const localTimelock = await deploymentManager.deploy( - 'timelock', - 'vendor/Timelock.sol', - [ - bridgeReceiver.address, // admin - 10 * 60, // delay - 14 * SECONDS_PER_DAY, // grace period - 10 * 60, // minimum delay - 30 * SECONDS_PER_DAY // maximum delay - ] - ); - - // Initialize ArbitrumBridgeReceiver - await deploymentManager.idempotent( - async () => !(await bridgeReceiver.initialized()), - async () => { - trace(`Initializing BridgeReceiver`); - await bridgeReceiver.initialize( - GOERLI_TIMELOCK, // govTimelock - localTimelock.address // localTimelock - ); - trace(`BridgeReceiver initialized`); - } - ); - - // Deploy Comet - const deployed = await deployComet(deploymentManager, deploySpec); - const { comet } = deployed; - - // Deploy Bulker - const bulker = await deploymentManager.deploy( - 'bulker', - 'bulkers/BaseBulker.sol', - [ - await comet.governor(), // admin - WETH.address // weth - ] - ); - - return { - ...deployed, - bridgeReceiver, - bulker - }; -} \ No newline at end of file diff --git a/deployments/arbitrum-goerli/usdc.e/migrations/1679518383_configurate_and_ens.ts b/deployments/arbitrum-goerli/usdc.e/migrations/1679518383_configurate_and_ens.ts deleted file mode 100644 index 7a05a2023..000000000 --- a/deployments/arbitrum-goerli/usdc.e/migrations/1679518383_configurate_and_ens.ts +++ /dev/null @@ -1,296 +0,0 @@ -import { Contract } from 'ethers'; -import { expect } from 'chai'; -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { diffState, getCometConfig } from '../../../../plugins/deployment_manager/DiffState'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; -import { calldata, exp, getConfigurationStruct, proposal } from '../../../../src/deploy'; -import { applyL1ToL2Alias, estimateL2Transaction, estimateTokenBridge } from '../../../../scenario/utils/arbitrumUtils'; - -const ENSName = 'compound-community-licenses.eth'; -const ENSResolverAddress = '0x19c2d5D0f035563344dBB7bE5fD09c8dad62b001'; -const ENSSubdomainLabel = 'v3-additional-grants'; -const ENSSubdomain = `${ENSSubdomainLabel}.${ENSName}`; -const ENSTextRecordKey = 'v3-official-markets'; - -const arbitrumCOMPAddress = '0xf03370d2aCf26Dde26389B66498B7c293038F5aF'; - -export default migration('1679518383_configurate_and_ens', { - prepare: async (_deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - const { utils } = ethers; - - const { - bridgeReceiver, - timelock: l2Timelock, - comet, - cometAdmin, - configurator, - rewards, - } = await deploymentManager.getContracts(); - - const { - arbitrumInbox, - arbitrumL1GatewayRouter, - timelock, - governor, - USDC, - COMP, - } = await govDeploymentManager.getContracts(); - - const USDCAmountToBridge = exp(10, 6); - const COMPAmountToBridge = exp(2_500, 18); - const usdcGatewayAddress = await arbitrumL1GatewayRouter.getGateway(USDC.address); - const compGatewayAddress = await arbitrumL1GatewayRouter.getGateway(COMP.address); - const refundAddress = l2Timelock.address; - - const compGasParams = await estimateTokenBridge( - { - token: COMP.address, - from: timelock.address, - to: rewards.address, - amount: COMPAmountToBridge - }, - govDeploymentManager, - deploymentManager - ); - - const usdcGasParams = await estimateTokenBridge( - { - token: USDC.address, - from: timelock.address, - to: comet.address, - amount: USDCAmountToBridge - }, - govDeploymentManager, - deploymentManager - ); - - const configuration = await getConfigurationStruct(deploymentManager); - - const setConfigurationCalldata = await calldata( - configurator.populateTransaction.setConfiguration(comet.address, configuration) - ); - const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [configurator.address, comet.address] - ); - const setRewardConfigCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [comet.address, arbitrumCOMPAddress] - ); - const l2ProposalData = utils.defaultAbiCoder.encode( - ['address[]', 'uint256[]', 'string[]', 'bytes[]'], - [ - [configurator.address, cometAdmin.address, rewards.address], - [0, 0, 0], - [ - 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', - 'deployAndUpgradeTo(address,address)', - 'setRewardConfig(address,address)' - ], - [setConfigurationCalldata, deployAndUpgradeToCalldata, setRewardConfigCalldata] - ] - ); - - const createRetryableTicketGasParams = await estimateL2Transaction( - { - from: applyL1ToL2Alias(timelock.address), - to: bridgeReceiver.address, - data: l2ProposalData - }, - deploymentManager - ); - - const ENSResolver = await govDeploymentManager.existing('ENSResolver', ENSResolverAddress, 'goerli'); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const officialMarketsJSON = await ENSResolver.text(subdomainHash, ENSTextRecordKey); - const officialMarkets = JSON.parse(officialMarketsJSON); - // XXX - const updatedMarkets = { - ...officialMarkets, - 421613: [ - { - baseSymbol: 'USDC', - cometAddress: comet.address, - } - ], - }; - - const mainnetActions = [ - // 1. Set Comet configuration and deployAndUpgradeTo new Comet on Arbitrum. - { - contract: arbitrumInbox, - signature: 'createRetryableTicket(address,uint256,uint256,address,address,uint256,uint256,bytes)', - args: [ - bridgeReceiver.address, // address to, - 0, // uint256 l2CallValue, - createRetryableTicketGasParams.maxSubmissionCost, // uint256 maxSubmissionCost, - refundAddress, // address excessFeeRefundAddress, - refundAddress, // address callValueRefundAddress, - createRetryableTicketGasParams.gasLimit, // uint256 gasLimit, - createRetryableTicketGasParams.maxFeePerGas, // uint256 maxFeePerGas, - l2ProposalData, // bytes calldata data - ], - value: createRetryableTicketGasParams.deposit - }, - // 2. Approve the USDC gateway to take Timelock's USDC for bridging - { - contract: USDC, - signature: 'approve(address,uint256)', - args: [usdcGatewayAddress, USDCAmountToBridge] - }, - // 3. Bridge USDC from mainnet to Arbitrum Comet - { - contract: arbitrumL1GatewayRouter, - signature: 'outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)', - args: [ - USDC.address, // address _token, - refundAddress, // address _refundTo - comet.address, // address _to, - USDCAmountToBridge, // uint256 _amount, - usdcGasParams.gasLimit, // uint256 _maxGas, - usdcGasParams.maxFeePerGas, // uint256 _gasPriceBid, - utils.defaultAbiCoder.encode( - ['uint256', 'bytes'], - [usdcGasParams.maxSubmissionCost, '0x'] - ) // bytes calldata _data - ], - value: usdcGasParams.deposit - }, - // 4. Approve the COMP gateway to take Timelock's COMP for bridging - { - contract: COMP, - signature: 'approve(address,uint256)', - args: [compGatewayAddress, COMPAmountToBridge] - }, - // 5. Bridge COMP from mainnet to Arbitrum rewards - { - contract: arbitrumL1GatewayRouter, - signature: 'outboundTransferCustomRefund(address,address,address,uint256,uint256,uint256,bytes)', - args: [ - COMP.address, // address _token, - refundAddress, // address _refundTo, - rewards.address, // address _to, - COMPAmountToBridge, // uint256 _amount, - compGasParams.gasLimit, // uint256 _maxGas, - compGasParams.maxFeePerGas, // uint256 _gasPriceBid, - utils.defaultAbiCoder.encode( - ['uint256', 'bytes'], - [compGasParams.maxSubmissionCost, '0x'] - ) // bytes calldata _data - ], - value: compGasParams.deposit - }, - // 6. Update the list of official markets - { - target: ENSResolverAddress, - signature: 'setText(bytes32,string,string)', - calldata: ethers.utils.defaultAbiCoder.encode( - ['bytes32', 'string', 'string'], - [subdomainHash, ENSTextRecordKey, JSON.stringify(updatedMarkets)] - ) - }, - ]; - - const description = 'XXX'; // XXX add description - 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, govDeploymentManager: DeploymentManager, preMigrationBlockNumber: number) { - const ethers = deploymentManager.hre.ethers; - await deploymentManager.spider(); // await deploymentManager.spider(); // Pull in Arbitrum COMP now that reward config has been set - - const { - comet, - rewards, - WBTC, - WETH, - LINK - } = await deploymentManager.getContracts(); - - // 1. - const stateChanges = await diffState(comet, getCometConfig, preMigrationBlockNumber); - expect(stateChanges).to.deep.equal({ - LINK: { - supplyCap: exp(5_000_000, 18) - }, - WBTC: { - supplyCap: exp(300, 8) - }, - WETH: { - supplyCap: exp(5_000, 18) - } - }); - - const config = await rewards.rewardConfig(comet.address); - expect(config.token).to.be.equal(arbitrumCOMPAddress); - expect(config.rescaleFactor).to.be.equal(exp(1, 12)); - expect(config.shouldUpscale).to.be.equal(true); - - // 2. & 3. - expect(await comet.getReserves()).to.be.equal(exp(10, 6)); - - // 4. & 5. - const arbitrumCOMP = new Contract( - arbitrumCOMPAddress, - ['function balanceOf(address account) external view returns (uint256)'], - deploymentManager.hre.ethers.provider - ); - expect(await arbitrumCOMP.balanceOf(rewards.address)).to.be.equal(exp(2_500, 18)); - - // 6. - const ENSResolver = await govDeploymentManager.existing('ENSResolver', ENSResolverAddress); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const officialMarketsJSON = await ENSResolver.text(subdomainHash, ENSTextRecordKey); - const officialMarkets = JSON.parse(officialMarketsJSON); - expect(officialMarkets).to.deep.equal({ - 5: [ - { - baseSymbol: 'USDC', - cometAddress: '0x3EE77595A8459e93C2888b13aDB354017B198188', - }, - { - baseSymbol: 'WETH', - cometAddress: '0x9A539EEc489AAA03D588212a164d0abdB5F08F5F', - }, - ], - - 420: [ - { - baseSymbol: 'USDC', - cometAddress: '0xb8F2f9C84ceD7bBCcc1Db6FB7bb1F19A9a4adfF4' - } - ], - - 421613: [ - { - baseSymbol: 'USDC', - cometAddress: comet.address - }, - ], - - 80001: [ - { - baseSymbol: 'USDC', - cometAddress: '0xF09F0369aB0a875254fB565E52226c88f10Bc839' - }, - ] - }); - } -}); diff --git a/deployments/arbitrum-goerli/usdc.e/relations.ts b/deployments/arbitrum-goerli/usdc.e/relations.ts deleted file mode 100644 index f266af2a2..000000000 --- a/deployments/arbitrum-goerli/usdc.e/relations.ts +++ /dev/null @@ -1,29 +0,0 @@ -import baseRelationConfig from '../../relations'; - -export default { - ...baseRelationConfig, - governor: { - artifact: 'contracts/bridges/arbitrum/ArbitrumBridgeReceiver.sol:ArbitrumBridgeReceiver' - }, - ClonableBeaconProxy: { - artifact: 'contracts/ERC20.sol:ERC20' - }, - // USDC - '0x8FB1E3fC51F3b789dED7557E680551d93Ea9d892': { - artifact: 'contracts/ERC20.sol:ERC20', - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - // WETH - '0xe39ab88f8a4777030a534146a9ca3b52bd5d43a3': { - artifact: 'contracts/ERC20.sol:ERC20', - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - } -}; diff --git a/deployments/arbitrum-goerli/usdc.e/roots.json b/deployments/arbitrum-goerli/usdc.e/roots.json deleted file mode 100644 index 1ef25d7d2..000000000 --- a/deployments/arbitrum-goerli/usdc.e/roots.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "comet": "0x1d573274E19174260c5aCE3f2251598959d24456", - "configurator": "0x1Ead344570F0f0a0cD86d95d8adDC7855C8723Fb", - "rewards": "0x8DA65F8E3Aa22A498211fc4204C498ae9050DAE4", - "bridgeReceiver": "0xAC9fC1a9532BC92a9f33eD4c6Ce4A7a54930F376", - "bulker": "0x987350Af5a17b6DdafeB95E6e329c178f44841d7" -} \ No newline at end of file diff --git a/deployments/arbitrum-goerli/usdc/configuration.json b/deployments/arbitrum-goerli/usdc/configuration.json deleted file mode 100644 index fda04e2ac..000000000 --- a/deployments/arbitrum-goerli/usdc/configuration.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "Compound USDC", - "symbol": "cUSDCv3", - "baseToken": "USDC", - "baseTokenAddress": "0xfd064A18f3BF249cf1f87FC203E90D8f650f2d63", - "baseTokenPriceFeed": "0x1692Bdd32F31b831caAc1b0c9fAF68613682813b", - "borrowMin": "1e6", - "pauseGuardian": "0x6C2fD6738e43ce0cc4A6f23a37e3a733516794A0", - "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.000402083333333e15", - "baseBorrowSpeed": "0.000402083333333e15", - "baseMinForRewards": "10000e6" - }, - "assets": { - "LINK": { - "address": "0xbb7303602be1b9149b097aafb094ffce1860e532", - "priceFeed": "0xd28Ba6CA3bB72bF371b80a2a0a33cBcf9073C954", - "decimals": "18", - "borrowCF": 0.775, - "liquidateCF": 0.825, - "liquidationFactor": 0.95, - "supplyCap": "5000000e18" - }, - "WETH": { - "address": "0xe39ab88f8a4777030a534146a9ca3b52bd5d43a3", - "priceFeed": "0x62CAe0FA2da220f43a51F86Db2EDb36DcA9A5A08", - "decimals": "18", - "borrowCF": 0.775, - "liquidateCF": 0.825, - "liquidationFactor": 0.95, - "supplyCap": "5000e18" - }, - "WBTC": { - "address": "0x22d5e2dE578677791f6c90e0110Ec629be9d5Fb5", - "priceFeed": "0x6550bc2301936011c1334555e62A87705A81C12C", - "decimals": "8", - "borrowCF": 0.7, - "liquidateCF": 0.75, - "liquidationFactor": 0.93, - "supplyCap": "300e8" - } - } -} diff --git a/deployments/arbitrum-goerli/usdc/deploy.ts b/deployments/arbitrum-goerli/usdc/deploy.ts deleted file mode 100644 index ce94cab24..000000000 --- a/deployments/arbitrum-goerli/usdc/deploy.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; -import { DeploySpec, deployComet } from '../../../src/deploy'; - -const SECONDS_PER_DAY = 24 * 60 * 60; - -const GOERLI_TIMELOCK = '0x8Fa336EB4bF58Cfc508dEA1B0aeC7336f55B1399'; - -export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { - const trace = deploymentManager.tracer() - const ethers = deploymentManager.hre.ethers; - - // pull in existing assets - const USDC = await deploymentManager.existing('USDC', '0xfd064A18f3BF249cf1f87FC203E90D8f650f2d63', 'arbitrum-goerli'); - const LINK = await deploymentManager.existing('LINK', '0xbb7303602be1b9149b097aafb094ffce1860e532', 'arbitrum-goerli'); - const WETH = await deploymentManager.existing('WETH', '0xe39ab88f8a4777030a534146a9ca3b52bd5d43a3', 'arbitrum-goerli'); - const WBTC = await deploymentManager.existing('WBTC', '0x22d5e2dE578677791f6c90e0110Ec629be9d5Fb5', 'arbitrum-goerli'); - - // Import shared contracts from cUSDCv3 - const cometAdmin = await deploymentManager.fromDep('cometAdmin', 'arbitrum-goerli', 'usdc.e'); - const cometFactory = await deploymentManager.fromDep('cometFactory', 'arbitrum-goerli', 'usdc.e'); - const $configuratorImpl = await deploymentManager.fromDep('configurator:implementation', 'arbitrum-goerli', 'usdc.e'); - const configurator = await deploymentManager.fromDep('configurator', 'arbitrum-goerli', 'usdc.e'); - const rewards = await deploymentManager.fromDep('rewards', 'arbitrum-goerli', 'usdc.e'); - const bulker = await deploymentManager.fromDep('bulker', 'arbitrum-goerli', 'usdc.e'); - const localTimelock = await deploymentManager.fromDep('timelock', 'arbitrum-goerli', 'usdc.e'); - const bridgeReceiver = await deploymentManager.fromDep('bridgeReceiver', 'arbitrum-goerli', 'usdc.e'); - - // Deploy Comet - const deployed = await deployComet(deploymentManager, deploySpec); - - return { - ...deployed, - bridgeReceiver, - bulker, - rewards, - }; -} \ No newline at end of file diff --git a/deployments/arbitrum-goerli/usdc/migrations/1689112067_configurate_and_ens.ts b/deployments/arbitrum-goerli/usdc/migrations/1689112067_configurate_and_ens.ts deleted file mode 100644 index 4ba4b9935..000000000 --- a/deployments/arbitrum-goerli/usdc/migrations/1689112067_configurate_and_ens.ts +++ /dev/null @@ -1,283 +0,0 @@ -import { Contract } from 'ethers'; -import { expect } from 'chai'; -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { diffState, getCometConfig } from '../../../../plugins/deployment_manager/DiffState'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; -import { calldata, exp, getConfigurationStruct, proposal } from '../../../../src/deploy'; -import { applyL1ToL2Alias, estimateL2Transaction, estimateTokenBridge } from '../../../../scenario/utils/arbitrumUtils'; - -const ENSName = 'compound-community-licenses.eth'; -const ENSResolverAddress = '0x19c2d5D0f035563344dBB7bE5fD09c8dad62b001'; -const ENSSubdomainLabel = 'v3-additional-grants'; -const ENSSubdomain = `${ENSSubdomainLabel}.${ENSName}`; -const ENSTextRecordKey = 'v3-official-markets'; - -const arbitrumCOMPAddress = '0xf03370d2aCf26Dde26389B66498B7c293038F5aF'; - -export default migration('1689112067_configurate_and_ens', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - const { utils } = ethers; - - const cometFactory = await deploymentManager.fromDep('cometFactory', 'arbitrum-goerli', 'usdc.e'); - const usdceComet = await deploymentManager.fromDep('usdceComet', 'arbitrum-goerli', 'usdc.e', 'comet'); - const { - bridgeReceiver, - timelock: l2Timelock, - comet, - cometAdmin, - configurator, - rewards, - } = await deploymentManager.getContracts(); - - const { - arbitrumInbox, - arbitrumL1GatewayRouter, - timelock, - governor, - USDC, - COMP, - CCTPTokenMessenger, - } = await govDeploymentManager.getContracts(); - - // CCTP destination domain for Arbitrum - const ArbitrumDestinationDomain = 3; - const USDCAmountToBridge = exp(10, 6); - const refundAddress = l2Timelock.address; - const configuration = await getConfigurationStruct(deploymentManager); - const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactory.address) - ); - - const setConfigurationCalldata = await calldata( - configurator.populateTransaction.setConfiguration(comet.address, configuration) - ); - - const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [configurator.address, comet.address] - ); - - const setRewardConfigCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [comet.address, arbitrumCOMPAddress] - ); - - const turnOffUSDCeCometSupplySpeedCalldata = utils.defaultAbiCoder.encode( - ['address', 'uint64'], - [usdceComet.address, 0] - ); - - const turnOffUSDCeCometBorrowSpeedCalldata = utils.defaultAbiCoder.encode( - ['address', 'uint64'], - [usdceComet.address, 0] - ); - - const deployAndUpgradeToUSDCeCometCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [configurator.address, usdceComet.address] - ); - - const l2ProposalData = utils.defaultAbiCoder.encode( - ['address[]', 'uint256[]', 'string[]', 'bytes[]'], - [ - [configurator.address, configurator.address, cometAdmin.address, rewards.address, configurator.address, configurator.address, cometAdmin.address], - [0, 0, 0, 0, 0, 0, 0], - [ - 'setFactory(address,address)', - 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', - 'deployAndUpgradeTo(address,address)', - 'setRewardConfig(address,address)', - 'setBaseTrackingSupplySpeed(address,uint64)', - 'setBaseTrackingBorrowSpeed(address,uint64)', - 'deployAndUpgradeTo(address,address)', - ], - [setFactoryCalldata, setConfigurationCalldata, deployAndUpgradeToCalldata, setRewardConfigCalldata, turnOffUSDCeCometSupplySpeedCalldata, turnOffUSDCeCometBorrowSpeedCalldata, deployAndUpgradeToUSDCeCometCalldata] - ] - ); - - const createRetryableTicketGasParams = await estimateL2Transaction( - { - from: applyL1ToL2Alias(timelock.address), - to: bridgeReceiver.address, - data: l2ProposalData - }, - deploymentManager - ); - - const ENSResolver = await govDeploymentManager.existing('ENSResolver', ENSResolverAddress, 'goerli'); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const arbitrumChainId = (await deploymentManager.hre.ethers.provider.getNetwork()).chainId.toString(); - const newMarketObject = { baseSymbol: 'USDC', cometAddress: comet.address }; - const officialMarketsJSON = JSON.parse(await ENSResolver.text(subdomainHash, ENSTextRecordKey)); - - // Rename old USDC market into USDC.e - officialMarketsJSON[arbitrumChainId][0].baseSymbol = 'USDC.e'; - - if (officialMarketsJSON[arbitrumChainId]) { - officialMarketsJSON[arbitrumChainId].push(newMarketObject); - } else { - officialMarketsJSON[arbitrumChainId] = [newMarketObject]; - } - - const mainnetActions = [ - // 1. Set Comet configuration and deployAndUpgradeTo new Comet on Arbitrum. - { - contract: arbitrumInbox, - signature: 'createRetryableTicket(address,uint256,uint256,address,address,uint256,uint256,bytes)', - args: [ - bridgeReceiver.address, // address to, - 0, // uint256 l2CallValue, - createRetryableTicketGasParams.maxSubmissionCost, // uint256 maxSubmissionCost, - refundAddress, // address excessFeeRefundAddress, - refundAddress, // address callValueRefundAddress, - createRetryableTicketGasParams.gasLimit, // uint256 gasLimit, - createRetryableTicketGasParams.maxFeePerGas, // uint256 maxFeePerGas, - l2ProposalData, // bytes calldata data - ], - value: createRetryableTicketGasParams.deposit - }, - // 2. Approve USDC to CCTP - { - contract: USDC, - signature: 'approve(address,uint256)', - args: [CCTPTokenMessenger.address, USDCAmountToBridge] - }, - // 3. Burn USDC to Arbitrum via CCTP - { - contract: CCTPTokenMessenger, - signature: 'depositForBurn(uint256,uint32,bytes32,address)', - args: [USDCAmountToBridge, ArbitrumDestinationDomain, utils.hexZeroPad(comet.address, 32), USDC.address], - }, - // 4. Update the list of official markets - { - target: ENSResolverAddress, - signature: 'setText(bytes32,string,string)', - calldata: ethers.utils.defaultAbiCoder.encode( - ['bytes32', 'string', 'string'], - [subdomainHash, ENSTextRecordKey, JSON.stringify(officialMarketsJSON)] - ) - } - ]; - - // TODO: Will update this description to be more accurate once the contract is deployed - const description = "# Configurate Arbitrum cUSDCv3 market for Native USDC native, and set ENS record for official markets"; - 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, govDeploymentManager: DeploymentManager, preMigrationBlockNumber: number) { - const ethers = deploymentManager.hre.ethers; - await deploymentManager.spider(); // Pull in Arbitrum COMP now that reward config has been set - const usdceComet = await deploymentManager.fromDep('usdceComet', 'arbitrum-goerli', 'usdc.e', 'comet'); - const { - comet, - rewards, - } = await deploymentManager.getContracts(); - - const config = await rewards.rewardConfig(comet.address); - - // 1. Verify state changes - const stateChanges = await diffState(comet, getCometConfig, preMigrationBlockNumber); - expect(stateChanges).to.deep.equal({ - LINK: { - supplyCap: exp(5_000_000, 18) - }, - WETH: { - supplyCap: exp(5_000, 18) - }, - WBTC: { - supplyCap: exp(300, 8) - }, - baseTrackingSupplySpeed: exp(34.74 / 86400, 15, 18), - baseTrackingBorrowSpeed: exp(34.74 / 86400, 15, 18), - }); - - expect(config.token).to.be.equal(arbitrumCOMPAddress); - expect(config.rescaleFactor).to.be.equal(exp(1, 12)); - expect(config.shouldUpscale).to.be.equal(true); - // Ensure proposal has set usdce market to 0 - expect(await usdceComet.baseTrackingSupplySpeed()).to.be.equal(0); - expect(await usdceComet.baseTrackingBorrowSpeed()).to.be.equal(0); - - // 2. & 3. Verify the seeded USDC reaches Comet reserve - expect(await comet.getReserves()).to.be.equal(exp(10, 6)); - - // 4. Verify the official markets are updated - const ENSResolver = await govDeploymentManager.existing('ENSResolver', ENSResolverAddress); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const officialMarketsJSON = await ENSResolver.text(subdomainHash, ENSTextRecordKey); - const officialMarkets = JSON.parse(officialMarketsJSON); - - expect(officialMarkets).to.deep.equal({ - 5: [ - { - baseSymbol: 'USDC', - cometAddress: '0x3EE77595A8459e93C2888b13aDB354017B198188', - }, - { - baseSymbol: 'WETH', - cometAddress: '0x9A539EEc489AAA03D588212a164d0abdB5F08F5F', - }, - ], - - 420: [ - { - baseSymbol: 'USDC', - cometAddress: '0xb8F2f9C84ceD7bBCcc1Db6FB7bb1F19A9a4adfF4' - } - ], - - 421613: [ - { - baseSymbol: 'USDC.e', - cometAddress: '0x1d573274E19174260c5aCE3f2251598959d24456', - }, - { - baseSymbol: 'USDC', - cometAddress: comet.address - }, - ], - - 59140: [ - { - baseSymbol: 'USDC', - cometAddress: '0xa84b24A43ba1890A165f94Ad13d0196E5fD1023a' - } - ], - - 84531: [ - { - baseSymbol: 'USDC', - cometAddress: '0xe78Fc55c884704F9485EDa042fb91BfE16fD55c1' - }, - { - baseSymbol: 'WETH', - cometAddress: '0xED94f3052638620fE226a9661ead6a39C2a265bE' - } - ], - - 80001: [ - { - baseSymbol: 'USDC', - cometAddress: '0xF09F0369aB0a875254fB565E52226c88f10Bc839' - }, - ] - }); - } -}); diff --git a/deployments/arbitrum-goerli/usdc/relations.ts b/deployments/arbitrum-goerli/usdc/relations.ts deleted file mode 100644 index 8ad1e0e2d..000000000 --- a/deployments/arbitrum-goerli/usdc/relations.ts +++ /dev/null @@ -1,29 +0,0 @@ -import baseRelationConfig from '../../relations'; - -export default { - ...baseRelationConfig, - governor: { - artifact: 'contracts/bridges/arbitrum/ArbitrumBridgeReceiver.sol:ArbitrumBridgeReceiver' - }, - ClonableBeaconProxy: { - artifact: 'contracts/ERC20.sol:ERC20' - }, - // Native USDC - '0xfd064A18f3BF249cf1f87FC203E90D8f650f2d63': { - artifact: 'contracts/ERC20.sol:ERC20', - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - // WETH - '0xe39ab88f8a4777030a534146a9ca3b52bd5d43a3': { - artifact: 'contracts/ERC20.sol:ERC20', - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - } -}; diff --git a/deployments/arbitrum-goerli/usdc/roots.json b/deployments/arbitrum-goerli/usdc/roots.json deleted file mode 100644 index 6f3a59a8c..000000000 --- a/deployments/arbitrum-goerli/usdc/roots.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comet": "0x0C94d3F9D7F211630EDecAF085718Ac80821A6cA", - "configurator": "0x1Ead344570F0f0a0cD86d95d8adDC7855C8723Fb", - "rewards": "0x8DA65F8E3Aa22A498211fc4204C498ae9050DAE4", - "bridgeReceiver": "0xAC9fC1a9532BC92a9f33eD4c6Ce4A7a54930F376", - "bulker": "0x987350Af5a17b6DdafeB95E6e329c178f44841d7", - "CCTPMessageTransmitter": "0x109bc137cb64eab7c0b1dddd1edf341467dc2d35" -} \ No newline at end of file diff --git a/deployments/arbitrum/usdc/relations.ts b/deployments/arbitrum/usdc/relations.ts index 462bfc1a4..9a8535766 100644 --- a/deployments/arbitrum/usdc/relations.ts +++ b/deployments/arbitrum/usdc/relations.ts @@ -59,4 +59,12 @@ export default { } } }, + ERC1967Proxy: { + artifact: 'contracts/ERC20.sol:ERC20', + delegates: { + field: { + slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' + } + } + }, }; \ No newline at end of file diff --git a/deployments/base-goerli/usdc/configuration.json b/deployments/base-goerli/usdc/configuration.json deleted file mode 100644 index c782ac14d..000000000 --- a/deployments/base-goerli/usdc/configuration.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "Compound USDC", - "symbol": "cUSDCv3", - "baseToken": "USDC", - "baseTokenAddress": "0x31D3A7711a74b4Ec970F50c3eaf1ee47ba803A95", - "baseTokenPriceFeed": "0xb85765935B4d9Ab6f841c9a00690Da5F34368bc0", - "borrowMin": "1e6", - "pauseGuardian": "0xBA5e81fD6811E2699b478d1Bcde62a585bC9b6f7", - "storeFrontPriceFactor": 0.5, - "targetReserves": "1000000e6", - "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.000402083333333e15", - "baseBorrowSpeed": "0.000402083333333e15", - "baseMinForRewards": "10000e6" - }, - "assets": { - "cbETH": { - "address": "0x7c6b91D9Be155A6Db01f749217d76fF02A7227F2", - "priceFeed": "0xcD2A119bD1F7DF95d706DE6F2057fDD45A0503E2", - "decimals": "18", - "borrowCF": 0.75, - "liquidateCF": 0.8, - "liquidationFactor": 0.93, - "supplyCap": "800e18" - }, - "WETH": { - "address": "0x4200000000000000000000000000000000000006", - "priceFeed": "0xcD2A119bD1F7DF95d706DE6F2057fDD45A0503E2", - "decimals": "18", - "borrowCF": 0.775, - "liquidateCF": 0.825, - "liquidationFactor": 0.95, - "supplyCap": "1000e18" - } - } -} diff --git a/deployments/base-goerli/usdc/deploy.ts b/deployments/base-goerli/usdc/deploy.ts deleted file mode 100644 index d9b505101..000000000 --- a/deployments/base-goerli/usdc/deploy.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; -import { DeploySpec, deployComet } from '../../../src/deploy'; - -const SECONDS_PER_DAY = 24 * 60 * 60; - -const GOERLI_TIMELOCK = '0x8Fa336EB4bF58Cfc508dEA1B0aeC7336f55B1399'; - -export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { - const deployed = await deployContracts(deploymentManager, deploySpec); - return deployed; -} - -async function deployContracts( - deploymentManager: DeploymentManager, - deploySpec: DeploySpec -): Promise { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - - // Pull in existing assets - const WETH = await deploymentManager.existing( - 'WETH', - '0x4200000000000000000000000000000000000006', - 'base-goerli' - ); - - const l2CrossDomainMessenger = await deploymentManager.existing( - 'l2CrossDomainMessenger', - ['0xC0d3c0d3c0D3c0D3C0d3C0D3C0D3c0d3c0d30007', '0x4200000000000000000000000000000000000007'], - 'base-goerli' - ); - - const l2StandardBridge = await deploymentManager.existing( - 'l2StandardBridge', - ['0xC0d3c0d3c0D3c0d3C0D3c0D3C0d3C0D3C0D30010', '0x4200000000000000000000000000000000000010'], - 'base-goerli' - ); - - // Deploy OptimismBridgeReceiver - const bridgeReceiver = await deploymentManager.deploy( - 'bridgeReceiver', - 'bridges/optimism/OptimismBridgeReceiver.sol', - [l2CrossDomainMessenger.address] - ); - - // Deploy Local Timelock - const localTimelock = await deploymentManager.deploy( - 'timelock', - 'vendor/Timelock.sol', - [ - bridgeReceiver.address, // admin - 10 * 60, // delay - 14 * SECONDS_PER_DAY, // grace period - 10 * 60, // minimum delay - 30 * SECONDS_PER_DAY // maximum delay - ] - ); - - // Initialize OptimismBridgeReceiver - await deploymentManager.idempotent( - async () => !(await bridgeReceiver.initialized()), - async () => { - trace(`Initializing BridgeReceiver`); - await bridgeReceiver.initialize( - GOERLI_TIMELOCK, // govTimelock - localTimelock.address // localTimelock - ); - trace(`BridgeReceiver initialized`); - } - ); - - // Deploy Comet - const deployed = await deployComet(deploymentManager, deploySpec); - const { comet } = deployed; - - // Deploy Bulker - const bulker = await deploymentManager.deploy( - 'bulker', - 'bulkers/BaseBulker.sol', - [ - await comet.governor(), // admin - WETH.address // weth - ] - ); - - // Deploy fauceteer - const fauceteer = await deploymentManager.deploy('fauceteer', 'test/Fauceteer.sol', []); - - return { - ...deployed, - bridgeReceiver, - l2CrossDomainMessenger, - l2StandardBridge, - bulker, - fauceteer - }; -} diff --git a/deployments/base-goerli/usdc/migrations/1679592519_configurate_and_ens.ts b/deployments/base-goerli/usdc/migrations/1679592519_configurate_and_ens.ts deleted file mode 100644 index 2143b2825..000000000 --- a/deployments/base-goerli/usdc/migrations/1679592519_configurate_and_ens.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { diffState, getCometConfig } from '../../../../plugins/deployment_manager/DiffState'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; -import { calldata, exp, getConfigurationStruct, proposal } from '../../../../src/deploy'; -import { expect } from 'chai'; - -const ENSName = 'compound-community-licenses.eth'; -const ENSResolverAddress = '0x19c2d5D0f035563344dBB7bE5fD09c8dad62b001'; -const ENSRegistryAddress = '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'; -const ENSSubdomainLabel = 'v3-additional-grants'; -const ENSSubdomain = `${ENSSubdomainLabel}.${ENSName}`; -const ENSTextRecordKey = 'v3-official-markets'; -const baseCOMPAddress = '0xA29b548056c3fD0f68BAd9d4829EC4E66f22f796'; - -export default migration('1679592519_configurate_and_ens', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - const { utils } = ethers; - - const { - bridgeReceiver, - comet, - cometAdmin, - configurator, - rewards, - } = await deploymentManager.getContracts(); - - const { - baseL1CrossDomainMessenger, - baseL1StandardBridge, - governor, - COMP: goerliCOMP, - } = await govDeploymentManager.getContracts(); - - // ENS Setup - // See also: https://docs.ens.domains/contract-api-reference/name-processing - const ENSResolver = await govDeploymentManager.existing('ENSResolver', ENSResolverAddress, 'goerli'); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const baseGoerliChainId = (await deploymentManager.hre.ethers.provider.getNetwork()).chainId.toString(); - const newMarketObject = { baseSymbol: 'USDC', cometAddress: comet.address }; - const officialMarketsJSON = JSON.parse(await ENSResolver.text(subdomainHash, ENSTextRecordKey)); - if (officialMarketsJSON[baseGoerliChainId]) { - officialMarketsJSON[baseGoerliChainId].push(newMarketObject); - } else { - officialMarketsJSON[baseGoerliChainId] = [newMarketObject]; - } - - const configuration = await getConfigurationStruct(deploymentManager); - - const setConfigurationCalldata = await calldata( - configurator.populateTransaction.setConfiguration(comet.address, configuration) - ); - const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [configurator.address, comet.address] - ); - const setRewardConfigCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [comet.address, baseCOMPAddress] - ); - const l2ProposalData = utils.defaultAbiCoder.encode( - ['address[]', 'uint256[]', 'string[]', 'bytes[]'], - [ - [configurator.address, cometAdmin.address, rewards.address], - [0, 0, 0], - [ - 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', - 'deployAndUpgradeTo(address,address)', - 'setRewardConfig(address,address)' - ], - [setConfigurationCalldata, deployAndUpgradeToCalldata, setRewardConfigCalldata] - ] - ); - - const COMPAmountToBridge = exp(10_000, 18); - - // Note: We aren't bridging USDC over to Base Goerli because they don't use a bridged version of USDC there, - const goerliActions = [ - // 1. Set Comet configuration + deployAndUpgradeTo new Comet and set reward config on Base-Goerli. - { - contract: baseL1CrossDomainMessenger, - signature: 'sendMessage(address,bytes,uint32)', - args: [bridgeReceiver.address, l2ProposalData, 2_500_000] - }, - - // 2. Approve Goerli's L1StandardBridge to take Timelock's COMP (for bridging) - { - contract: goerliCOMP, - signature: 'approve(address,uint256)', - args: [baseL1StandardBridge.address, COMPAmountToBridge] - }, - // 3. Bridge COMP from Goerli to Base-Goerli Comet using L1StandardBridge - { - contract: baseL1StandardBridge, - // function depositERC20To(address _l1Token, address _l2Token, address _to, uint256 _amount, uint32 _l2Gas,bytes calldata _data) - signature: 'depositERC20To(address,address,address,uint256,uint32,bytes)', - args: [goerliCOMP.address, baseCOMPAddress, rewards.address, COMPAmountToBridge, 200_000, '0x'] - }, - - // 4. Update the list of official markets - { - target: ENSResolverAddress, - signature: 'setText(bytes32,string,string)', - calldata: ethers.utils.defaultAbiCoder.encode( - ['bytes32', 'string', 'string'], - [subdomainHash, ENSTextRecordKey, JSON.stringify(officialMarketsJSON)] - ) - }, - ]; - - const description = "# Configurate Base-Goerli cUSDCv3 market, set reward config, bridge over USDC and COMP, and update ENS text record."; - const txn = await govDeploymentManager.retry(async () => - trace(await governor.propose(...(await proposal(goerliActions, 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, govDeploymentManager: DeploymentManager, preMigrationBlockNumber: number) { - const ethers = deploymentManager.hre.ethers; - await deploymentManager.spider(); // We spider here to pull in Optimism COMP now that reward config has been set - - const { - comet, - rewards, - COMP, - } = await deploymentManager.getContracts(); - - // 1. - const stateChanges = await diffState(comet, getCometConfig, preMigrationBlockNumber); - expect(stateChanges).to.deep.equal({ - pauseGuardian: '0xBA5e81fD6811E2699b478d1Bcde62a585bC9b6f7', - baseTrackingSupplySpeed: exp(34.74 / 86400, 15, 18), - baseTrackingBorrowSpeed: exp(34.74 / 86400, 15, 18), - baseBorrowMin: exp(1, 6), - WETH: { - supplyCap: exp(1000, 18) - }, - cbETH: { - supplyCap: exp(800, 18) - } - }) - - const config = await rewards.rewardConfig(comet.address); - expect(config.token).to.be.equal(COMP.address); - expect(config.rescaleFactor).to.be.equal(exp(1, 12)); - expect(config.shouldUpscale).to.be.equal(true); - - // 2. & 3. - expect(await COMP.balanceOf(rewards.address)).to.be.equal(exp(10_000, 18)); - - // 4. - const ENSResolver = await govDeploymentManager.existing('ENSResolver', ENSResolverAddress, 'goerli'); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const officialMarketsJSON = await ENSResolver.text(subdomainHash, ENSTextRecordKey); - const officialMarkets = JSON.parse(officialMarketsJSON); - expect(officialMarkets).to.deep.equal({ - 5: [ - { - baseSymbol: 'USDC', - cometAddress: '0x3EE77595A8459e93C2888b13aDB354017B198188', - }, - { - baseSymbol: 'WETH', - cometAddress: '0x9A539EEc489AAA03D588212a164d0abdB5F08F5F', - }, - ], - 80001: [ - { - baseSymbol: 'USDC', - cometAddress: '0xF09F0369aB0a875254fB565E52226c88f10Bc839', - }, - ], - 420: [ - { - baseSymbol: 'USDC', - cometAddress: '0xb8F2f9C84ceD7bBCcc1Db6FB7bb1F19A9a4adfF4' - } - ], - 421613: [ - { - baseSymbol: 'USDC', - cometAddress: '0x1d573274E19174260c5aCE3f2251598959d24456' - } - ], - 84531: [ - { - baseSymbol: 'USDC', - cometAddress: comet.address, - }, - ], - }); - } -}); \ No newline at end of file diff --git a/deployments/base-goerli/usdc/relations.ts b/deployments/base-goerli/usdc/relations.ts deleted file mode 100644 index 5f5760eec..000000000 --- a/deployments/base-goerli/usdc/relations.ts +++ /dev/null @@ -1,24 +0,0 @@ -import baseRelationConfig from '../../relations'; - -export default { - ...baseRelationConfig, - governor: { - artifact: 'contracts/bridges/optimism/OptimismBridgeReceiver.sol:OptimismBridgeReceiver' - }, - - l2CrossDomainMessenger: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - - l2StandardBridge: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - } -}; \ No newline at end of file diff --git a/deployments/base-goerli/usdc/roots.json b/deployments/base-goerli/usdc/roots.json deleted file mode 100644 index ffe3f14d7..000000000 --- a/deployments/base-goerli/usdc/roots.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "comet": "0xe78Fc55c884704F9485EDa042fb91BfE16fD55c1", - "configurator": "0xB1C86B6f4BA3c997dAC601671418F6B026aaA5b2", - "rewards": "0x0818165C053D325985d87F4b8646b3062C72C385", - "bridgeReceiver": "0xdf983449591838C8660cAd7cE08C65b030A43bbE", - "l2CrossDomainMessenger": "0x4200000000000000000000000000000000000007", - "l2StandardBridge": "0x4200000000000000000000000000000000000010", - "bulker": "0x684108D64Ac3BdE77c617bDEbDBC9afaE6562676", - "fauceteer": "0x54fcBea987d18E027a827eE25e1943Cf0874Eba8" -} \ No newline at end of file diff --git a/deployments/base-goerli/weth/configuration.json b/deployments/base-goerli/weth/configuration.json deleted file mode 100644 index b0060d2f0..000000000 --- a/deployments/base-goerli/weth/configuration.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "Compound WETH", - "symbol": "cWETHv3", - "baseToken": "WETH", - "baseTokenAddress": "0x4200000000000000000000000000000000000006", - "borrowMin": "0.001e18", - "pauseGuardian": "0xBA5e81fD6811E2699b478d1Bcde62a585bC9b6f7", - "storeFrontPriceFactor": 0.5, - "targetReserves": "500e18", - "rates": { - "supplyKink": 0.9, - "supplySlopeLow": 0.0283824, - "supplySlopeHigh": 0.6066567706, - "supplyBase": 0, - "borrowKink": 0.9, - "borrowSlopeLow": 0.05171500002, - "borrowSlopeHigh": 0.5171500339, - "borrowBase": 0.009945209674 - }, - "tracking": { - "indexScale": "1e15", - "baseSupplySpeed": "0.000402083333333e15", - "baseBorrowSpeed": "0.000402083333333e15", - "baseMinForRewards": "1e18" - }, - "assets": { - "cbETH": { - "address": "0x7c6b91D9Be155A6Db01f749217d76fF02A7227F2", - "priceFeed": "0xcD2A119bD1F7DF95d706DE6F2057fDD45A0503E2", - "decimals": "18", - "borrowCF": 0.90, - "liquidateCF": 0.93, - "liquidationFactor": 0.95, - "supplyCap": "1000e18" - } - } -} - diff --git a/deployments/base-goerli/weth/deploy.ts b/deployments/base-goerli/weth/deploy.ts deleted file mode 100644 index 8b4065cbc..000000000 --- a/deployments/base-goerli/weth/deploy.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; -import { DeploySpec, deployComet, exp } from '../../../src/deploy'; - -export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { - const deployed = await deployContracts(deploymentManager, deploySpec); - return deployed; -} - -async function deployContracts( - deploymentManager: DeploymentManager, - deploySpec: DeploySpec -): Promise { - const trace = deploymentManager.tracer(); - - // Deploy constant price feed for WETH - const wethConstantPriceFeed = await deploymentManager.deploy( - 'WETH:priceFeed', - 'pricefeeds/ConstantPriceFeed.sol', - [ - 8, // decimals - exp(1, 8) // constantPrice - ] - ); - - // Deploy scaling price feed for cbETH - // XXX There is no cbETH / ETH pricefeed on testnet. Remember to change this for mainnet. - // const cbETHScalingPriceFeed = await deploymentManager.deploy( - // 'cbETH:priceFeed', - // 'ScalingPriceFeed.sol', - // [ - // '0xcD2A119bD1F7DF95d706DE6F2057fDD45A0503E2', // cbETH / ETH price feed - // 8 // decimals - // ] - // ); - const cbETHConstantPriceFeed = await deploymentManager.deploy( - 'cbETH:priceFeed', - 'pricefeeds/ConstantPriceFeed.sol', - [ - 8, // decimals - exp(1, 8) // constantPrice - ] - ); - - // Import shared contracts from cUSDCv3 - const cometAdmin = await deploymentManager.fromDep('cometAdmin', 'base-goerli', 'usdc'); - const cometFactory = await deploymentManager.fromDep('cometFactory', 'base-goerli', 'usdc'); - const $configuratorImpl = await deploymentManager.fromDep('configurator:implementation', 'base-goerli', 'usdc'); - const configurator = await deploymentManager.fromDep('configurator', 'base-goerli', 'usdc'); - const rewards = await deploymentManager.fromDep('rewards', 'base-goerli', 'usdc'); - const bulker = await deploymentManager.fromDep('bulker', 'base-goerli', 'usdc'); - const fauceteer = await deploymentManager.fromDep('fauceteer', 'base-goerli', 'usdc'); - const l2CrossDomainMessenger = await deploymentManager.fromDep('l2CrossDomainMessenger', 'base-goerli', 'usdc'); - const l2StandardBridge = await deploymentManager.fromDep('l2StandardBridge', 'base-goerli', 'usdc'); - const localTimelock = await deploymentManager.fromDep('timelock', 'base-goerli', 'usdc'); - const bridgeReceiver = await deploymentManager.fromDep('bridgeReceiver', 'base-goerli', 'usdc'); - - // Deploy Comet - const deployed = await deployComet(deploymentManager, deploySpec); - - // XXX We will need to deploy a new bulker only if need to support wstETH - - return { - ...deployed, - bridgeReceiver, - l2CrossDomainMessenger, - l2StandardBridge, - bulker, - fauceteer - }; -} diff --git a/deployments/base-goerli/weth/migrations/1685486850_configurate_and_ens.ts b/deployments/base-goerli/weth/migrations/1685486850_configurate_and_ens.ts deleted file mode 100644 index fc00b94ed..000000000 --- a/deployments/base-goerli/weth/migrations/1685486850_configurate_and_ens.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { diffState, getCometConfig } from '../../../../plugins/deployment_manager/DiffState'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; -import { calldata, exp, getConfigurationStruct, proposal } from '../../../../src/deploy'; -import { expect } from 'chai'; - -const ENSName = 'compound-community-licenses.eth'; -const ENSResolverAddress = '0x19c2d5D0f035563344dBB7bE5fD09c8dad62b001'; -const ENSRegistryAddress = '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'; -const ENSSubdomainLabel = 'v3-additional-grants'; -const ENSSubdomain = `${ENSSubdomainLabel}.${ENSName}`; -const ENSTextRecordKey = 'v3-official-markets'; -const baseCOMPAddress = '0xA29b548056c3fD0f68BAd9d4829EC4E66f22f796'; -const amountETHToWrap = exp(0.1, 18); - -export default migration('1685486850_configurate_and_ens', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - const { utils } = ethers; - - const cometFactory = await deploymentManager.fromDep('cometFactory', 'base-goerli', 'usdc'); - const { - bridgeReceiver, - timelock: localTimelock, - comet, - cometAdmin, - configurator, - rewards, - WETH - } = await deploymentManager.getContracts(); - - const { - baseL1CrossDomainMessenger, - baseL1StandardBridge, - governor, - COMP: goerliCOMP, - } = await govDeploymentManager.getContracts(); - - // ENS Setup - // See also: https://docs.ens.domains/contract-api-reference/name-processing - const ENSResolver = await govDeploymentManager.existing('ENSResolver', ENSResolverAddress, 'goerli'); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const baseGoerliChainId = (await deploymentManager.hre.ethers.provider.getNetwork()).chainId.toString(); - const newMarketObject = { baseSymbol: 'WETH', cometAddress: comet.address }; - const officialMarketsJSON = JSON.parse(await ENSResolver.text(subdomainHash, ENSTextRecordKey)); - if (officialMarketsJSON[baseGoerliChainId]) { - officialMarketsJSON[baseGoerliChainId].push(newMarketObject); - } else { - officialMarketsJSON[baseGoerliChainId] = [newMarketObject]; - } - - const configuration = await getConfigurationStruct(deploymentManager); - const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactory.address) - ); - const setConfigurationCalldata = await calldata( - configurator.populateTransaction.setConfiguration(comet.address, configuration) - ); - const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [configurator.address, comet.address] - ); - const setRewardConfigCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [comet.address, baseCOMPAddress] - ); - // Note: There is no way to directly bridge WETH, so we have to bridge ETH to the Timelock, wrap it, then transfer it to Comet - const transferWETHCalldata = utils.defaultAbiCoder.encode( - ['address', 'uint256'], - [comet.address, amountETHToWrap] - ); - - const l2ProposalData = utils.defaultAbiCoder.encode( - ['address[]', 'uint256[]', 'string[]', 'bytes[]'], - [ - [configurator.address, configurator.address, cometAdmin.address, rewards.address, WETH.address, WETH.address], - [0, 0, 0, 0, amountETHToWrap, 0], - [ - 'setFactory(address,address)', - 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', - 'deployAndUpgradeTo(address,address)', - 'setRewardConfig(address,address)', - 'deposit()', - 'transfer(address,uint256)' - ], - [setFactoryCalldata, setConfigurationCalldata, deployAndUpgradeToCalldata, setRewardConfigCalldata, '0x', transferWETHCalldata] - ] - ); - - const COMPAmountToBridge = exp(10_000, 18); - - const goerliActions = [ - - // 1. Set Comet configuration + deployAndUpgradeTo new Comet, set reward config on Base-Goerli, wrap ETH to WETH and transfer to Comet as reserves. - { - contract: baseL1CrossDomainMessenger, - signature: 'sendMessage(address,bytes,uint32)', - args: [bridgeReceiver.address, l2ProposalData, 3_500_000] - }, - - // 2. Bridge ETH to the L2 timelock - { - contract: baseL1StandardBridge, - value: amountETHToWrap, - signature: 'depositETHTo(address,uint32,bytes)', - args: [localTimelock.address, 200_000, '0x'] - }, - - // 3. Approve Goerli's L1StandardBridge to take Timelock's COMP (for bridging) - { - contract: goerliCOMP, - signature: 'approve(address,uint256)', - args: [baseL1StandardBridge.address, COMPAmountToBridge] - }, - // 4. Bridge COMP from Goerli to Base-Goerli Comet using L1StandardBridge - { - contract: baseL1StandardBridge, - // function depositERC20To(address _l1Token, address _l2Token, address _to, uint256 _amount, uint32 _l2Gas,bytes calldata _data) - signature: 'depositERC20To(address,address,address,uint256,uint32,bytes)', - args: [goerliCOMP.address, baseCOMPAddress, rewards.address, COMPAmountToBridge, 200_000, '0x'] - }, - - // 5. Update the list of official markets - { - target: ENSResolverAddress, - signature: 'setText(bytes32,string,string)', - calldata: ethers.utils.defaultAbiCoder.encode( - ['bytes32', 'string', 'string'], - [subdomainHash, ENSTextRecordKey, JSON.stringify(officialMarketsJSON)] - ) - }, - ]; - - const description = "# Configurate Base-Goerli cWETHv3 market, set reward config, bridge over WETH and COMP, and update ENS text record."; - const txn = await govDeploymentManager.retry(async () => - trace(await governor.propose(...(await proposal(goerliActions, 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, govDeploymentManager: DeploymentManager, preMigrationBlockNumber: number) { - const ethers = deploymentManager.hre.ethers; - await deploymentManager.spider(); // We spider here to pull in Optimism COMP now that reward config has been set - - const { - comet, - rewards, - COMP, - WETH - } = await deploymentManager.getContracts(); - - // 1. - const stateChanges = await diffState(comet, getCometConfig, preMigrationBlockNumber); - expect(stateChanges).to.deep.equal({ - pauseGuardian: '0xBA5e81fD6811E2699b478d1Bcde62a585bC9b6f7', - baseTrackingSupplySpeed: exp(34.74 / 86400, 15, 18), - baseTrackingBorrowSpeed: exp(34.74 / 86400, 15, 18), - cbETH: { - supplyCap: exp(1000, 18) - } - }) - - const config = await rewards.rewardConfig(comet.address); - expect(config.token).to.be.equal(COMP.address); - expect(config.rescaleFactor).to.be.equal(exp(1, 12)); - expect(config.shouldUpscale).to.be.equal(true); - - // 1. & 2. - expect(await comet.getReserves()).to.be.equal(amountETHToWrap); - expect(await WETH.balanceOf(comet.address)).to.be.equal(amountETHToWrap); - - // 3. & 4. - expect(await COMP.balanceOf(rewards.address)).to.be.equal(exp(20_000, 18)); - - // 5. - const ENSResolver = await govDeploymentManager.existing('ENSResolver', ENSResolverAddress, 'goerli'); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const officialMarketsJSON = await ENSResolver.text(subdomainHash, ENSTextRecordKey); - const officialMarkets = JSON.parse(officialMarketsJSON); - - expect(officialMarkets).to.deep.equal({ - 5: [ - { - baseSymbol: 'USDC', - cometAddress: '0x3EE77595A8459e93C2888b13aDB354017B198188', - }, - { - baseSymbol: 'WETH', - cometAddress: '0x9A539EEc489AAA03D588212a164d0abdB5F08F5F', - }, - ], - 80001: [ - { - baseSymbol: 'USDC', - cometAddress: '0xF09F0369aB0a875254fB565E52226c88f10Bc839', - }, - ], - 420: [ - { - baseSymbol: 'USDC', - cometAddress: '0xb8F2f9C84ceD7bBCcc1Db6FB7bb1F19A9a4adfF4' - } - ], - 421613: [ - { - baseSymbol: 'USDC', - cometAddress: '0x1d573274E19174260c5aCE3f2251598959d24456' - } - ], - 84531: [ - { - baseSymbol: 'USDC', - cometAddress: '0xe78Fc55c884704F9485EDa042fb91BfE16fD55c1' - }, - { - baseSymbol: 'WETH', - cometAddress: comet.address, - }, - ], - }); - } -}); \ No newline at end of file diff --git a/deployments/base-goerli/weth/relations.ts b/deployments/base-goerli/weth/relations.ts deleted file mode 100644 index 5f5760eec..000000000 --- a/deployments/base-goerli/weth/relations.ts +++ /dev/null @@ -1,24 +0,0 @@ -import baseRelationConfig from '../../relations'; - -export default { - ...baseRelationConfig, - governor: { - artifact: 'contracts/bridges/optimism/OptimismBridgeReceiver.sol:OptimismBridgeReceiver' - }, - - l2CrossDomainMessenger: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - - l2StandardBridge: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - } -}; \ No newline at end of file diff --git a/deployments/base-goerli/weth/roots.json b/deployments/base-goerli/weth/roots.json deleted file mode 100644 index b804a9c21..000000000 --- a/deployments/base-goerli/weth/roots.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "comet": "0xED94f3052638620fE226a9661ead6a39C2a265bE", - "configurator": "0xB1C86B6f4BA3c997dAC601671418F6B026aaA5b2", - "rewards": "0x0818165C053D325985d87F4b8646b3062C72C385", - "bridgeReceiver": "0xdf983449591838C8660cAd7cE08C65b030A43bbE", - "l2CrossDomainMessenger": "0x4200000000000000000000000000000000000007", - "l2StandardBridge": "0x4200000000000000000000000000000000000010", - "bulker": "0x684108D64Ac3BdE77c617bDEbDBC9afaE6562676", - "fauceteer": "0x54fcBea987d18E027a827eE25e1943Cf0874Eba8" -} \ No newline at end of file diff --git a/deployments/goerli/usdc/configuration.json b/deployments/goerli/usdc/configuration.json deleted file mode 100644 index 6f632ad4c..000000000 --- a/deployments/goerli/usdc/configuration.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "Compound USDC", - "symbol": "cUSDCv3", - "baseToken": "USDC", - "baseTokenPriceFeed": "0xAb5c49580294Aff77670F839ea425f5b78ab3Ae7", - "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": "10000e6" - }, - "rewardToken": "COMP", - "assets": { - "COMP": { - "priceFeed": "0x54a06047087927D9B0fb21c1cf0ebd792764dDB8", - "decimals": "18", - "borrowCF": 0.65, - "liquidateCF": 0.7, - "liquidationFactor": 0.92, - "supplyCap": "500000e18" - }, - "WBTC": { - "priceFeed": "0xA39434A63A52E749F02807ae27335515BA4b07F7", - "decimals": "8", - "borrowCF": 0.7, - "liquidateCF": 0.75, - "liquidationFactor": 0.93, - "supplyCap": "35000e8" - }, - "WETH": { - "priceFeed": "0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e", - "decimals": "18", - "borrowCF": 0.82, - "liquidateCF": 0.85, - "liquidationFactor": 0.93, - "supplyCap": "1000000e18" - } - } -} \ No newline at end of file diff --git a/deployments/goerli/usdc/deploy.ts b/deployments/goerli/usdc/deploy.ts deleted file mode 100644 index b0dd2d7d9..000000000 --- a/deployments/goerli/usdc/deploy.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; -import { DeploySpec, cloneGov, deployComet, exp, sameAddress, wait } from '../../../src/deploy'; - -export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { - const deployed = await deployContracts(deploymentManager, deploySpec); - await mintTokens(deploymentManager); - return deployed; -} - -async function deployContracts(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { - const trace = deploymentManager.tracer() - const ethers = deploymentManager.hre.ethers; - const signer = await deploymentManager.getSigner(); - - // Declare existing assets as aliases - const COMP = await deploymentManager.existing('COMP', '0x3587b2F7E0E2D6166d6C14230e7Fe160252B0ba4'); - const USDC = await deploymentManager.existing('USDC', '0x07865c6E87B9F70255377e024ace6630C1Eaa37F'); - const WBTC = await deploymentManager.existing('WBTC', '0xAAD4992D949f9214458594dF92B44165Fb84dC19'); - const WETH = await deploymentManager.existing('WETH', '0x42a71137C09AE83D8d05974960fd607d40033499'); - - // Goerli -> Mumbai bridge contract - const fxRoot = await deploymentManager.existing('fxRoot', '0x3d1d3e34f7fb6d26245e6640e1c50710efff15ba', 'goerli'); - - // Deploy governance contracts - const { fauceteer, timelock } = await cloneGov(deploymentManager); - - // Deploy all Comet-related contracts - const deployed = await deployComet(deploymentManager, deploySpec); - const { rewards } = deployed; - - // Deploy Bulker - const bulker = await deploymentManager.deploy( - 'bulker', - 'Bulker.sol', - [timelock.address, WETH.address] - ); - - await deploymentManager.idempotent( - async () => (await COMP.balanceOf(rewards.address)).eq(0), - async () => { - trace(`Sending some COMP to CometRewards`); - const amount = exp(1_000_000, 18); - trace(await wait(COMP.connect(signer).transfer(rewards.address, amount))); - trace(`COMP.balanceOf(${rewards.address}): ${await COMP.balanceOf(rewards.address)}`); - trace(`COMP.balanceOf(${signer.address}): ${await COMP.balanceOf(signer.address)}`); - } - ); - - return { ...deployed, fauceteer, bulker, fxRoot }; -} - -async function mintTokens(deploymentManager: DeploymentManager) { - const trace = deploymentManager.tracer(); - const signer = await deploymentManager.getSigner(); - const contracts = await deploymentManager.contracts(); - const fauceteer = contracts.get('fauceteer'); - - trace(`Attempting to mint as ${signer.address}...`); - - const WETH = contracts.get('WETH'); - await deploymentManager.idempotent( - async () => (await WETH.balanceOf(signer.address)).lt(exp(0.01, 18)), - async () => { - trace(`Minting 0.01 WETH for signer (this is a precious resource!)`); - trace(await wait(WETH.connect(signer).deposit({ value: exp(0.01, 18) }))); - trace(`WETH.balanceOf(${signer.address}): ${await WETH.balanceOf(signer.address)}`); - } - ); - - const WBTC = contracts.get('WBTC'); - await deploymentManager.idempotent( - async () => (await WBTC.balanceOf(fauceteer.address)).eq(0), - async () => { - trace(`Minting 20 WBTC to fauceteer`); - const amount = exp(20, await WBTC.decimals()); - trace(await wait(WBTC.connect(signer).mint(fauceteer.address, amount))); - trace(`WBTC.balanceOf(${fauceteer.address}): ${await WBTC.balanceOf(fauceteer.address)}`); - } - ); -} \ No newline at end of file diff --git a/deployments/goerli/usdc/migrations/1663870047_add_link.ts b/deployments/goerli/usdc/migrations/1663870047_add_link.ts deleted file mode 100644 index b4d1460c3..000000000 --- a/deployments/goerli/usdc/migrations/1663870047_add_link.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { DeploymentManager, migration } from '../../../../plugins/deployment_manager'; -import { exp, proposal, wait } from '../../../../src/deploy'; - -import { expect } from 'chai'; - -const clone = { - link: '0x514910771af9ca656af840dff83e8264ecf986ca', -}; - -const LINK_PRICE_FEED = '0x48731cF7e84dc94C5f84577882c14Be11a5B7456'; -const PROPOSED_LINK_ASSET_INFO = { - priceFeed: LINK_PRICE_FEED, - decimals: 18, - borrowCollateralFactor: exp(0.75, 18), - liquidateCollateralFactor: exp(0.8, 18), - liquidationFactor: exp(0.92, 18), - supplyCap: exp(50_000_000, 18), -}; - -export default migration('1663870047_add_link', { - async prepare(deploymentManager: DeploymentManager) { - return {}; - }, - - async enact(deploymentManager: DeploymentManager) { - const trace = deploymentManager.tracer(); - const signer = await deploymentManager.getSigner(); - - const { - governor, - comet, - configurator, - cometAdmin, - fauceteer, - } = await deploymentManager.getContracts(); - - // Clone LINK and send half of total supply to the fauceteer - const LINK = await deploymentManager.clone('LINK', clone.link, []); - trace(`Sending half of all LINK to fauceteer`); - const amount = (await LINK.balanceOf(signer.address)).div(2); - trace(await wait(LINK.connect(signer).transfer(fauceteer.address, amount))); - trace(`LINK.balanceOf(${fauceteer.address}): ${await LINK.balanceOf(fauceteer.address)}`); - - const linkAssetConfig = { - asset: LINK.address, - ...PROPOSED_LINK_ASSET_INFO - }; - - const actions = [ - // 1. Add LINK in Configurator - { - contract: configurator, - signature: 'addAsset(address,(address,address,uint8,uint64,uint64,uint64,uint128))', - args: [comet.address, linkAssetConfig], - }, - - // 2. Deploy and upgrade to a new version of Comet - { - contract: cometAdmin, - signature: 'deployAndUpgradeTo(address,address)', - args: [configurator.address, comet.address], - }, - ]; - const description = "# Add LINK to Goerli"; - const txn = await deploymentManager.retry( - async () => governor.propose(...await proposal(actions, description)) - ); - trace(txn); - - const event = (await txn.wait()).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, - fauceteer, - LINK - } = await deploymentManager.getContracts(); - const linkAssetIndex = 3; - const linkAssetConfig = { - asset: LINK.address, - ...PROPOSED_LINK_ASSET_INFO - }; - - // 1. Compare proposed asset config with Comet asset info - const cometLinkAssetInfo = await comet.getAssetInfoByAddress(LINK.address); - expect(linkAssetIndex).to.be.equal(cometLinkAssetInfo.offset); - expect(linkAssetConfig.asset).to.be.equal(cometLinkAssetInfo.asset); - expect(linkAssetConfig.priceFeed).to.be.equal(cometLinkAssetInfo.priceFeed); - expect(exp(1, linkAssetConfig.decimals)).to.be.equal(cometLinkAssetInfo.scale); - expect(linkAssetConfig.borrowCollateralFactor).to.be.equal(cometLinkAssetInfo.borrowCollateralFactor); - expect(linkAssetConfig.liquidateCollateralFactor).to.be.equal(cometLinkAssetInfo.liquidateCollateralFactor); - expect(linkAssetConfig.liquidationFactor).to.be.equal(cometLinkAssetInfo.liquidationFactor); - expect(linkAssetConfig.supplyCap).to.be.equal(cometLinkAssetInfo.supplyCap); - - // 2. Compare proposed asset config with Configurator asset config - const configuratorLinkAssetConfig = (await configurator.getConfiguration(comet.address)).assetConfigs[linkAssetIndex]; - expect(linkAssetConfig.asset).to.be.equal(configuratorLinkAssetConfig.asset); - expect(linkAssetConfig.priceFeed).to.be.equal(configuratorLinkAssetConfig.priceFeed); - expect(linkAssetConfig.decimals).to.be.equal(configuratorLinkAssetConfig.decimals); - expect(linkAssetConfig.borrowCollateralFactor).to.be.equal(configuratorLinkAssetConfig.borrowCollateralFactor); - expect(linkAssetConfig.liquidateCollateralFactor).to.be.equal(configuratorLinkAssetConfig.liquidateCollateralFactor); - expect(linkAssetConfig.liquidationFactor).to.be.equal(configuratorLinkAssetConfig.liquidationFactor); - expect(linkAssetConfig.supplyCap).to.be.equal(configuratorLinkAssetConfig.supplyCap); - - // 3. Expect that the Fauceteer has received half of the LINK total supply - expect(await LINK.balanceOf(fauceteer.address)).to.be.equal(exp(500_000_000, 18)); // Half of 1bn total supply - }, -}); diff --git a/deployments/goerli/usdc/migrations/1665028496_absorb_transfer_event_and_auto_collateral.ts b/deployments/goerli/usdc/migrations/1665028496_absorb_transfer_event_and_auto_collateral.ts deleted file mode 100644 index c58d98206..000000000 --- a/deployments/goerli/usdc/migrations/1665028496_absorb_transfer_event_and_auto_collateral.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { DeploymentManager, migration } from '../../../../plugins/deployment_manager'; -import { calldata, exp, proposal } from '../../../../src/deploy'; - -import { expect } from 'chai'; - -export default migration('1665028496_absorb_transfer_event_and_auto_collateral', { - async prepare(deploymentManager: DeploymentManager) { - const cometFactory = await deploymentManager.deploy('cometFactory', 'CometFactory.sol', [], true); - return { newFactoryAddress: cometFactory.address }; - }, - - async enact(deploymentManager: DeploymentManager, { newFactoryAddress }) { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - - const { - governor, - comet, - configurator, - cometAdmin, - COMP, - } = await deploymentManager.getContracts(); - - const actions = [ - // 1. Set comet factory to newly deployed factory - { - contract: configurator, - signature: 'setFactory(address,address)', - args: [comet.address, newFactoryAddress], - }, - - // 2. Deploy and upgrade to a new version of Comet - { - contract: cometAdmin, - signature: 'deployAndUpgradeTo(address,address)', - args: [configurator.address, comet.address], - }, - ]; - const description = "# Liquidation Event Handling And Collateral Reserves\n"; - const txn = await deploymentManager.retry( - async () => governor.propose(...await proposal(actions, description)) - ); - trace(txn); - - const event = (await txn.wait()).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) { - // 1. & 2. - // added a scenario to check for new Transfer event - } -}); diff --git a/deployments/goerli/usdc/migrations/1681942579_upgrade_governor_bravo.ts b/deployments/goerli/usdc/migrations/1681942579_upgrade_governor_bravo.ts deleted file mode 100644 index c23f01ca3..000000000 --- a/deployments/goerli/usdc/migrations/1681942579_upgrade_governor_bravo.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { expect } from 'chai'; -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; -import { proposal } from '../../../../src/deploy'; - -const clone = { - governorImpl: '0xeF3B6E9e13706A8F01fe98fdCf66335dc5CfdEED' -}; - -const OLD_GOVERNOR_IMPL_ADDRESS = '0x9d26789c7b2492E6015B26dc75C79AeA71a7211c'; - -export default migration('1681942579_upgrade_governor_bravo', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - - const { governor } = await deploymentManager.getContracts(); - - // Deploy new governor implementation (cloned from mainnet) - const newGovernorImpl = await deploymentManager.clone( - 'newGovernorImpl', - clone.governorImpl, - [], - 'mainnet' - ); - - const actions = [ - // 1. Set implementation of the governor to the new governor implementation - { - target: governor.address, - signature: '_setImplementation(address)', - calldata: ethers.utils.defaultAbiCoder.encode(['address'], [newGovernorImpl.address]) - } - ]; - const description = - '# Update governor implementation\n\n## Explanation\n\nUpdates the governor implementation to allow for sending ETH from the Timelock. \n'; - const txn = await deploymentManager.retry(async () => - governor.propose(...(await proposal(actions, description))) - ); - trace(txn); - - const event = (await txn.wait()).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) { - await deploymentManager.spider(); // We spider here to pull in the updated governor impl address - const { 'governor:implementation': governorImpl } = await deploymentManager.getContracts(); - - // 1. - expect(governorImpl.address).to.not.be.eq(OLD_GOVERNOR_IMPL_ADDRESS); - } -}); diff --git a/deployments/goerli/usdc/relations.ts b/deployments/goerli/usdc/relations.ts deleted file mode 100644 index 6652288ff..000000000 --- a/deployments/goerli/usdc/relations.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { RelationConfigMap } from '../../../plugins/deployment_manager/RelationConfig'; -import baseRelationConfig from '../../relations'; - -export default { - ...baseRelationConfig, - fxRoot: { - relations: { - stateSender: { - field: async fxRoot => fxRoot.stateSender() - } - } - }, - arbitrumInbox: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - }, - relations: { - arbitrumBridge: { - field: async inbox => inbox.bridge() - } - } - }, - arbitrumL1GatewayRouter: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - baseL1CrossDomainMessenger: { - delegates: { - // Not great, but this address shouldn't change and is very difficult to grab on-chain (private methods) - field: async () => '0xa042e16781484716c1Ef448c919af7BCd9607467' - } - }, - baseL1StandardBridge: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - }, - }, - opL1CrossDomainMessenger: { - delegates: { - field: async () => '0xDa2332D0a7608919Cd331B1304Cd179129a90495', - }, - }, - opL1StandardBridge: { - delegates: { - field: { - slot: - '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc', - }, - }, - }, - lineaMessageService: { - artifact: 'contracts/bridges/linea/IMessageService.sol:IMessageService', - // delegates: { - // field: { - // slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - // } - // } - }, - lineaL1TokenBridge: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - lineaL1usdcBridge: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - scrollMessenger: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - scrollL1TokenBridge: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - } -}; diff --git a/deployments/goerli/usdc/roots.json b/deployments/goerli/usdc/roots.json deleted file mode 100644 index 3add9436d..000000000 --- a/deployments/goerli/usdc/roots.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "timelock": "0x8Fa336EB4bF58Cfc508dEA1B0aeC7336f55B1399", - "fauceteer": "0x75442Ac771a7243433e033F3F8EaB2631e22938f", - "comet": "0x3EE77595A8459e93C2888b13aDB354017B198188", - "configurator": "0xB28495db3eC65A0e3558F040BC4f98A0d588Ae60", - "rewards": "0xef9e070044d62C38D2e316146dDe92AD02CF2c2c", - "bulker": "0x69dD076105977c55dC2835951d287f82D54606b4", - "fxRoot": "0x3d1d3E34f7fB6D26245E6640E1c50710eFFf15bA", - "arbitrumInbox": "0x6BEbC4925716945D46F0Ec336D5C2564F419682C", - "arbitrumL1GatewayRouter": "0x4c7708168395aEa569453Fc36862D2ffcDaC588c", - "baseL1CrossDomainMessenger": "0x8e5693140eA606bcEB98761d9beB1BC87383706D", - "baseL1StandardBridge": "0xfA6D8Ee5BE770F84FC001D098C4bD604Fe01284a", - "lineaMessageService": "0x70BaD09280FD342D02fe64119779BC1f0791BAC2", - "lineaL1TokenBridge": "0xaA012D038E6440535Ec66eDf2DA592F4F8398133", - "lineaL1usdcBridge": "0x9c556D2cCfb6157E4A6305aa9963EdD6ca5047cB", - "CCTPTokenMessenger": "0xd0c3da58f55358142b8d3e06c1c30c5c6114efe8", - "CCTPMessageTransmitter": "0x26413e8157cd32011e726065a5462e97dd4d03d9", - "opL1CrossDomainMessenger": "0x5086d1eEF304eb5284A0f6720f79403b4e9bE294", - "opL1StandardBridge": "0x636Af16bf2f682dD3109e60102b8E1A089FedAa8", - "scrollMessenger": "0x5260e38080BFe97e6C4925d9209eCc5f964373b6", - "scrollL1TokenBridge": "0xe5E30E7c24e4dFcb281A682562E53154C15D3332" -} diff --git a/deployments/goerli/weth/configuration.json b/deployments/goerli/weth/configuration.json deleted file mode 100644 index bd5113a3f..000000000 --- a/deployments/goerli/weth/configuration.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "Compound WETH", - "symbol": "cWETHv3", - "baseToken": "WETH", - "baseTokenAddress": "0x42a71137C09AE83D8d05974960fd607d40033499", - "borrowMin": "0.1e18", - "governor": "0x8Fa336EB4bF58Cfc508dEA1B0aeC7336f55B1399", - "pauseGuardian": "0x8Fa336EB4bF58Cfc508dEA1B0aeC7336f55B1399", - "storeFrontPriceFactor": 0.5, - "targetReserves": "5000e18", - "rates": { - "supplyKink": 0.9, - "supplySlopeLow": 0.01690681444, - "supplySlopeHigh": 0.6066567706, - "supplyBase": 0, - "borrowKink": 0.9, - "borrowSlopeLow": 0.05171500002, - "borrowSlopeHigh": 0.5171500339, - "borrowBase": 0.009945209674 - }, - "tracking": { - "indexScale": "1e15", - "baseSupplySpeed": "447916666666e0", - "baseBorrowSpeed": "0e15", - "baseMinForRewards": "1000e18" - }, - "assets": { - "cbETH": { - "decimals": "18", - "borrowCF": 0.90, - "liquidateCF": 0.93, - "liquidationFactor": 0.95, - "supplyCap": "9_000e18" - }, - "wstETH": { - "address": "0x4942BBAf745f235e525BAff49D31450810EDed5b", - "decimals": "18", - "borrowCF": 0.90, - "liquidateCF": 0.93, - "liquidationFactor": 0.95, - "supplyCap": "80_000e18" - } - } -} \ No newline at end of file diff --git a/deployments/goerli/weth/deploy.ts b/deployments/goerli/weth/deploy.ts deleted file mode 100644 index a08b9c01a..000000000 --- a/deployments/goerli/weth/deploy.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; -import { debug, DeploySpec, deployComet, exp, sameAddress, wait } from '../../../src/deploy'; - -const clone = { - cbETHImpl: '0x31724cA0C982A31fbb5C57f4217AB585271fc9a5', - cbETHProxy: '0xBe9895146f7AF43049ca1c1AE358B0541Ea49704', -}; - -export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { - const deployed = await deployContracts(deploymentManager, deploySpec); - await mintTokens(deploymentManager); - return deployed; -} - -async function deployContracts(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { - const ethers = deploymentManager.hre.ethers; - const signer = await deploymentManager.getSigner(); - - // Declare existing assets as aliases - const WETH = await deploymentManager.existing('WETH', '0x42a71137C09AE83D8d05974960fd607d40033499', 'goerli'); - const wstETH = await deploymentManager.existing('wstETH', '0x4942BBAf745f235e525BAff49D31450810EDed5b', 'goerli'); - - // Import shared contracts from cUSDCv3 - const cometAdmin = await deploymentManager.fromDep('cometAdmin', 'goerli', 'usdc'); - const cometFactory = await deploymentManager.fromDep('cometFactory', 'goerli', 'usdc'); - const $configuratorImpl = await deploymentManager.fromDep('configurator:implementation', 'goerli', 'usdc'); - const configurator = await deploymentManager.fromDep('configurator', 'goerli', 'usdc'); - const rewards = await deploymentManager.fromDep('rewards', 'goerli', 'usdc'); - const fauceteer = await deploymentManager.fromDep('fauceteer', 'goerli', 'usdc'); - const fxRoot = await deploymentManager.fromDep('fxRoot', 'goerli', 'usdc'); - - // Clone cbETH - const cbETHProxyAdmin = await deploymentManager.deploy('cbETH:admin', 'vendor/proxy/transparent/ProxyAdmin.sol', []); - const cbETHImpl = await deploymentManager.clone('cbETH:implementation', clone.cbETHImpl, []); - const cbETHProxy = await deploymentManager.clone('cbETH', clone.cbETHProxy, [cbETHImpl.address]); - const cbETHProxyAdminSlot = '0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b'; - const cbETH = cbETHImpl.attach(cbETHProxy.address); - await deploymentManager.idempotent( - async () => !sameAddress(await ethers.provider.getStorageAt(cbETHProxy.address, cbETHProxyAdminSlot), cbETHProxyAdmin.address), - async () => { - debug(`Changing admin of cbETH proxy to ${cbETHProxyAdmin.address}`); - await wait(cbETHProxy.connect(signer).changeAdmin(cbETHProxyAdmin.address)); - - debug(`Initializing cbETH`); - await wait(cbETH.connect(signer).initialize( - 'Coinbase Wrapped Staked ETH', // name - 'cbETH', // symbol - '', // currency - 18, // decimals - signer.address, // Master Minter - signer.address, // Pauser - signer.address, // Blacklister - signer.address // Owner - )); - } - ); - - // Deploy stETH / ETH SimplePriceFeed - const stETHtoETHPriceFeed = await deploymentManager.deploy( - 'stETHToETH:simplePriceFeed', - 'test/SimplePriceFeed.sol', - [ - exp(0.98882408, 18), // Latest answer on mainnet at block 16170924 - 18 - ] - ); - - // Deploy cbETH / ETH SimplePriceFeed - const cbETHtoETHPriceFeed = await deploymentManager.deploy( - 'cbETHToETH:simplePriceFeed', - 'test/SimplePriceFeed.sol', - [ - exp(0.97, 18), - 18 - ] - ); - - // Deploy WstETHPriceFeed - const wstETHPriceFeed = await deploymentManager.deploy( - 'wstETH:priceFeed', - 'WstETHPriceFeed.sol', - [ - stETHtoETHPriceFeed.address, // stETH / ETH price feed - wstETH.address, // wstETH - 8 // decimals - ] - ); - - // Deploy constant price feed for WETH - const wethConstantPriceFeed = await deploymentManager.deploy( - 'WETH:priceFeed', - 'ConstantPriceFeed.sol', - [ - 8, // decimals - exp(1, 8) // constantPrice - ] - ); - - // Deploy scaling price feed for cbETH - const cbETHScalingPriceFeed = await deploymentManager.deploy( - 'cbETH:priceFeed', - 'ScalingPriceFeed.sol', - [ - cbETHtoETHPriceFeed.address, // cbETH / ETH price feed - 8 // decimals - ] - ); - - // Deploy all Comet-related contracts - const deployed = await deployComet(deploymentManager, deploySpec); - const { comet } = deployed; - - // Deploy Bulker - const bulker = await deploymentManager.deploy( - 'bulker', - 'bulkers/MainnetBulker.sol', - [ - await comet.governor(), // admin_ - WETH.address, // weth_ - wstETH.address // wsteth_ - ] - ); - - return { ...deployed, bulker, fauceteer, fxRoot }; -} - -async function mintTokens(deploymentManager: DeploymentManager) { - const signer = await deploymentManager.getSigner(); - const contracts = await deploymentManager.contracts(); - const fauceteer = contracts.get('fauceteer')!; - - debug(`Attempting to mint as ${signer.address}...`); - - // If we haven't spidered new contracts (which we could before minting, but its slow), - // then the proxy contract won't have the impl functions yet, so just do it explicitly - const cbETHProxy = contracts.get('cbETH')!, cbETHImpl = contracts.get('cbETH:implementation')!; - const cbETH = cbETHImpl.attach(cbETHProxy.address); - await deploymentManager.idempotent( - async () => (await cbETH.balanceOf(fauceteer.address)).eq(0), - async () => { - debug(`Minting 1M cbETH to fauceteer`); - const amount = exp(1_000_000, await cbETH.decimals()); - await wait(cbETH.connect(signer).configureMinter(signer.address, amount)); - await wait(cbETH.connect(signer).mint(fauceteer.address, amount)); - debug(`cbETH.balanceOf(${fauceteer.address}): ${await cbETH.balanceOf(fauceteer.address)}`); - } - ); -} diff --git a/deployments/goerli/weth/migrations/1672860425_initialize_market.ts b/deployments/goerli/weth/migrations/1672860425_initialize_market.ts deleted file mode 100644 index 03aa5a7b8..000000000 --- a/deployments/goerli/weth/migrations/1672860425_initialize_market.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { DeploymentManager, migration } from '../../../../plugins/deployment_manager'; -import { exp, getConfigurationStruct, proposal } from '../../../../src/deploy'; - -import { expect } from 'chai'; - -const COMPAddress = '0x3587b2F7E0E2D6166d6C14230e7Fe160252B0ba4'; - -export default migration('1672860425_initialize_market', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager) => { - const trace = deploymentManager.tracer(); - - // Import shared contracts from cUSDCv3 - const cometFactory = await deploymentManager.fromDep('cometFactory', 'goerli', 'usdc'); - - const { - governor, - comet, - configurator, - cometAdmin, - rewards, - } = await deploymentManager.getContracts(); - - const configuration = await getConfigurationStruct(deploymentManager); - - const actions = [ - // 1. Set the factory in the Configurator - { - contract: configurator, - signature: 'setFactory(address,address)', - args: [comet.address, cometFactory.address], - }, - - // 2. Set the configuration in the Configurator - { - contract: configurator, - signature: 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', - args: [comet.address, configuration], - }, - - // 3. Deploy and upgrade to a new version of Comet - { - contract: cometAdmin, - signature: "deployAndUpgradeTo(address,address)", - args: [configurator.address, comet.address], - }, - - // 4. Set the rewards configuration to COMP - { - contract: rewards, - signature: "setRewardConfig(address,address)", - args: [comet.address, COMPAddress], - }, - ]; - const description = "# Initialize cWETHv3 on Goerli" - const txn = await deploymentManager.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 true; - }, - - - async verify(deploymentManager: DeploymentManager) { - const { - comet, - rewards, - wstETH, - cbETH, - } = await deploymentManager.getContracts(); - // 2. & 3. - expect(await comet.baseTrackingSupplySpeed()).to.be.equal(exp(38.7 / 86400, 15, 18)); // ~ 38.7 COMP / day cut from v2 - expect(await comet.baseTrackingBorrowSpeed()).to.be.equal(0); - - const wstETHInfo = await comet.getAssetInfoByAddress(wstETH.address); - expect(wstETHInfo.supplyCap).to.be.equal(exp(80_000, 18)); // ~ $100M / $1225 - - const cbETHInfo = await comet.getAssetInfoByAddress(cbETH.address); - expect(cbETHInfo.supplyCap).to.be.equal(exp(9_000, 18)); // ~ $10M / $1091 - - // 4. - const config = await rewards.rewardConfig(comet.address); - expect(config.token).to.be.equal(COMPAddress); - expect(config.rescaleFactor).to.be.equal(1000000000000n); - expect(config.shouldUpscale).to.be.equal(true); - }, -}); \ No newline at end of file diff --git a/deployments/goerli/weth/migrations/1675148548_set_up_ens_subdomain_and_text_record.ts b/deployments/goerli/weth/migrations/1675148548_set_up_ens_subdomain_and_text_record.ts deleted file mode 100644 index eeebc7936..000000000 --- a/deployments/goerli/weth/migrations/1675148548_set_up_ens_subdomain_and_text_record.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { expect } from 'chai'; -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; -import { proposal } from '../../../../src/deploy'; - -interface Vars {} - -const ENSName = 'compound-community-licenses.eth'; -const ENSSubdomainLabel = 'v3-additional-grants'; -const ENSSubdomain = ENSSubdomainLabel + '.' + ENSName; -const ENSResolverAddress = '0x19c2d5D0f035563344dBB7bE5fD09c8dad62b001'; -const ENSRegistryAddress = '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'; -const textRecordKey = 'v3-official-markets'; -// JSON string of official markets -const officialMarketsJSON = JSON.stringify({ - 1: [ - { - baseSymbol: 'USDC', - cometAddress: '0xc3d688B66703497DAA19211EEdff47f25384cdc3' - }, - { - baseSymbol: 'WETH', - cometAddress: '0xA17581A9E3356d9A858b789D68B4d866e593aE94' - } - ] -}); - -export default migration('1675148548_set_up_ens_subdomain_and_text_record', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, vars: Vars) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - - const { timelock, governor } = await deploymentManager.getContracts(); - - // Namehash explanation: https://docs.ens.domains/contract-api-reference/name-processing - const nameHash = ethers.utils.namehash(ENSName); - const labelHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(ENSSubdomainLabel)); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - - const actions = [ - // 1. Set up 'v3-additional-grants.compound-community-licenses.eth' ENS subdomain with the Timelock as the owner - { - target: ENSRegistryAddress, - signature: 'setSubnodeRecord(bytes32,bytes32,address,address,uint64)', - // setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) - calldata: ethers.utils.defaultAbiCoder.encode( - ['bytes32', 'bytes32', 'address', 'address', 'uint64'], - [nameHash, labelHash, timelock.address, ENSResolverAddress, 0] - ) - }, - - // 2. Set the official markets text record on the subdomain - { - target: ENSResolverAddress, - signature: 'setText(bytes32,string,string)', - calldata: ethers.utils.defaultAbiCoder.encode( - ['bytes32', 'string', 'string'], - [subdomainHash, textRecordKey, officialMarketsJSON] - ) - } - ]; - const description = - '# Set up an ENS subdomain and text record for official Comet deployments\n'; - const txn = await deploymentManager.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 true; - }, - - async verify(deploymentManager: DeploymentManager) { - const ethers = deploymentManager.hre.ethers; - - const ENSResolver = await deploymentManager.existing('ENSResolver', ENSResolverAddress); - const ENSRegistry = await deploymentManager.existing('ENSRegistry', ENSRegistryAddress); - - const { timelock } = await deploymentManager.getContracts(); - - const nameHash = ethers.utils.namehash(ENSName); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - - // 1. - expect(await ENSRegistry.recordExists(subdomainHash)).to.be.equal(true); - expect(await ENSRegistry.owner(subdomainHash)).to.be.equal(timelock.address); - expect(await ENSRegistry.resolver(subdomainHash)).to.be.equal(ENSResolverAddress); - expect(await ENSRegistry.ttl(subdomainHash)).to.be.equal(0); - - // 2. - expect(await ENSResolver.text(subdomainHash, textRecordKey)).to.be.equal(officialMarketsJSON); - expect(await ENSResolver.text(nameHash, textRecordKey)).to.be.equal(''); - } -}); diff --git a/deployments/goerli/weth/relations.ts b/deployments/goerli/weth/relations.ts deleted file mode 100644 index 73cec97f3..000000000 --- a/deployments/goerli/weth/relations.ts +++ /dev/null @@ -1,20 +0,0 @@ -import baseRelationConfig from '../../relations'; - -export default { - ...baseRelationConfig, - 'fxRoot': { - relations: { - stateSender: { - field: async (fxRoot) => fxRoot.stateSender() - } - } - }, - 'wstETH': { - artifact: 'contracts/bulkers/IWstETH.sol', - relations: { - stETH: { - field: async (wstETH) => wstETH.stETH() - } - } - }, -}; diff --git a/deployments/goerli/weth/roots.json b/deployments/goerli/weth/roots.json deleted file mode 100644 index 9f4b7c1e7..000000000 --- a/deployments/goerli/weth/roots.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comet": "0x9A539EEc489AAA03D588212a164d0abdB5F08F5F", - "configurator": "0xB28495db3eC65A0e3558F040BC4f98A0d588Ae60", - "rewards": "0xef9e070044d62C38D2e316146dDe92AD02CF2c2c", - "bulker": "0x69dD076105977c55dC2835951d287f82D54606b4", - "fauceteer": "0x75442Ac771a7243433e033F3F8EaB2631e22938f", - "fxRoot": "0x3d1d3e34f7fb6d26245e6640e1c50710efff15ba" -} \ No newline at end of file diff --git a/deployments/linea-goerli/usdc/configuration.json b/deployments/linea-goerli/usdc/configuration.json deleted file mode 100644 index 0ce449a25..000000000 --- a/deployments/linea-goerli/usdc/configuration.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "Compound USDC", - "symbol": "cUSDCv3", - "baseToken": "USDC", - "baseTokenAddress": "0xf56dc6695cF1f5c364eDEbC7Dc7077ac9B586068", - "baseTokenPriceFeed": "0xcb81fffa91cd5f3436318d25057c1d5df8e23f95", - "borrowMin": "0.001e6", - "storeFrontPriceFactor": 0.5, - "targetReserves": "1000000e6", - "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.000402083333333e15", - "baseBorrowSpeed": "0.000402083333333e15", - "baseMinForRewards": "1000e6" - }, - "assets": { - "WETH": { - "address": "0x2C1b868d6596a18e32E61B901E4060C872647b6C", - "priceFeed": "0x45A61d74eaa5F78a6e1919Ca74Db2615743190Ad", - "decimals": "18", - "borrowCF": 0.775, - "liquidateCF": 0.825, - "liquidationFactor": 0.95, - "supplyCap": "10000000e18" - }, - "WBTC": { - "address": "0xdbcd5bafbaa8c1b326f14ec0c8b125db57a5cc4c", - "priceFeed": "0x625e78891611d5a6227ff78548c373b56b0c8ea0", - "decimals": "18", - "borrowCF": 0.7, - "liquidateCF": 0.75, - "liquidationFactor": 0.93, - "supplyCap": "30000e18" - } - } -} diff --git a/deployments/linea-goerli/usdc/deploy.ts b/deployments/linea-goerli/usdc/deploy.ts deleted file mode 100644 index 6ae1e930c..000000000 --- a/deployments/linea-goerli/usdc/deploy.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; -import { DeploySpec, deployComet, exp, wait } from '../../../src/deploy'; - -const secondsPerDay = 24 * 60 * 60; - -const GOERLI_TIMELOCK = '0x8Fa336EB4bF58Cfc508dEA1B0aeC7336f55B1399'; - -export default async function deploy( - deploymentManager: DeploymentManager, - deploySpec: DeploySpec -): Promise { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - - // Pull in existing assets - const WETH = await deploymentManager.existing( - 'WETH', - '0x2C1b868d6596a18e32E61B901E4060C872647b6C', - 'linea-goerli' - ); - - const l2MessageService = await deploymentManager.existing( - 'l2MessageService', - '0xC499a572640B64eA1C8c194c43Bc3E19940719dC', - 'linea-goerli' - ); - - const l2TokenBridge = await deploymentManager.existing( - 'l2TokenBridge', - '0xB191E3d98074f92584E5205B99c3F17fB2068927', - 'linea-goerli' - ); - - const l2usdcBridge = await deploymentManager.existing( - 'l2usdcBridge', - '0x2aeD4D02fD76EeC1580cCDbA158b16F4A0Ad2B60', - 'linea-goerli' - ); - - // Deploy LineaBridgeReceiver - const bridgeReceiver = await deploymentManager.deploy( - 'bridgeReceiver', - 'bridges/linea/LineaBridgeReceiver.sol', - [l2MessageService.address] - ); - - // Deploy Local Timelock - const localTimelock = await deploymentManager.deploy('timelock', 'vendor/Timelock.sol', [ - bridgeReceiver.address, // admin - 10 * 60, // delay - 14 * secondsPerDay, // grace period - 10 * 60, // minimum delay - 30 * secondsPerDay // maximum delay - ]); - - // Initialize BridgeReceiver - await deploymentManager.idempotent( - async () => !(await bridgeReceiver.initialized()), - async () => { - trace(`Initializing BridgeReceiver`); - await bridgeReceiver.initialize( - GOERLI_TIMELOCK, // govTimelock - localTimelock.address // localTimelock - ); - trace(`BridgeReceiver initialized`); - } - ); - - // Deploy Comet - const deployed = await deployComet(deploymentManager, deploySpec); - const { comet } = deployed; - - // Deploy Bulker - const bulker = await deploymentManager.deploy('bulker', 'bulkers/BaseBulker.sol', [ - await comet.governor(), // admin - WETH.address // weth - ]); - - // Deploy fauceteer - const fauceteer = await deploymentManager.deploy('fauceteer', 'test/Fauceteer.sol', []); - - return { - ...deployed, - bridgeReceiver, - l2MessageService, - l2TokenBridge, - bulker, - fauceteer, - l2usdcBridge - }; -} diff --git a/deployments/linea-goerli/usdc/migrations/1686918613_configurate_and_ens.ts b/deployments/linea-goerli/usdc/migrations/1686918613_configurate_and_ens.ts deleted file mode 100644 index e7dbc724b..000000000 --- a/deployments/linea-goerli/usdc/migrations/1686918613_configurate_and_ens.ts +++ /dev/null @@ -1,250 +0,0 @@ -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { diffState, getCometConfig } from '../../../../plugins/deployment_manager/DiffState'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; -import { calldata, exp, getConfigurationStruct, proposal } from '../../../../src/deploy'; -import { expect } from 'chai'; - -const ENSName = 'compound-community-licenses.eth'; -const ENSResolverAddress = '0x19c2d5D0f035563344dBB7bE5fD09c8dad62b001'; -const ENSSubdomainLabel = 'v3-additional-grants'; -const ENSSubdomain = `${ENSSubdomainLabel}.${ENSName}`; -const ENSTextRecordKey = 'v3-official-markets'; -const lineaCOMPAddress = '0xab3134fa5edfb3dc64aa790e8bb6448117d18fe9'; - -export default migration('1686918613_configurate_and_ens', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - const { utils } = ethers; - - const { - bridgeReceiver, - comet, - cometAdmin, - configurator, - rewards - } = await deploymentManager.getContracts(); - - const { - lineaMessageService, - lineaL1TokenBridge, - lineaL1usdcBridge, - governor, - COMP, - USDC - } = await govDeploymentManager.getContracts(); - - // ENS Setup - // See also: https://docs.ens.domains/contract-api-reference/name-processing - const ENSResolver = await govDeploymentManager.existing( - 'ENSResolver', - ENSResolverAddress, - 'goerli' - ); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const lineaGoerliChainId = ( - await deploymentManager.hre.ethers.provider.getNetwork() - ).chainId.toString(); - const newMarketObject = { baseSymbol: 'USDC', cometAddress: comet.address }; - const officialMarketsJSON = JSON.parse(await ENSResolver.text(subdomainHash, ENSTextRecordKey)); - if (officialMarketsJSON[lineaGoerliChainId]) { - officialMarketsJSON[lineaGoerliChainId].push(newMarketObject); - } else { - officialMarketsJSON[lineaGoerliChainId] = [newMarketObject]; - } - - const configuration = await getConfigurationStruct(deploymentManager); - - const setConfigurationCalldata = await calldata( - configurator.populateTransaction.setConfiguration(comet.address, configuration) - ); - const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [configurator.address, comet.address] - ); - const setRewardConfigCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [comet.address, lineaCOMPAddress] - ); - const l2ProposalData = utils.defaultAbiCoder.encode( - ['address[]', 'uint256[]', 'string[]', 'bytes[]'], - [ - [configurator.address, cometAdmin.address, rewards.address], - [0, 0, 0], - [ - 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', - 'deployAndUpgradeTo(address,address)', - 'setRewardConfig(address,address)' - ], - [setConfigurationCalldata, deployAndUpgradeToCalldata, setRewardConfigCalldata] - ] - ); - - const COMPAmountToBridge = exp(1_000, 18); - const USDCAmountToBridge = exp(100_000, 6); - - const goerliActions = [ - // 1. Set Comet configuration + deployAndUpgradeTo new Comet and set reward config on Linea-Goerli. - { - contract: lineaMessageService, - signature: 'sendMessage(address,uint256,bytes)', - args: [bridgeReceiver.address, 0, l2ProposalData] - }, - - // 2. Approve Goerli's L1StandardBridge to take Timelock's COMP (for bridging) - { - contract: COMP, - signature: 'approve(address,uint256)', - args: [lineaL1TokenBridge.address, COMPAmountToBridge] - }, - // 3. Bridge COMP from Goerli to Linea-Goerli Comet using L1StandardBridge - { - contract: lineaL1TokenBridge, - signature: 'bridgeToken(address,uint256,address)', - args: [COMP.address, COMPAmountToBridge, rewards.address] - }, - // 4. Approve Goerli's L1usdcBridge to take Timelock's USDC (for bridging) - { - contract: USDC, - signature: 'approve(address,uint256)', - args: [lineaL1usdcBridge.address, USDCAmountToBridge] - }, - // 5. Bridge USDC from Goerli to Linea-Goerli Comet using L1usdcBridge - { - contract: lineaL1usdcBridge, - signature: 'depositTo(uint256,address)', - args: [USDCAmountToBridge, rewards.address] - }, - // 6. Update the list of official markets - { - target: ENSResolverAddress, - signature: 'setText(bytes32,string,string)', - calldata: ethers.utils.defaultAbiCoder.encode( - ['bytes32', 'string', 'string'], - [subdomainHash, ENSTextRecordKey, JSON.stringify(officialMarketsJSON)] - ) - } - ]; - - const description = - '# Configurate Linea-Goerli cUSDCv3 market, set reward config, bridge over USDC and COMP, and update ENS text record.'; - const txn = await govDeploymentManager.retry(async () => - trace(await governor.propose(...(await proposal(goerliActions, 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, - govDeploymentManager: DeploymentManager, - preMigrationBlockNumber: number - ) { - const ethers = deploymentManager.hre.ethers; - await deploymentManager.spider(); // We spider here to pull in Linea COMP now that reward config has been set - - const { comet, rewards, COMP, USDC } = await deploymentManager.getContracts(); - - // 1. - const stateChanges = await diffState(comet, getCometConfig, preMigrationBlockNumber); - expect(stateChanges).to.deep.equal({ - baseTrackingSupplySpeed: exp(34.74 / 86400, 15, 18), - baseTrackingBorrowSpeed: exp(34.74 / 86400, 15, 18), - baseMinForRewards: exp(1000, 6), - numAssets: 2, - WETH: { - borrowCollateralFactor: exp(0.775, 18), - liquidationFactor: exp(0.95, 18), - supplyCap: exp(1000, 18) - }, - WBTC: { - offset: 1, - asset: '0xdbcd5bafbaa8c1b326f14ec0c8b125db57a5cc4c', - priceFeed: '0x625e78891611D5A6227Ff78548C373b56B0C8ea0', - scale: exp(1, 18), - borrowCollateralFactor: exp(0.7, 18), - liquidateCollateralFactor: exp(0.75, 18), - liquidationFactor: exp(0.93, 18), - supplyCap: exp(300, 18) - }, - }); - - const config = await rewards.rewardConfig(comet.address); - expect(config.token).to.be.equal(COMP.address); - expect(config.rescaleFactor).to.be.equal(exp(1, 12)); - expect(config.shouldUpscale).to.be.equal(true); - - // 2. & 3. - expect(await COMP.balanceOf(rewards.address)).to.be.equal(exp(1_000, 18)); - - // 4 & 5, - expect(await USDC.balanceOf(rewards.address)).to.be.equal(exp(100_000, 6)); - - // 6. - const ENSResolver = await govDeploymentManager.existing( - 'ENSResolver', - ENSResolverAddress, - 'goerli' - ); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const officialMarketsJSON = await ENSResolver.text(subdomainHash, ENSTextRecordKey); - const officialMarkets = JSON.parse(officialMarketsJSON); - expect(officialMarkets).to.deep.equal({ - 5: [ - { - baseSymbol: 'USDC', - cometAddress: '0x3EE77595A8459e93C2888b13aDB354017B198188' - }, - { - baseSymbol: 'WETH', - cometAddress: '0x9A539EEc489AAA03D588212a164d0abdB5F08F5F' - } - ], - 80001: [ - { - baseSymbol: 'USDC', - cometAddress: '0xF09F0369aB0a875254fB565E52226c88f10Bc839' - } - ], - 420: [ - { - baseSymbol: 'USDC', - cometAddress: '0xb8F2f9C84ceD7bBCcc1Db6FB7bb1F19A9a4adfF4' - } - ], - 421613: [ - { - baseSymbol: 'USDC', - cometAddress: '0x1d573274E19174260c5aCE3f2251598959d24456' - } - ], - 84531: [ - { - baseSymbol: 'USDC', - cometAddress: '0xe78Fc55c884704F9485EDa042fb91BfE16fD55c1' - }, - { - baseSymbol: 'WETH', - cometAddress: '0xED94f3052638620fE226a9661ead6a39C2a265bE' - } - ], - 59140: [ - { - baseSymbol: 'USDC', - cometAddress: comet.address - } - ] - }); - } -}); diff --git a/deployments/linea-goerli/usdc/migrations/1687878801_increase_supply_caps.ts b/deployments/linea-goerli/usdc/migrations/1687878801_increase_supply_caps.ts deleted file mode 100644 index bf848322e..000000000 --- a/deployments/linea-goerli/usdc/migrations/1687878801_increase_supply_caps.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { - diffState, - getCometConfig, -} from '../../../../plugins/deployment_manager/DiffState'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; -import { - calldata, - exp, - getConfigurationStruct, - proposal, -} from '../../../../src/deploy'; -import { expect } from 'chai'; - -export default migration('1687878801_increase_supply_caps', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async ( - deploymentManager: DeploymentManager, - govDeploymentManager: DeploymentManager, - vars: Vars - ) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - const { utils } = ethers; - - const { - bridgeReceiver, - comet, - cometAdmin, - configurator, - } = await deploymentManager.getContracts(); - - const { - lineaMessageService, - governor, - } = await govDeploymentManager.getContracts(); - - const configuration = await getConfigurationStruct(deploymentManager); - - const setConfigurationCalldata = await calldata( - configurator.populateTransaction.setConfiguration( - comet.address, - configuration - ) - ); - 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], - [ - 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', - 'deployAndUpgradeTo(address,address)', - ], - [setConfigurationCalldata, deployAndUpgradeToCalldata], - ] - ); - - const goerliActions = [ - // 1. Set Comet configuration - { - contract: lineaMessageService, - signature: 'sendMessage(address,uint256,bytes)', - args: [bridgeReceiver.address, 0, l2ProposalData], - }, - ]; - - const description = '# Increase supply caps for Linea-Goerli cUSDCv3 market'; - const txn = await govDeploymentManager.retry(async () => - trace( - await governor.propose(...(await proposal(goerliActions, 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, - govDeploymentManager: DeploymentManager, - preMigrationBlockNumber: number - ) { - - const { comet } = await deploymentManager.getContracts(); - - // 1. - const stateChanges = await diffState(comet, getCometConfig, preMigrationBlockNumber); - expect(stateChanges).to.deep.equal({ - baseBorrowMin: exp(0.001, 6), - WETH: { - supplyCap: exp(10_000_000, 18) - }, - WBTC: { - supplyCap: exp(30_000, 18) - }, - }); - } -}); diff --git a/deployments/linea-goerli/usdc/relations.ts b/deployments/linea-goerli/usdc/relations.ts deleted file mode 100644 index f60791c96..000000000 --- a/deployments/linea-goerli/usdc/relations.ts +++ /dev/null @@ -1,37 +0,0 @@ -import baseRelationConfig from '../../relations'; - -export default { - ...baseRelationConfig, - governor: { - artifact: 'contracts/bridges/linea/LineaBridgeReceiver.sol:LineaBridgeReceiver' - }, - // COMP - '0xab3134fa5edfb3dc64aa790e8bb6448117d18fe9': { - artifact: 'contracts/ERC20.sol:ERC20', - }, - // WBTC - '0xdbcd5bafbaa8c1b326f14ec0c8b125db57a5cc4c': { - artifact: 'contracts/ERC20.sol:ERC20', - }, - l2MessageService: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - l2TokenBridge: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - l2usdcBridge: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - } -}; diff --git a/deployments/linea-goerli/usdc/roots.json b/deployments/linea-goerli/usdc/roots.json deleted file mode 100644 index 703086f1f..000000000 --- a/deployments/linea-goerli/usdc/roots.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "comet": "0xa84b24A43ba1890A165f94Ad13d0196E5fD1023a", - "configurator": "0x079f68Fa440A0F04d741a5Aba7DA8fE9DfB0AA8B", - "rewards": "0x44411C605eb7e009cad03f3847cfbbFCF8895130", - "bridgeReceiver": "0x06F066A9C0633507EAc640D89442C77748C3a2a8", - "l2MessageService": "0xC499a572640B64eA1C8c194c43Bc3E19940719dC", - "l2TokenBridge": "0xB191E3d98074f92584E5205B99c3F17fB2068927", - "bulker": "0xad6729C101691A63F7d1e4CcbaD04bC8c6818a22", - "fauceteer": "0x953d0A78eeC15E76266792fE163dC5316F5c2aca" -} \ No newline at end of file diff --git a/deployments/mainnet/usdt/relations.ts b/deployments/mainnet/usdt/relations.ts index 8036ed523..3bc07940d 100644 --- a/deployments/mainnet/usdt/relations.ts +++ b/deployments/mainnet/usdt/relations.ts @@ -28,4 +28,12 @@ export default { } } }, + TransparentUpgradeableProxy: { + artifact: 'contracts/ERC20.sol:ERC20', + delegates: { + field: { + slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' + } + } + }, }; \ No newline at end of file diff --git a/deployments/mumbai/usdc/configuration.json b/deployments/mumbai/usdc/configuration.json deleted file mode 100644 index cb9f2656f..000000000 --- a/deployments/mumbai/usdc/configuration.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "Compound USDC", - "symbol": "cUSDCv3", - "baseToken": "USDC", - "baseTokenPriceFeed": "0x572dDec9087154dC5dfBB1546Bb62713147e0Ab0", - "borrowMin": "100e6", - "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": "10000e6" - }, - "assets": { - "DAI": { - "priceFeed": "0x0FCAa9c899EC5A91eBc3D5Dd869De833b06fB046", - "decimals": "18", - "borrowCF": 0.79, - "liquidateCF": 0.85, - "liquidationFactor": 0.93, - "supplyCap": "1_000_000e18" - }, - "WETH": { - "priceFeed": "0x0715A7794a1dc8e42615F059dD6e406A6594651A", - "decimals": "18", - "borrowCF": 0.82, - "liquidateCF": 0.85, - "liquidationFactor": 0.93, - "supplyCap": "50_000e18" - }, - "WBTC": { - "priceFeed": "0x007A22900a3B98143368Bd5906f8E17e9867581b", - "decimals": "8", - "borrowCF": 0.7, - "liquidateCF": 0.75, - "liquidationFactor": 0.93, - "supplyCap": "20_000e8" - }, - "WMATIC": { - "priceFeed": "0xd0D5e3DB44DE05E9F294BB0a3bEEaF030DE24Ada", - "decimals": "18", - "borrowCF": 0.82, - "liquidateCF": 0.85, - "liquidationFactor": 0.93, - "supplyCap": "500_000e18" - } - } -} \ No newline at end of file diff --git a/deployments/mumbai/usdc/deploy.ts b/deployments/mumbai/usdc/deploy.ts deleted file mode 100644 index 45440653e..000000000 --- a/deployments/mumbai/usdc/deploy.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; -import { DeploySpec, deployComet, exp, sameAddress, wait } from '../../../src/deploy'; - -const clone = { - usdcImpl: '0xa2327a938Febf5FEC13baCFb16Ae10EcBc4cbDCF', - usdcProxy: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - weth: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', - wbtc: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - wmatic: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', - dai: '0x6b175474e89094c44da98b954eedeac495271d0f' -}; - -const FX_CHILD = "0xCf73231F28B7331BBe3124B907840A94851f9f11"; -const GOERLI_TIMELOCK = "0x8Fa336EB4bF58Cfc508dEA1B0aeC7336f55B1399"; - -const secondsPerDay = 24 * 60 * 60; - -export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { - const deployed = await deployContracts(deploymentManager, deploySpec); - await mintTokens(deploymentManager); - return deployed; -} - -async function deployContracts(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { - const trace = deploymentManager.tracer() - const ethers = deploymentManager.hre.ethers; - const signer = await deploymentManager.getSigner(); - - const fxChild = await deploymentManager.existing('fxChild', FX_CHILD, 'mumbai'); - - // Deploy PolygonBridgeReceiver - const bridgeReceiver = await deploymentManager.deploy( - 'bridgeReceiver', - 'bridges/polygon/PolygonBridgeReceiver.sol', - [fxChild?.address] // fxChild - ); - - // Deploy Local Timelock - const localTimelock = await deploymentManager.deploy( - 'timelock', - 'vendor/Timelock.sol', - [ - bridgeReceiver.address, // admin - 10 * 60, // delay - 14 * secondsPerDay, // grace period - 10 * 60, // minimum delay - 30 * secondsPerDay // maxiumum delay - ] - ); - - await deploymentManager.idempotent( - async () => !(await bridgeReceiver.initialized()), - async () => { - trace(`Initializing BridgeReceiver`); - await bridgeReceiver.initialize( - GOERLI_TIMELOCK, // govTimelock - localTimelock.address // localTimelock - ); - trace(`BridgeReceiver initialized`); - } - ); - - // USDC - const usdcProxyAdmin = await deploymentManager.deploy('USDC:admin', 'vendor/proxy/transparent/ProxyAdmin.sol', []); - const usdcImpl = await deploymentManager.clone('USDC:implementation', clone.usdcImpl, []); - const usdcProxy = await deploymentManager.clone('USDC', clone.usdcProxy, [usdcImpl.address]); - const usdcProxyAdminSlot = '0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b'; - const USDC = usdcImpl.attach(usdcProxy.address); - - await deploymentManager.idempotent( - async () => !sameAddress(await ethers.provider.getStorageAt(usdcProxy.address, usdcProxyAdminSlot), usdcProxyAdmin.address), - async () => { - trace(`Changing admin of USDC proxy to ${usdcProxyAdmin.address}`); - trace(await wait(usdcProxy.connect(signer).changeAdmin(usdcProxyAdmin.address))); - - trace(`Initializing USDC`); - trace(await wait(USDC.connect(signer).initialize( - 'USD Coin', // name - 'USDC', // symbol - 'USD', // currency - 6, // decimals - signer.address, // Master Minter - signer.address, // Pauser - signer.address, // Blacklister - signer.address // Owner - ))); - } - ); - - const WBTC = await deploymentManager.clone('WBTC', clone.wbtc, []); - const WETH = await deploymentManager.clone( - 'WETH', - clone.weth, - [signer.address], - 'polygon' // NOTE: cloned from Polygon, not mainnet - ); - const WMATIC = await deploymentManager.clone( - 'WMATIC', - clone.wmatic, - [], - 'polygon' // NOTE: cloned from Polygon, not mainnet - ); - const DAI = await deploymentManager.clone('DAI', clone.dai, - [80001] // chain id - ); - - // Deploy Comet - const deployed = await deployComet( - deploymentManager, - deploySpec, - { - governor: localTimelock.address, - pauseGuardian: localTimelock.address - } - ); - - // Deploy Bulker - const bulker = await deploymentManager.deploy('bulker', 'bulkers/BaseBulker.sol', [ - localTimelock.address, - WMATIC.address - ]); - - // Deploy fauceteer - const fauceteer = await deploymentManager.deploy('fauceteer', 'test/Fauceteer.sol', []); - - return { - bridgeReceiver, - bulker, - fauceteer, - fxChild, - ...deployed - }; -} - -async function mintTokens(deploymentManager: DeploymentManager) { - const trace = deploymentManager.tracer(); - const signer = await deploymentManager.getSigner(); - const fauceteer = await deploymentManager.getContractOrThrow('fauceteer'); - - trace(`Attempting to mint as ${signer.address}...`); - - const WMATIC = await deploymentManager.getContractOrThrow('WMATIC'); - await deploymentManager.idempotent( - async () => (await WMATIC.balanceOf(signer.address)).lt(exp(0.01, 18)), - async () => { - trace(`Minting 0.01 WMATIC for signer (this is a precious resource!)`); - trace(await wait(WMATIC.connect(signer).deposit({ value: exp(0.01, 18) }))); - trace(`WMATIC.balanceOf(${signer.address}): ${await WMATIC.balanceOf(signer.address)}`); - } - ); - - const WETH = await deploymentManager.getContractOrThrow('WETH'); - await deploymentManager.idempotent( - async () => (await WETH.balanceOf(fauceteer.address)).eq(0), - async () => { - trace(`Minting 10_000 WETH to fauceteer`); - const amount = ethers.utils.defaultAbiCoder.encode( - ['uint256'], - [exp(10_000, await WETH.decimals())] - ); - trace(await wait(WETH.connect(signer).deposit(fauceteer.address, amount))); - trace(`WETH.balanceOf(${fauceteer.address}): ${await WETH.balanceOf(fauceteer.address)}`); - } - ); - - // If we haven't spidered new contracts (which we could before minting, but its slow), - // then the proxy contract won't have the impl functions yet, so just do it explicitly - const usdcProxy = await deploymentManager.getContractOrThrow('USDC'); - const usdcImpl = await deploymentManager.getContractOrThrow('USDC:implementation'); - const USDC = usdcImpl.attach(usdcProxy.address); - await deploymentManager.idempotent( - async () => (await USDC.balanceOf(fauceteer.address)).eq(0), - async () => { - trace(`Minting 100M USDC to fauceteer`); - const amount = exp(100_000_000, await USDC.decimals()); - trace(await wait(USDC.connect(signer).configureMinter(signer.address, amount))); - trace(await wait(USDC.connect(signer).mint(fauceteer.address, amount))); - trace(`USDC.balanceOf(${fauceteer.address}): ${await USDC.balanceOf(fauceteer.address)}`); - } - ); - - const WBTC = await deploymentManager.getContractOrThrow('WBTC'); - await deploymentManager.idempotent( - async () => (await WBTC.balanceOf(fauceteer.address)).eq(0), - async () => { - trace(`Minting 20 WBTC to fauceteer`); - const amount = exp(20, await WBTC.decimals()); - trace(await wait(WBTC.connect(signer).mint(fauceteer.address, amount))); - trace(`WBTC.balanceOf(${fauceteer.address}): ${await WBTC.balanceOf(fauceteer.address)}`); - } - ); - - const DAI = await deploymentManager.getContractOrThrow('DAI'); - await deploymentManager.idempotent( - async () => (await DAI.balanceOf(fauceteer.address)).eq(0), - async () => { - trace(`Minting 100M DAI to fauceteer`); - const amount = exp(100_000_000, await DAI.decimals()); - trace(await wait(DAI.connect(signer).mint(fauceteer.address, amount))); - trace(`DAI.balanceOf(${fauceteer.address}): ${await DAI.balanceOf(fauceteer.address)}`); - } - ); -} \ No newline at end of file diff --git a/deployments/mumbai/usdc/migrations/1676659582_configurate_and_ens.ts b/deployments/mumbai/usdc/migrations/1676659582_configurate_and_ens.ts deleted file mode 100644 index 4d64e0f11..000000000 --- a/deployments/mumbai/usdc/migrations/1676659582_configurate_and_ens.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { Contract } from 'ethers'; -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; -import { calldata, exp, getConfigurationStruct, proposal } from '../../../../src/deploy'; -import { expect } from 'chai'; -import {ERC20__factory} from '../../../../build/types'; - -const ENSName = 'compound-community-licenses.eth'; -const ENSResolverAddress = '0x19c2d5D0f035563344dBB7bE5fD09c8dad62b001'; -const ENSRegistryAddress = '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'; -const ENSSubdomainLabel = 'v3-additional-grants'; -const ENSSubdomain = `${ENSSubdomainLabel}.${ENSName}`; -const ENSTextRecordKey = 'v3-official-markets'; - -const ERC20PredicateAddress = '0xdD6596F2029e6233DEFfaCa316e6A95217d4Dc34'; -const RootChainManagerAddress = '0xBbD7cBFA79faee899Eaf900F13C9065bF03B1A74'; - -export default migration('1676659582_configurate_and_ens', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - const { utils } = ethers; - - const { - bridgeReceiver, - comet, - cometAdmin, - configurator, - rewards, - WBTC, - WETH, - WMATIC - } = await deploymentManager.getContracts(); - - const { - fxRoot, - timelock, - governor, - USDC, - COMP, - } = await govDeploymentManager.getContracts(); - - // ENS Setup - // See also: https://docs.ens.domains/contract-api-reference/name-processing - const ENSResolver = await govDeploymentManager.existing('ENSResolver', ENSResolverAddress, 'goerli'); - const nameHash = ethers.utils.namehash(ENSName); - const labelHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(ENSSubdomainLabel)); - const subdomainHash = ethers.utils.namehash(ENSSubdomain), ttl = 0; - const officialMarkets = { - 5: [ - { - baseSymbol: 'USDC', - cometAddress: (await govDeploymentManager.fromDep('cUSDCv3', 'goerli', 'usdc', 'comet')).address, - }, - { - baseSymbol: 'WETH', - cometAddress: (await govDeploymentManager.fromDep('cWETHv3', 'goerli', 'weth', 'comet')).address - } - ], - - 80001: [ - { - baseSymbol: 'USDC', - cometAddress: comet.address, - } - ], - }; - - const configuration = await getConfigurationStruct(deploymentManager); - - const setConfigurationCalldata = await calldata( - configurator.populateTransaction.setConfiguration(comet.address, configuration) - ); - 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], - [ - 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', - 'deployAndUpgradeTo(address,address)' - ], - [setConfigurationCalldata, deployAndUpgradeToCalldata] - ] - ); - - const RootChainManager = await deploymentManager.existing( - 'RootChainManager', - RootChainManagerAddress, - 'goerli' - ); - const USDCAmountToBridge = exp(500, 6); - const COMPAmountToBridge = exp(10_000, 18); - const depositUSDCData = utils.defaultAbiCoder.encode(['uint256'], [USDCAmountToBridge]); - const depositForUSDCCalldata = utils.defaultAbiCoder.encode( - ['address', 'address', 'bytes'], - [comet.address, USDC.address, depositUSDCData] - ); - const depositCOMPData = utils.defaultAbiCoder.encode(['uint256'], [COMPAmountToBridge]); - const depositForCOMPCCalldata = utils.defaultAbiCoder.encode( - ['address', 'address', 'bytes'], - [rewards.address, COMP.address, depositCOMPData] - ); - - const mainnetActions = [ - // 1. Set Comet configuration and deployAndUpgradeTo new Comet on Mumbai. - { - contract: fxRoot, - signature: 'sendMessageToChild(address,bytes)', - args: [bridgeReceiver.address, l2ProposalData] - }, - // 2. Approve Mumbai's ERC20Predicate to take Timelock's USDC (for bridging) - { - contract: USDC, - signature: 'approve(address,uint256)', - args: [ERC20PredicateAddress, USDCAmountToBridge] - }, - // 3. Bridge USDC from mainnet to Mumbai Comet using RootChainManager - { - target: RootChainManager.address, - signature: 'depositFor(address,address,bytes)', - calldata: depositForUSDCCalldata - }, - // Note: Cannot test this flow for COMP because Polygon team has changed the way to map new tokens in January 2023 - // to go through the FxPortal instead of the RootChainManager - // // 4. Approve Mumbai's ERC20Predicate to take Timelock's COMP (for bridging) - // { - // contract: COMP, - // signature: 'approve(address,uint256)', - // args: [ERC20PredicateAddress, COMPAmountToBridge] - // }, - // // 5. Bridge COMP from mainnet to Mumbai CometRewards using RootChainManager - // { - // target: RootChainManager.address, - // signature: 'depositFor(address,address,bytes)', - // calldata: depositForCOMPCCalldata - // }, - - // Note: No need to do this because we have already set up the subdomain on Goerli - // 6. Set up ENS license subdomain with the Timelock as the owner - // { - // target: ENSRegistryAddress, - // signature: 'setSubnodeRecord(bytes32,bytes32,address,address,uint64)', - // calldata: ethers.utils.defaultAbiCoder.encode( - // ['bytes32', 'bytes32', 'address', 'address', 'uint64'], - // [nameHash, labelHash, timelock.address, ENSResolverAddress, ttl] - // ) - // }, - - // 7. Establish the new list of official markets - { - target: ENSResolverAddress, - signature: 'setText(bytes32,string,string)', - calldata: ethers.utils.defaultAbiCoder.encode( - ['bytes32', 'string', 'string'], - [subdomainHash, ENSTextRecordKey, JSON.stringify(officialMarkets)] - ) - }, - ]; - - const description = "Configurate Mumbai cUSDCv3 market, bridge over USDC and COMP, and update ENS text record."; - 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, govDeploymentManager: DeploymentManager) { - const ethers = deploymentManager.hre.ethers; - - const { - comet, - rewards, - DAI, - WBTC, - WETH, - WMATIC - } = await deploymentManager.getContracts(); - - const { - timelock, - } = await govDeploymentManager.getContracts(); - - // 1. - const daiInfo = await comet.getAssetInfoByAddress(DAI.address); - const wbtcInfo = await comet.getAssetInfoByAddress(WBTC.address); - const wethInfo = await comet.getAssetInfoByAddress(WETH.address); - const wmaticInfo = await comet.getAssetInfoByAddress(WMATIC.address); - expect(await daiInfo.supplyCap).to.be.eq(exp(1_000_000, 18)); - expect(await wbtcInfo.supplyCap).to.be.eq(exp(20_000, 8)); - expect(await wethInfo.supplyCap).to.be.eq(exp(50_000, 18)); - expect(await wmaticInfo.supplyCap).to.be.eq(exp(500_000, 18)); - - // 2. & 3. - // Note: Cannot verify because the USDC we are bridging over is different from the one in Comet - // expect(await comet.getReserves()).to.be.equal(exp(400_000, 6)); - const bridgedUSDC = new Contract( - '0x0FA8781a83E46826621b3BC094Ea2A0212e71B23', - ERC20__factory.createInterface(), - deploymentManager.hre.ethers.provider - ); - expect(await bridgedUSDC.balanceOf(comet.address)).to.be.equal(exp(500, 6)); - - // 4. & 5. - // const bridgedCOMP = new Contract( - // '0x46DaBF9092B40A3fE6c0bC3331Cd928B600754fE', - // ERC20__factory.createInterface(), - // deploymentManager.hre.ethers.provider - // ); - // expect(await bridgedCOMP.balanceOf(rewards.address)).to.be.equal(exp(10_000, 18)); - - // 6. & 7. - const ENSResolver = await govDeploymentManager.existing('ENSResolver', ENSResolverAddress, 'goerli'); - const ENSRegistry = await govDeploymentManager.existing('ENSRegistry', ENSRegistryAddress, 'goerli'); - const nameHash = ethers.utils.namehash(ENSName); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const officialMarketsJSON = await ENSResolver.text(subdomainHash, ENSTextRecordKey); - const officialMarkets = JSON.parse(officialMarketsJSON); - expect(await ENSRegistry.recordExists(subdomainHash)).to.be.equal(true); - expect(await ENSRegistry.owner(subdomainHash)).to.be.equal(timelock.address); - expect(await ENSRegistry.resolver(subdomainHash)).to.be.equal(ENSResolverAddress); - expect(await ENSRegistry.ttl(subdomainHash)).to.be.equal(0); - expect(officialMarkets).to.deep.equal({ - 5: [ - { - baseSymbol: 'USDC', - cometAddress: '0x3EE77595A8459e93C2888b13aDB354017B198188', - }, - { - baseSymbol: 'WETH', - cometAddress: '0x9A539EEc489AAA03D588212a164d0abdB5F08F5F', - }, - ], - - 80001: [ - { - baseSymbol: 'USDC', - cometAddress: comet.address, - }, - ] - }); - } -}); \ No newline at end of file diff --git a/deployments/mumbai/usdc/relations.ts b/deployments/mumbai/usdc/relations.ts deleted file mode 100644 index 9e27b0b01..000000000 --- a/deployments/mumbai/usdc/relations.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { RelationConfigMap } from '../../../plugins/deployment_manager/RelationConfig'; -import baseRelationConfig from '../../relations'; - -export default { - ...baseRelationConfig, - 'governor': { - artifact: 'contracts/bridges/polygon/PolygonBridgeReceiver.sol:PolygonBridgeReceiver', - } -}; \ No newline at end of file diff --git a/deployments/mumbai/usdc/roots.json b/deployments/mumbai/usdc/roots.json deleted file mode 100644 index 3947f3f3a..000000000 --- a/deployments/mumbai/usdc/roots.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bridgeReceiver": "0xe195d2cBf7f20E40Cf701a9fA3F01fE89bA5a1da", - "fauceteer": "0x1Cea3a83BA17692cEa8DB37D72446f014480F3bE", - "fxChild": "0xCf73231F28B7331BBe3124B907840A94851f9f11", - "comet": "0xF09F0369aB0a875254fB565E52226c88f10Bc839", - "configurator": "0x64550801B8bf3BF4D8792d46D8903F82e2EC95A9", - "rewards": "0x0785f2AC0dCBEDEE4b8D62c25A34098E9A0dF4bB", - "bulker": "0x990D086E52B132f5b4f769829612F756a4a20bb8" -} \ No newline at end of file diff --git a/deployments/optimism/usdc/relations.ts b/deployments/optimism/usdc/relations.ts index 7ef784489..179b7dff3 100644 --- a/deployments/optimism/usdc/relations.ts +++ b/deployments/optimism/usdc/relations.ts @@ -33,4 +33,13 @@ export default { } } }, + + ERC1967Proxy: { + artifact: 'contracts/ERC20.sol:ERC20', + delegates: { + field: { + slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' + } + } + }, }; diff --git a/deployments/relations.ts b/deployments/relations.ts index f0ea7c6ca..1655c90c6 100644 --- a/deployments/relations.ts +++ b/deployments/relations.ts @@ -31,7 +31,14 @@ const relationConfigMap: RelationConfigMap = { }) ); }, - alias: async (token) => token.symbol(), + alias: async (token) => { + try { + return token.symbol(); + } + catch (e) { + throw new Error(`Failed to get symbol for token ${token.address}`); + } + }, }, assetPriceFeeds: { field: async (comet) => { diff --git a/deployments/scroll-goerli/usdc/configuration.json b/deployments/scroll-goerli/usdc/configuration.json deleted file mode 100644 index 8d370324f..000000000 --- a/deployments/scroll-goerli/usdc/configuration.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "Compound USDC", - "symbol": "cUSDCv3", - "baseToken": "USDC", - "baseTokenAddress": "0x67aE69Fd63b4fc8809ADc224A9b82Be976039509", - "baseTokenPriceFeed": "0xbbb06bDcf221Ae565f458b990DE83Cbb3D27C2aA", - "borrowMin": "0.001e6", - "storeFrontPriceFactor": 0.5, - "targetReserves": "1000000e6", - "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.000402083333333e15", - "baseBorrowSpeed": "0.000402083333333e15", - "baseMinForRewards": "1000e6" - }, - "assets": { - "WETH": { - "address": "0xa1EA0B2354F5A344110af2b6AD68e75545009a03", - "priceFeed": "0x2287BAF672879935cB944a2C050971515E73da65", - "decimals": "18", - "borrowCF": 0.775, - "liquidateCF": 0.825, - "liquidationFactor": 0.95, - "supplyCap": "10000000e18" - } - } -} diff --git a/deployments/scroll-goerli/usdc/deploy.ts b/deployments/scroll-goerli/usdc/deploy.ts deleted file mode 100644 index 93fb99f9b..000000000 --- a/deployments/scroll-goerli/usdc/deploy.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; -import { DeploySpec, deployComet, exp, wait } from '../../../src/deploy'; - -const secondsPerDay = 24 * 60 * 60; - -const GOERLI_TIMELOCK = '0x8Fa336EB4bF58Cfc508dEA1B0aeC7336f55B1399'; // L1 contract - -export default async function deploy( - deploymentManager: DeploymentManager, - deploySpec: DeploySpec -): Promise { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - - // Pull in existing assets - const WETH = await deploymentManager.existing( - 'WETH', - '0xa1EA0B2354F5A344110af2b6AD68e75545009a03', - 'scroll-goerli' - ); - - const l2Messenger = await deploymentManager.existing( - 'l2Messenger', - '0xb75d7e84517e1504C151B270255B087Fd746D34C', - 'scroll-goerli' - ); - - const l2ERC20Gateway = await deploymentManager.existing( - 'l2ERC20Gateway', - '0xB878F37BB278bf0e4974856fFe86f5e6F66BD725', - 'scroll-goerli' - ); - - const l2ETHGateway = await deploymentManager.existing( - 'l2ETHGateway', - '0x32139B5C8838E94fFcD83E60dff95Daa7F0bA14c', - 'scroll-goerli' - ); - - const l2WETHGateway = await deploymentManager.existing( - 'l2WETHGateway', - '0xBb88bF582F2BBa46702621dae5CB9271057bC85b', - 'scroll-goerli' - ); - - // Deploy ScrollBridgeReceiver - const bridgeReceiver = await deploymentManager.deploy( - 'bridgeReceiver', - 'bridges/scroll/ScrollBridgeReceiver.sol', - [l2Messenger.address] - ); - - // Deploy Local Timelock - const localTimelock = await deploymentManager.deploy('timelock', 'vendor/Timelock.sol', [ - bridgeReceiver.address, // admin - 10 * 60, // delay - 14 * secondsPerDay, // grace period - 10 * 60, // minimum delay - 30 * secondsPerDay // maximum delay - ]); - - // Initialize BridgeReceiver - await deploymentManager.idempotent( - async () => !(await bridgeReceiver.initialized()), - async () => { - trace(`Initializing BridgeReceiver`); - await bridgeReceiver.initialize( - GOERLI_TIMELOCK, // govTimelock - localTimelock.address // localTimelock - ); - trace(`BridgeReceiver initialized`); - } - ); - - // Deploy Comet - const deployed = await deployComet(deploymentManager, deploySpec); - const { comet } = deployed; - - // Deploy Bulker - const bulker = await deploymentManager.deploy('bulker', 'bulkers/BaseBulker.sol', [ - await comet.governor(), // admin - WETH.address // weth - ]); - - // Deploy fauceteer - const fauceteer = await deploymentManager.deploy('fauceteer', 'test/Fauceteer.sol', []); - - return { - ...deployed, - bridgeReceiver, - l2Messenger, - l2ERC20Gateway, - l2ETHGateway, - l2WETHGateway, - bulker, - fauceteer, - }; -} diff --git a/deployments/scroll-goerli/usdc/migrations/1694594095_configurate_and_ens.ts b/deployments/scroll-goerli/usdc/migrations/1694594095_configurate_and_ens.ts deleted file mode 100644 index 33e2fdfb3..000000000 --- a/deployments/scroll-goerli/usdc/migrations/1694594095_configurate_and_ens.ts +++ /dev/null @@ -1,229 +0,0 @@ -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { diffState, getCometConfig } from '../../../../plugins/deployment_manager/DiffState'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; -import { calldata, exp, getConfigurationStruct, proposal } from '../../../../src/deploy'; -import { expect } from 'chai'; - -const ENSName = 'compound-community-licenses.eth'; -const ENSResolverAddress = '0x19c2d5D0f035563344dBB7bE5fD09c8dad62b001'; -const ENSSubdomainLabel = 'v3-additional-grants'; -const ENSSubdomain = `${ENSSubdomainLabel}.${ENSName}`; -const ENSTextRecordKey = 'v3-official-markets'; -const scrollCOMPAddress = '0xE90a006650cda1F8390f95f45132B36bA9038bdF'; -const scrollL1StandardERC20GatewayAddress = "0xeF37207c1A1efF6D6a9d7BfF3cF4270e406d319b" - -export default migration('1694594095_configurate_and_ens', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager) => { - const trace = deploymentManager.tracer(); - const ethers = deploymentManager.hre.ethers; - const { utils } = ethers; - - const { - bridgeReceiver, - comet, - cometAdmin, - configurator, - rewards - } = await deploymentManager.getContracts(); - - const { - scrollMessenger, - scrollL1TokenBridge, - governor, - COMP, - } = await govDeploymentManager.getContracts(); - - // ENS Setup - // See also: https://docs.ens.domains/contract-api-reference/name-processing - const ENSResolver = await govDeploymentManager.existing( - 'ENSResolver', - ENSResolverAddress, - 'goerli' - ); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const scrollGoerliChainId = ( - await deploymentManager.hre.ethers.provider.getNetwork() - ).chainId.toString(); - const newMarketObject = { baseSymbol: 'USDC', cometAddress: comet.address }; - const officialMarketsJSON = JSON.parse(await ENSResolver.text(subdomainHash, ENSTextRecordKey)); - if (officialMarketsJSON[scrollGoerliChainId]) { - officialMarketsJSON[scrollGoerliChainId].push(newMarketObject); - } else { - officialMarketsJSON[scrollGoerliChainId] = [newMarketObject]; - } - - const configuration = await getConfigurationStruct(deploymentManager); - - const setConfigurationCalldata = await calldata( - configurator.populateTransaction.setConfiguration(comet.address, configuration) - ); - const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [configurator.address, comet.address] - ); - const setRewardConfigCalldata = utils.defaultAbiCoder.encode( - ['address', 'address'], - [comet.address, scrollCOMPAddress] - ); - const l2ProposalData = utils.defaultAbiCoder.encode( - ['address[]', 'uint256[]', 'string[]', 'bytes[]'], - [ - [configurator.address, cometAdmin.address, rewards.address], - [0, 0, 0], - [ - 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', - 'deployAndUpgradeTo(address,address)', - 'setRewardConfig(address,address)' - ], - [setConfigurationCalldata, deployAndUpgradeToCalldata, setRewardConfigCalldata] - ] - ); - - const COMPAmountToBridge = exp(10_000, 18); - - const goerliActions = [ - // 1. Set Comet configuration + deployAndUpgradeTo new Comet and set reward config on Scroll Alpha. - { - contract: scrollMessenger, - signature: 'sendMessage(address,uint256,bytes,uint256)', - args: [bridgeReceiver.address, 0, l2ProposalData, 600_000] - }, - - // 2. Approve Goerli's StandardERC20Gateway to take Timelock's COMP (for bridging) - { - contract: COMP, - signature: 'approve(address,uint256)', - args: [scrollL1StandardERC20GatewayAddress, COMPAmountToBridge] - }, - // 3. Bridge COMP from Goerli to Scroll Alpha Comet using L1GatewayRouter - { - contract: scrollL1TokenBridge, - signature: 'depositERC20(address,address,uint256,uint256)', - args: [COMP.address, rewards.address, COMPAmountToBridge, 300_000] - }, - // 4. Update the list of official markets - { - target: ENSResolverAddress, - signature: 'setText(bytes32,string,string)', - calldata: ethers.utils.defaultAbiCoder.encode( - ['bytes32', 'string', 'string'], - [subdomainHash, ENSTextRecordKey, JSON.stringify(officialMarketsJSON)] - ) - } - ]; - - const description = - '# Configurate Scroll Alpha cUSDCv3 market, set reward config, bridge over USDC and COMP, and update ENS text record.'; - const txn = await govDeploymentManager.retry(async () => - trace(await governor.propose(...(await proposal(goerliActions, 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, - govDeploymentManager: DeploymentManager, - preMigrationBlockNumber: number - ) { - const ethers = deploymentManager.hre.ethers; - await deploymentManager.spider(); // We spider here to pull in Scroll COMP now that reward config has been set - - const { comet, rewards, COMP, USDC } = await deploymentManager.getContracts(); - - // 1. - const stateChanges = await diffState(comet, getCometConfig, preMigrationBlockNumber); - expect(stateChanges).to.deep.equal({ - baseTrackingSupplySpeed: exp(34.74 / 86400, 15, 18), - baseTrackingBorrowSpeed: exp(34.74 / 86400, 15, 18), - baseMinForRewards: exp(1000, 6), - WETH: { - borrowCollateralFactor: exp(0.775, 18), - liquidationFactor: exp(0.95, 18), - supplyCap: exp(1000, 18) - }, - }); - - const config = await rewards.rewardConfig(comet.address); - expect(config.token).to.be.equal(COMP.address); - expect(config.rescaleFactor).to.be.equal(exp(1, 12)); - expect(config.shouldUpscale).to.be.equal(true); - - // 2. & 3. - expect(await COMP.balanceOf(rewards.address)).to.be.equal(exp(1_000, 18)); - - // 4 - const ENSResolver = await govDeploymentManager.existing( - 'ENSResolver', - ENSResolverAddress, - 'goerli' - ); - const subdomainHash = ethers.utils.namehash(ENSSubdomain); - const officialMarketsJSON = await ENSResolver.text(subdomainHash, ENSTextRecordKey); - const officialMarkets = JSON.parse(officialMarketsJSON); - expect(officialMarkets).to.deep.equal({ - 5: [ - { - baseSymbol: 'USDC', - cometAddress: '0x3EE77595A8459e93C2888b13aDB354017B198188' - }, - { - baseSymbol: 'WETH', - cometAddress: '0x9A539EEc489AAA03D588212a164d0abdB5F08F5F' - } - ], - 80001: [ - { - baseSymbol: 'USDC', - cometAddress: '0xF09F0369aB0a875254fB565E52226c88f10Bc839' - } - ], - 420: [ - { - baseSymbol: 'USDC', - cometAddress: '0xb8F2f9C84ceD7bBCcc1Db6FB7bb1F19A9a4adfF4' - } - ], - 421613: [ - { - baseSymbol: 'USDC', - cometAddress: '0x1d573274E19174260c5aCE3f2251598959d24456' - } - ], - 84531: [ - { - baseSymbol: 'USDC', - cometAddress: '0xe78Fc55c884704F9485EDa042fb91BfE16fD55c1' - }, - { - baseSymbol: 'WETH', - cometAddress: '0xED94f3052638620fE226a9661ead6a39C2a265bE' - } - ], - 59140: [ - { - baseSymbol: 'USDC', - cometAddress: "0xa84b24A43ba1890A165f94Ad13d0196E5fD1023a" - } - ], - 534353: [ - { - baseSymbol: 'USDC', - cometAddress: comet.address - } - ] - }); - } - -}); diff --git a/deployments/scroll-goerli/usdc/relations.ts b/deployments/scroll-goerli/usdc/relations.ts deleted file mode 100644 index 767191e98..000000000 --- a/deployments/scroll-goerli/usdc/relations.ts +++ /dev/null @@ -1,42 +0,0 @@ -import baseRelationConfig from '../../relations'; - -export default { - ...baseRelationConfig, - governor: { - artifact: 'contracts/bridges/scroll/ScrollBridgeReceiver.sol:ScrollBridgeReceiver' - }, - l2Messenger: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - l2ERC20Gateway: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - l2ETHGateway: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - l2WETHGateway: { - delegates: { - field: { - slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - } - } - }, - '0x477df03cb8c83ec241df01302a9d13102676eee4': { - artifact: 'contracts/Configurator.sol:Configurator', - }, - '0x3effaacd82fa5a76d539b7d9cee0250f972f115f': { - artifact: 'contracts/CometFactory.sol:CometFactory', - } -}; diff --git a/deployments/scroll-goerli/usdc/roots.json b/deployments/scroll-goerli/usdc/roots.json deleted file mode 100644 index cf9aee3fd..000000000 --- a/deployments/scroll-goerli/usdc/roots.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "comet": "0x149B7023781d1D37689d447A565a1bf5854a8e3d", - "configurator": "0x6f5010E26581DC625802005EC82b30067460610a", - "rewards": "0xB2dbE5c648D8B4329499af8929Ee1d81b577ed5E", - "bridgeReceiver": "0x1ad7e375CF875bf9145fFa511d9D3c3A0d9DD0f8", - "l2Messenger": "0xb75d7e84517e1504C151B270255B087Fd746D34C", - "l2ERC20Gateway": "0xB878F37BB278bf0e4974856fFe86f5e6F66BD725", - "l2ETHGateway": "0x32139B5C8838E94fFcD83E60dff95Daa7F0bA14c", - "l2WETHGateway": "0xBb88bF582F2BBa46702621dae5CB9271057bC85b", - "bulker": "0x055FFa809c8817A1a0967B40027e48856C9D7945", - "fauceteer": "0x4a499858975e824f4ee2B95633B6B975Ab6d029E" -} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 2e474d544..86661713e 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -18,11 +18,8 @@ import './tasks/scenario/task.ts'; // Relation Config import relationConfigMap from './deployments/relations'; -import goerliRelationConfigMap from './deployments/goerli/usdc/relations'; -import goerliWethRelationConfigMap from './deployments/goerli/weth/relations'; import sepoliaUsdcRelationConfigMap from './deployments/sepolia/usdc/relations'; import sepoliaWethRelationConfigMap from './deployments/sepolia/weth/relations'; -import mumbaiRelationConfigMap from './deployments/mumbai/usdc/relations'; import mainnetRelationConfigMap from './deployments/mainnet/usdc/relations'; import mainnetWethRelationConfigMap from './deployments/mainnet/weth/relations'; import mainnetUsdtRelationConfigMap from './deployments/mainnet/usdt/relations'; @@ -33,21 +30,15 @@ import polygonUsdtRelationConfigMap from './deployments/polygon/usdt/relations'; import arbitrumBridgedUsdcRelationConfigMap from './deployments/arbitrum/usdc.e/relations'; import arbitrumNativeUsdcRelationConfigMap from './deployments/arbitrum/usdc/relations'; import arbitrumWETHRelationConfigMap from './deployments/arbitrum/weth/relations'; -import arbitrumBridgedUsdcGoerliRelationConfigMap from './deployments/arbitrum-goerli/usdc.e/relations'; -import arbitrumGoerliNativeUsdcRelationConfigMap from './deployments/arbitrum-goerli/usdc/relations'; import arbitrumUsdtRelationConfigMap from './deployments/arbitrum/usdt/relations'; import baseUsdbcRelationConfigMap from './deployments/base/usdbc/relations'; import baseWethRelationConfigMap from './deployments/base/weth/relations'; import baseUsdcRelationConfigMap from './deployments/base/usdc/relations'; import baseAeroRelationConfigMap from './deployments/base/aero/relations'; -import baseGoerliRelationConfigMap from './deployments/base-goerli/usdc/relations'; -import baseGoerliWethRelationConfigMap from './deployments/base-goerli/weth/relations'; -import lineaGoerliRelationConfigMap from './deployments/linea-goerli/usdc/relations'; import optimismRelationConfigMap from './deployments/optimism/usdc/relations'; import optimismUsdtRelationConfigMap from './deployments/optimism/usdt/relations'; import optimismWethRelationConfigMap from './deployments/optimism/weth/relations'; import mantleRelationConfigMap from './deployments/mantle/usde/relations'; -import scrollGoerliRelationConfigMap from './deployments/scroll-goerli/usdc/relations'; import scrollRelationConfigMap from './deployments/scroll/usdc/relations'; task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => { @@ -63,7 +54,6 @@ const { POLYGONSCAN_KEY, ARBISCAN_KEY, BASESCAN_KEY, - LINEASCAN_KEY, OPTIMISMSCAN_KEY, MANTLESCAN_KEY, INFURA_KEY, @@ -125,7 +115,7 @@ const networkConfigs: NetworkConfig[] = [ { network: 'polygon', chainId: 137, - url: `https://polygon-mainnet.infura.io/v3/${INFURA_KEY}`, + url: `https://rpc.ankr.com/polygon/${ANKR_KEY}`, }, { network: 'optimism', @@ -136,7 +126,7 @@ const networkConfigs: NetworkConfig[] = [ network: 'mantle', chainId: 5000, // link for scenarios - url: `https://mantle-mainnet.infura.io/v3/${INFURA_KEY}`, + url: `https://rpc.ankr.com/mantle/${ANKR_KEY}`, // link for deployment // url: `https://rpc.mantle.xyz`, }, @@ -148,7 +138,7 @@ const networkConfigs: NetworkConfig[] = [ { network: 'arbitrum', chainId: 42161, - url: `https://arbitrum-mainnet.infura.io/v3/${INFURA_KEY}`, + url: `https://rpc.ankr.com/arbitrum/${ANKR_KEY}`, }, { network: 'avalanche', @@ -160,31 +150,6 @@ const networkConfigs: NetworkConfig[] = [ chainId: 43113, url: 'https://api.avax-test.network/ext/bc/C/rpc', }, - { - network: 'mumbai', - chainId: 80001, - url: `https://polygon-mumbai.infura.io/v3/${INFURA_KEY}`, - }, - { - network: 'arbitrum-goerli', - chainId: 421613, - url: `https://arbitrum-goerli.infura.io/v3/${INFURA_KEY}`, - }, - { - network: 'base-goerli', - chainId: 84531, - url: `https://goerli.base.org/`, - }, - { - network: 'linea-goerli', - chainId: 59140, - url: `https://linea-goerli.infura.io/v3/${INFURA_KEY}`, - }, - { - network: 'scroll-goerli', - chainId: 534353, - url: 'https://alpha-rpc.scroll.io/l2', - }, { network: 'scroll', chainId: 534352, @@ -262,30 +227,22 @@ const config: HardhatUserConfig = { mainnet: ETHERSCAN_KEY, ropsten: ETHERSCAN_KEY, rinkeby: ETHERSCAN_KEY, - goerli: ETHERSCAN_KEY, sepolia: ETHERSCAN_KEY, // Avalanche avalanche: SNOWTRACE_KEY, avalancheFujiTestnet: SNOWTRACE_KEY, // Polygon polygon: POLYGONSCAN_KEY, - polygonMumbai: POLYGONSCAN_KEY, // Arbitrum arbitrumOne: ARBISCAN_KEY, arbitrumTestnet: ARBISCAN_KEY, arbitrum: ARBISCAN_KEY, - 'arbitrum-goerli': ARBISCAN_KEY, // Base base: BASESCAN_KEY, - 'base-goerli': BASESCAN_KEY, - // Linea - 'linea-goerli': LINEASCAN_KEY, // optimism: OPTIMISMSCAN_KEY, optimisticEthereum: OPTIMISMSCAN_KEY, // Mantle mantle: MANTLESCAN_KEY, - // Scroll Testnet - 'scroll-goerli': ETHERSCAN_KEY, // Scroll 'scroll': ETHERSCAN_KEY, }, @@ -299,15 +256,6 @@ const config: HardhatUserConfig = { browserURL: 'https://arbiscan.io/' } }, - { - // Hardhat's Etherscan plugin calls the network `arbitrumGoerli`, so we need to add an entry for our own network name - network: 'arbitrum-goerli', - chainId: 421613, - urls: { - apiURL: 'https://api-goerli.arbiscan.io/api', - browserURL: 'https://goerli.arbiscan.io/' - } - }, { // Hardhat's Etherscan plugin doesn't have support Base, so we need to add an entry for our own network name network: 'base', @@ -317,31 +265,6 @@ const config: HardhatUserConfig = { browserURL: 'https://basescan.org/' } }, - { - // Hardhat's Etherscan plugin calls the network `baseGoerli`, so we need to add an entry for our own network name - network: 'base-goerli', - chainId: 84531, - urls: { - apiURL: 'https://api-goerli.basescan.org/api', - browserURL: 'https://goerli.basescan.org/' - } - }, - { - network: 'linea-goerli', - chainId: 59140, - urls: { - apiURL: 'https://api-goerli.lineascan.build/api', - browserURL: 'https://goerli.lineascan.build/' - } - }, - { - network: 'scroll-goerli', - chainId: 534353, - urls: { - apiURL: 'https://alpha-blockscout.scroll.io/api', - browserURL: 'https://alpha-blockscout.scroll.io/' - } - }, { network: 'scroll', chainId: 534352, @@ -374,17 +297,10 @@ const config: HardhatUserConfig = { deploymentManager: { relationConfigMap, networks: { - goerli: { - usdc: goerliRelationConfigMap, - weth: goerliWethRelationConfigMap - }, sepolia: { usdc: sepoliaUsdcRelationConfigMap, weth: sepoliaWethRelationConfigMap }, - mumbai: { - usdc: mumbaiRelationConfigMap - }, mainnet: { usdc: mainnetRelationConfigMap, weth: mainnetWethRelationConfigMap, @@ -402,23 +318,12 @@ const config: HardhatUserConfig = { usdt: arbitrumUsdtRelationConfigMap, weth: arbitrumWETHRelationConfigMap }, - 'arbitrum-goerli': { - 'usdc.e': arbitrumBridgedUsdcGoerliRelationConfigMap, - usdc: arbitrumGoerliNativeUsdcRelationConfigMap - }, 'base': { usdbc: baseUsdbcRelationConfigMap, weth: baseWethRelationConfigMap, usdc: baseUsdcRelationConfigMap, aero: baseAeroRelationConfigMap }, - 'base-goerli': { - usdc: baseGoerliRelationConfigMap, - weth: baseGoerliWethRelationConfigMap - }, - 'linea-goerli': { - usdc: lineaGoerliRelationConfigMap - }, optimism: { usdc: optimismRelationConfigMap, usdt: optimismUsdtRelationConfigMap, @@ -427,9 +332,6 @@ const config: HardhatUserConfig = { 'mantle': { 'usde': mantleRelationConfigMap }, - 'scroll-goerli': { - usdc: scrollGoerliRelationConfigMap - }, 'scroll': { usdc: scrollRelationConfigMap } @@ -474,16 +376,6 @@ const config: HardhatUserConfig = { network: 'fuji', deployment: 'usdc' }, - { - name: 'goerli', - network: 'goerli', - deployment: 'usdc' - }, - { - name: 'goerli-weth', - network: 'goerli', - deployment: 'weth', - }, { name: 'sepolia-usdc', network: 'sepolia', @@ -494,12 +386,6 @@ const config: HardhatUserConfig = { network: 'sepolia', deployment: 'weth' }, - { - name: 'mumbai', - network: 'mumbai', - deployment: 'usdc', - auxiliaryBase: 'goerli' - }, { name: 'polygon', network: 'polygon', @@ -536,18 +422,6 @@ const config: HardhatUserConfig = { deployment: 'weth', auxiliaryBase: 'mainnet' }, - { - name: 'arbitrum-goerli-usdc.e', - network: 'arbitrum-goerli', - deployment: 'usdc.e', - auxiliaryBase: 'goerli' - }, - { - name: 'arbitrum-goerli-usdc', - network: 'arbitrum-goerli', - deployment: 'usdc', - auxiliaryBase: 'goerli' - }, { name: 'base-usdbc', network: 'base', @@ -572,24 +446,6 @@ const config: HardhatUserConfig = { deployment: 'aero', auxiliaryBase: 'mainnet' }, - { - name: 'base-goerli', - network: 'base-goerli', - deployment: 'usdc', - auxiliaryBase: 'goerli' - }, - { - name: 'base-goerli-weth', - network: 'base-goerli', - deployment: 'weth', - auxiliaryBase: 'goerli' - }, - { - name: 'linea-goerli', - network: 'linea-goerli', - deployment: 'usdc', - auxiliaryBase: 'goerli' - }, { name: 'optimism-usdc', network: 'optimism', @@ -614,12 +470,6 @@ const config: HardhatUserConfig = { deployment: 'usde', auxiliaryBase: 'mainnet' }, - { - name: 'scroll-goerli', - network: 'scroll-goerli', - deployment: 'usdc', - auxiliaryBase: 'goerli' - }, { name: 'scroll-usdc', network: 'scroll', diff --git a/plugins/deployment_manager/test/VerifyTest.ts b/plugins/deployment_manager/test/VerifyTest.ts index e2e48f0c6..2c63e3937 100644 --- a/plugins/deployment_manager/test/VerifyTest.ts +++ b/plugins/deployment_manager/test/VerifyTest.ts @@ -16,12 +16,12 @@ export function mockVerifySuccess(hre: HardhatRuntimeEnvironment) { let solcList = JSON.parse(fs.readFileSync(path.join(__dirname, './SolcList.json'), 'utf8')); - // Note: we need to convince the prober task that this is goerli, which it's not. + // Note: we need to convince the prober task that this is sepolia, which it's not. // So we'll fake the network name and the chain ID hre.config.etherscan.apiKey = { - goerli: 'GOERLI_KEY', + sepolia: 'SEPOLIA_KEY', }; - hre.network.name = 'goerli'; + hre.network.name = 'sepolia'; let sendOld = hre.network.provider.send.bind(hre.network.provider); hre.network.provider.send = function (...args) { if (args.length === 1 && args[0] === 'eth_chainId') { @@ -32,7 +32,7 @@ export function mockVerifySuccess(hre: HardhatRuntimeEnvironment) { }; const solcMockPool = mockAgent.get('https://solc-bin.ethereum.org'); - const etherscanMockPool = mockAgent.get('https://api-goerli.etherscan.io'); + const etherscanMockPool = mockAgent.get('https://api-sepolia.etherscan.io'); solcMockPool.intercept({ path: '/bin/list.json', @@ -53,7 +53,7 @@ export function mockVerifySuccess(hre: HardhatRuntimeEnvironment) { path: '/api', method: 'GET', query: { - apikey: 'GOERLI_KEY', + apikey: 'SEPOLIA_KEY', module: 'contract', action: 'checkverifystatus', guid: 'MYGUID', diff --git a/plugins/import/etherscan.ts b/plugins/import/etherscan.ts index 332c7fe2c..c770ff1a1 100644 --- a/plugins/import/etherscan.ts +++ b/plugins/import/etherscan.ts @@ -10,21 +10,15 @@ export function getEtherscanApiUrl(network: string): string { let host = { rinkeby: 'api-rinkeby.etherscan.io', ropsten: 'api-ropsten.etherscan.io', - goerli: 'api-goerli.etherscan.io', sepolia: 'api-sepolia.etherscan.io', mainnet: 'api.etherscan.io', fuji: 'api-testnet.snowtrace.io', avalanche: 'api.snowtrace.io', - mumbai: 'api-mumbai.polygonscan.com', polygon: 'api.polygonscan.com', arbitrum: 'api.arbiscan.io', - 'arbitrum-goerli': 'api-goerli.arbiscan.io', base: 'api.basescan.org', - 'base-goerli': 'api-goerli.basescan.org', - 'linea-goerli': 'api-goerli.lineascan.build', optimism: 'api-optimistic.etherscan.io', mantle: 'api.mantlescan.xyz', - 'scroll-goerli': 'alpha-blockscout.scroll.io', scroll: 'api.scrollscan.com' }[network]; @@ -39,21 +33,15 @@ export function getEtherscanUrl(network: string): string { let host = { rinkeby: 'rinkeby.etherscan.io', ropsten: 'ropsten.etherscan.io', - goerli: 'goerli.etherscan.io', sepolia: 'sepolia.etherscan.io', mainnet: 'etherscan.io', fuji: 'testnet.snowtrace.io', avalanche: 'snowtrace.io', - mumbai: 'mumbai.polygonscan.com', polygon: 'polygonscan.com', arbitrum: 'arbiscan.io', - 'arbitrum-goerli': 'goerli.arbiscan.io', base: 'basescan.org', - 'base-goerli': 'goerli.basescan.org', - 'linea-goerli': 'goerli.lineascan.build', optimism: 'optimistic.etherscan.io', mantle: 'mantlescan.xyz', - 'scroll-goerli': 'alpha-blockscout.scroll.io', scroll: 'scrollscan.com' }[network]; @@ -68,21 +56,15 @@ export function getEtherscanApiKey(network: string): string { let apiKey = { rinkeby: process.env.ETHERSCAN_KEY, ropsten: process.env.ETHERSCAN_KEY, - goerli: process.env.ETHERSCAN_KEY, sepolia: process.env.ETHERSCAN_KEY, mainnet: process.env.ETHERSCAN_KEY, fuji: process.env.SNOWTRACE_KEY, avalanche: process.env.SNOWTRACE_KEY, - mumbai: process.env.POLYGONSCAN_KEY, polygon: process.env.POLYGONSCAN_KEY, arbitrum: process.env.ARBISCAN_KEY, - 'arbitrum-goerli': process.env.ARBISCAN_KEY, base: process.env.BASESCAN_KEY, - 'base-goerli': process.env.BASESCAN_KEY, - 'linea-goerli': process.env.LINEASCAN_KEY, optimism: process.env.OPTIMISMSCAN_KEY, mantle: process.env.MANTLESCAN_KEY, - 'scroll-goerli': process.env.ETHERSCAN_KEY, scroll: process.env.ETHERSCAN_KEY }[network]; diff --git a/plugins/scenario/utils/hreForBase.ts b/plugins/scenario/utils/hreForBase.ts index 454af84e3..f7dd53b7d 100644 --- a/plugins/scenario/utils/hreForBase.ts +++ b/plugins/scenario/utils/hreForBase.ts @@ -77,7 +77,7 @@ export async function forkedHreForBase(base: ForkSpec): Promise { const comet = await ctx.getComet(); @@ -22,15 +23,23 @@ async function hasNativeAsCollateralOrBase(ctx: CometContext): Promise scenario( 'Comet#bulker > (non-WETH base) all non-reward actions in one txn', { - filter: async (ctx) => await isBulkerSupported(ctx) && !matchesDeployment(ctx, [{ deployment: 'weth' }, { deployment: 'wsteth' }, { network: 'mumbai' }, { network: 'linea-goerli' }]), - supplyCaps: { - $asset0: 5000, - $asset1: 5000, - }, - tokenBalances: { - albert: { $base: '== 0', $asset0: 5000, $asset1: 5000 }, - $comet: { $base: 5000 }, - }, + filter: async (ctx) => await isBulkerSupported(ctx) && !matchesDeployment(ctx, [{ deployment: 'weth' }, { deployment: 'wsteth' }]), + supplyCaps: async (ctx) => ( + { + $asset0: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset, + } + ), + tokenBalances: async (ctx) => ( + { + albert: { + $base: '== 0', + $asset0: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset + }, + $comet: { $base: getConfigForScenario(ctx).bulkerComet }, + } + ), }, async ({ comet, actors, bulker }, context) => { const { albert, betty } = actors; @@ -44,9 +53,9 @@ scenario( const { asset: collateralAssetAddress, scale: scaleBN } = asset0 === wrappedNativeToken ? { asset: asset1, scale: scale1 } : { asset: asset0, scale: scale0 }; const collateralAsset = context.getAssetByAddress(collateralAssetAddress); const collateralScale = scaleBN.toBigInt(); - const toSupplyCollateral = 5000n * collateralScale; - const toBorrowBase = 1000n * baseScale; - const toTransferBase = 500n * baseScale; + const toSupplyCollateral = BigInt(getConfigForScenario(context).bulkerAsset) * collateralScale; + const toBorrowBase = BigInt(getConfigForScenario(context).bulkerBorrowBase) * baseScale; + const toTransferBase = BigInt(getConfigForScenario(context).bulkerBorrowAsset) * baseScale; const toSupplyEth = exp(0.01, 18); const toWithdrawEth = exp(0.005, 18); @@ -107,15 +116,23 @@ scenario( scenario( 'Comet#bulker > (wstETH base) all non-reward actions in one txn', { - filter: async (ctx) => await isBulkerSupported(ctx) && !matchesDeployment(ctx, [{ deployment: 'weth' }, { network: 'mumbai' }, { network: 'linea-goerli' }]), - supplyCaps: { - $asset0: 5000, - $asset1: 5000, - }, - tokenBalances: { - albert: { $base: '== 0', $asset0: 5000, $asset1: 5000 }, - $comet: { $base: 5000 }, - }, + filter: async (ctx) => await isBulkerSupported(ctx) && !matchesDeployment(ctx, [{ deployment: 'weth' }]), + supplyCaps: async (ctx) => ( + { + $asset0: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset, + } + ), + tokenBalances: async (ctx) => ( + { + albert: { + $base: '== 0', + $asset0: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset + }, + $comet: { $base: getConfigForScenario(ctx).bulkerComet }, + } + ), }, async ({ comet, actors, bulker }, context) => { const { albert, betty } = actors; @@ -129,9 +146,9 @@ scenario( const { asset: collateralAssetAddress, scale: scaleBN } = asset0 === wrappedNativeToken ? { asset: asset1, scale: scale1 } : { asset: asset0, scale: scale0 }; const collateralAsset = context.getAssetByAddress(collateralAssetAddress); const collateralScale = scaleBN.toBigInt(); - const toSupplyCollateral = 5000n * collateralScale; - const toBorrowBase = 1000n * baseScale; - const toTransferBase = 500n * baseScale; + const toSupplyCollateral = BigInt(getConfigForScenario(context).bulkerAsset) * collateralScale; + const toBorrowBase = BigInt(getConfigForScenario(context).bulkerBorrowBase) * baseScale; + const toTransferBase = BigInt(getConfigForScenario(context).bulkerBorrowAsset) * baseScale; const toSupplyEth = exp(0.01, 18); const toWithdrawEth = exp(0.005, 18); @@ -193,13 +210,20 @@ scenario( 'Comet#bulker > (WETH base) all non-reward actions in one txn', { filter: async (ctx) => await isBulkerSupported(ctx) && matchesDeployment(ctx, [{ deployment: 'weth' }]), - supplyCaps: { - $asset0: 3000, - }, - tokenBalances: { - albert: { $base: '== 0', $asset0: 3000 }, - $comet: { $base: 5000 }, - }, + supplyCaps: async (ctx) => ( + { + $asset0: getConfigForScenario(ctx).bulkerAsset, + } + ), + tokenBalances: async (ctx) => ( + { + albert: { + $base: '== 0', + $asset0: getConfigForScenario(ctx).bulkerAsset + }, + $comet: { $base: getConfigForScenario(ctx).bulkerComet }, + } + ), }, async ({ comet, actors, bulker }, context) => { const { albert, betty } = actors; @@ -209,9 +233,9 @@ scenario( const { asset: collateralAssetAddress, scale: scaleBN } = await comet.getAssetInfo(0); const collateralAsset = context.getAssetByAddress(collateralAssetAddress); const collateralScale = scaleBN.toBigInt(); - const toSupplyCollateral = 3000n * collateralScale; - const toBorrowBase = 1500n * baseScale; - const toTransferBase = 500n * baseScale; + const toSupplyCollateral = BigInt(getConfigForScenario(context).bulkerAsset) * collateralScale; + const toBorrowBase = BigInt(getConfigForScenario(context).bulkerBorrowBase) * baseScale; + const toTransferBase = BigInt(getConfigForScenario(context).bulkerBorrowAsset) * baseScale; const toSupplyEth = exp(0.01, 18); const toWithdrawEth = exp(0.005, 18); @@ -268,15 +292,23 @@ scenario( scenario( 'Comet#bulker > (non-WETH base) all actions in one txn', { - filter: async (ctx) => await isBulkerSupported(ctx) && await isRewardSupported(ctx) && !matchesDeployment(ctx, [{ deployment: 'weth' }, { deployment: 'wsteth' }, { network: 'linea-goerli' }]), - supplyCaps: { - $asset0: 5000, - $asset1: 5000, - }, - tokenBalances: { - albert: { $base: '== 1000000', $asset0: 5000, $asset1: 5000 }, - $comet: { $base: 5000 }, - } + filter: async (ctx) => await isBulkerSupported(ctx) && await isRewardSupported(ctx) && !matchesDeployment(ctx, [{ deployment: 'weth' }, { deployment: 'wsteth' }]), + supplyCaps: async (ctx) => ( + { + $asset0: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset, + } + ), + tokenBalances: async (ctx) => ( + { + albert: { + $base: `== ${getConfigForScenario(ctx).bulkerBase}`, + $asset0: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset + }, + $comet: { $base: getConfigForScenario(ctx).bulkerComet }, + } + ), }, async ({ comet, actors, rewards, bulker }, context, world) => { const { albert, betty } = actors; @@ -291,10 +323,10 @@ scenario( const collateralAsset = context.getAssetByAddress(collateralAssetAddress); const collateralScale = scaleBN.toBigInt(); const [rewardTokenAddress] = await rewards.rewardConfig(comet.address); - const toSupplyBase = 1_000_000n * baseScale; - const toSupplyCollateral = 5000n * collateralScale; - const toBorrowBase = 1000n * baseScale; - const toTransferBase = 500n * baseScale; + const toSupplyBase = BigInt(getConfigForScenario(context).bulkerBase) * baseScale; + const toSupplyCollateral = BigInt(getConfigForScenario(context).bulkerAsset) * collateralScale; + const toBorrowBase = BigInt(getConfigForScenario(context).bulkerBorrowBase) * baseScale; + const toTransferBase = BigInt(getConfigForScenario(context).bulkerBorrowAsset) * baseScale; const toSupplyEth = exp(0.01, 18); const toWithdrawEth = exp(0.005, 18); @@ -372,15 +404,23 @@ scenario( scenario( 'Comet#bulker > (wstETH base) all actions in one txn', { - filter: async (ctx) => await isBulkerSupported(ctx) && await isRewardSupported(ctx) && !matchesDeployment(ctx, [{ deployment: 'weth' }, { network: 'linea-goerli' }]), - supplyCaps: { - $asset0: 5000, - $asset1: 5000, - }, - tokenBalances: { - albert: { $base: '== 1000000', $asset0: 5000, $asset1: 5000 }, - $comet: { $base: 5000 }, - } + filter: async (ctx) => await isBulkerSupported(ctx) && await isRewardSupported(ctx) && !matchesDeployment(ctx, [{ deployment: 'weth' }]), + supplyCaps: async (ctx) => ( + { + $asset0: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset, + } + ), + tokenBalances: async (ctx) => ( + { + albert: { + $base: `== ${getConfigForScenario(ctx).bulkerBase}`, + $asset0: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset + }, + $comet: { $base: getConfigForScenario(ctx).bulkerComet }, + } + ), }, async ({ comet, actors, rewards, bulker }, context, world) => { const { albert, betty } = actors; @@ -395,10 +435,10 @@ scenario( const collateralAsset = context.getAssetByAddress(collateralAssetAddress); const collateralScale = scaleBN.toBigInt(); const [rewardTokenAddress] = await rewards.rewardConfig(comet.address); - const toSupplyBase = 1_000_000n * baseScale; - const toSupplyCollateral = 5000n * collateralScale; - const toBorrowBase = 1000n * baseScale; - const toTransferBase = 500n * baseScale; + const toSupplyBase = BigInt(getConfigForScenario(context).bulkerBase) * baseScale; + const toSupplyCollateral = BigInt(getConfigForScenario(context).bulkerAsset) * collateralScale; + const toBorrowBase = BigInt(getConfigForScenario(context).bulkerBorrowBase) * baseScale; + const toTransferBase = BigInt(getConfigForScenario(context).bulkerBorrowAsset) * baseScale; const toSupplyEth = exp(0.01, 18); const toWithdrawEth = exp(0.005, 18); @@ -479,10 +519,12 @@ scenario( supplyCaps: { $asset0: 10, }, - tokenBalances: { - albert: { $base: '== 10', $asset0: 10 }, - $comet: { $base: 5000 }, - }, + tokenBalances: async (ctx) => ( + { + albert: { $base: '== 10', $asset0: 10 }, + $comet: { $base: getConfigForScenario(ctx).bulkerComet }, + } + ), }, async ({ comet, actors, rewards, bulker }, context, world) => { const { albert, betty } = actors; diff --git a/scenario/CrossChainGovernanceScenario.ts b/scenario/CrossChainGovernanceScenario.ts index cc25ab765..848b9663a 100644 --- a/scenario/CrossChainGovernanceScenario.ts +++ b/scenario/CrossChainGovernanceScenario.ts @@ -47,7 +47,7 @@ scenario( scenario( 'upgrade Polygon governance contracts and ensure they work properly', { - filter: async ctx => matchesDeployment(ctx, [{network: 'polygon'}, {network: 'mumbai'}]) + filter: async ctx => matchesDeployment(ctx, [{network: 'polygon'}]) }, async ({ comet, configurator, proxyAdmin, timelock: oldLocalTimelock, bridgeReceiver: oldBridgeReceiver }, context, world) => { const dm = world.deploymentManager; @@ -155,7 +155,7 @@ scenario( scenario( 'upgrade Arbitrum governance contracts and ensure they work properly', { - filter: async ctx => matchesDeployment(ctx, [{network: 'arbitrum'}, {network: 'arbitrum-goerli'}]) + filter: async ctx => matchesDeployment(ctx, [{network: 'arbitrum'}]) }, async ({ comet, configurator, proxyAdmin, timelock: oldLocalTimelock, bridgeReceiver: oldBridgeReceiver }, context, world) => { const dm = world.deploymentManager; @@ -262,7 +262,7 @@ scenario( } ); -scenario( +scenario.skip( 'upgrade Linea governance contracts and ensure they work properly', { filter: async ctx => matchesDeployment(ctx, [{ network: 'linea-goerli' }]) @@ -386,7 +386,7 @@ scenario( scenario( 'upgrade Scroll governance contracts and ensure they work properly', { - filter: async ctx => matchesDeployment(ctx, [{ network: 'scroll-goerli' }, {network: 'scroll'}]) + filter: async ctx => matchesDeployment(ctx, [{network: 'scroll'}]) }, async ( { diff --git a/scenario/InterestRateScenario.ts b/scenario/InterestRateScenario.ts index a5161ad33..72256e908 100644 --- a/scenario/InterestRateScenario.ts +++ b/scenario/InterestRateScenario.ts @@ -3,7 +3,6 @@ import { expect } from 'chai'; import { annualize, defactor, exp } from '../test/helpers'; import { BigNumber } from 'ethers'; import { FuzzType } from './constraints/Fuzzing'; -import { matchesDeployment } from './utils'; function calculateInterestRate( utilization: BigNumber, @@ -92,9 +91,6 @@ scenario( borrowPerYearInterestRateSlopeHigh: exp(0.3, 18), }, utilization: 0.5, - // XXX this scenario fails for Goerli cUSDCv3 because someone supplied 100bn USDC and it's no longer - // possible to increase the utilization up to the target amount - filter: async (ctx) => !matchesDeployment(ctx, [{network: 'goerli', deployment: 'usdc'}]) }, async ({ comet }) => { const utilization = await comet.getUtilization(); @@ -118,9 +114,6 @@ scenario( borrowPerYearInterestRateSlopeHigh: exp(0.3, 18), }, utilization: 0.85, - // XXX this scenario fails for Goerli cUSDCv3 because someone supplied 100bn USDC and it's no longer - // possible to increase the utilization up to the target amount - filter: async (ctx) => !matchesDeployment(ctx, [{network: 'goerli', deployment: 'usdc'}]) }, async ({ comet }) => { const utilization = await comet.getUtilization(); diff --git a/scenario/SupplyScenario.ts b/scenario/SupplyScenario.ts index a1b012390..e12d04a31 100644 --- a/scenario/SupplyScenario.ts +++ b/scenario/SupplyScenario.ts @@ -509,6 +509,7 @@ scenario( symbol === 'WETH' ? /Transaction reverted without a reason string/ : /.^/, symbol === 'wstETH' ? /0xc2139725/ : /.^/, symbol === 'WMATIC' ? /Transaction reverted without a reason string/ : /.^/, + symbol === 'WPOL' ? /Transaction reverted without a reason string/ : /.^/, ] ); } @@ -595,6 +596,7 @@ scenario( symbol === 'WETH' ? /Transaction reverted without a reason string/ : /.^/, symbol === 'wstETH' ? /0x00b284f2/ : /.^/, symbol === 'WMATIC' ? /Transaction reverted without a reason string/ : /.^/, + symbol === 'WPOL' ? /Transaction reverted without a reason string/ : /.^/, ] ); } diff --git a/scenario/TransferScenario.ts b/scenario/TransferScenario.ts index 796446453..0163e45f2 100644 --- a/scenario/TransferScenario.ts +++ b/scenario/TransferScenario.ts @@ -273,10 +273,15 @@ scenario( 'Comet#transfer collateral reverts if undercollateralized', { // XXX we should probably have a price constraint? - cometBalances: { - albert: { $base: -1000, $asset0: '== 3000' }, // in units of asset, not wei - betty: { $asset0: 0 }, - }, + cometBalances: async (ctx) => ( + { + albert: { + $base: -getConfigForScenario(ctx).transferBase, + $asset0: `== ${getConfigForScenario(ctx).transferAsset}` + }, // in units of asset, not wei + betty: { $asset0: 0 }, + } + ), }, async ({ comet, actors }, context) => { const { albert, betty } = actors; @@ -289,7 +294,7 @@ scenario( albert.transferAsset({ dst: betty.address, asset: collateralAsset.address, - amount: 3000n * scale, + amount: BigInt(getConfigForScenario(context).transferAsset) * scale, }), 'NotCollateralized()' ); @@ -300,10 +305,15 @@ scenario( 'Comet#transferFrom collateral reverts if undercollateralized', { // XXX we should probably have a price constraint? - cometBalances: { - albert: { $base: -1000, $asset0: '== 3000' }, // in units of asset, not wei - betty: { $asset0: 0 }, - }, + cometBalances: async (ctx) => ( + { + albert: { + $base: -getConfigForScenario(ctx).transferBase, + $asset0: `== ${getConfigForScenario(ctx).transferAsset}` + }, // in units of asset, not wei + betty: { $asset0: 0 }, + } + ), }, async ({ comet, actors }, context) => { const { albert, betty } = actors; @@ -319,7 +329,7 @@ scenario( src: albert.address, dst: betty.address, asset: collateralAsset.address, - amount: 3000n * scale, + amount: BigInt(getConfigForScenario(context).transferAsset) * scale, }), 'NotCollateralized()' ); diff --git a/scenario/WithdrawScenario.ts b/scenario/WithdrawScenario.ts index d0bab38b9..8ec1848e2 100644 --- a/scenario/WithdrawScenario.ts +++ b/scenario/WithdrawScenario.ts @@ -2,6 +2,7 @@ import { CometContext, scenario } from './context/CometContext'; import { expect } from 'chai'; import { expectApproximately, expectRevertCustom, hasMinBorrowGreaterThanOne, isTriviallySourceable, isValidAssetIndex, MAX_ASSETS } from './utils'; import { ContractReceipt } from 'ethers'; +import { getConfigForScenario } from './utils/scenarioHelper'; async function testWithdrawCollateral(context: CometContext, assetNum: number): Promise { const comet = await context.getComet(); @@ -104,13 +105,17 @@ scenario( scenario( 'Comet#withdraw > borrow base', { - tokenBalances: { - albert: { $base: '== 0' }, - $comet: { $base: 1000 }, // in units of asset, not wei - }, - cometBalances: { - albert: { $asset0: 3000 } // in units of asset, not wei - }, + tokenBalances: async (ctx) => ( + { + albert: { $base: '== 0' }, + $comet: { $base: getConfigForScenario(ctx).withdrawBase }, // in units of asset, not wei + } + ), + cometBalances: async (ctx) => ( + { + albert: { $asset0: getConfigForScenario(ctx).withdrawAsset } // in units of asset, not wei + } + ), }, async ({ comet, actors }, context) => { const { albert } = actors; @@ -123,10 +128,10 @@ scenario( expect(await comet.balanceOf(albert.address)).to.be.equal(0n); // Albert borrows 1000 unit of base from Comet - const txn = await albert.withdrawAsset({ asset: baseAsset.address, amount: 1000n * scale }); + const txn = await albert.withdrawAsset({ asset: baseAsset.address, amount: BigInt(getConfigForScenario(context).withdrawBase) * scale }); - expect(await baseAsset.balanceOf(albert.address)).to.be.equal(1000n * scale); - expectApproximately(await albert.getCometBaseBalance(), -1000n * scale, precision); + expect(await baseAsset.balanceOf(albert.address)).to.be.equal(BigInt(getConfigForScenario(context).withdrawBase) * scale); + expectApproximately(await albert.getCometBaseBalance(), -BigInt(getConfigForScenario(context).withdrawBase) * scale, precision); return txn; // return txn to measure gas } @@ -163,12 +168,17 @@ scenario( scenario( 'Comet#withdrawFrom > borrow base', { - tokenBalances: { - $comet: { $base: 1000 }, // in units of asset, not wei - }, - cometBalances: { - albert: { $asset0: 3000 } // in units of asset, not wei - }, + tokenBalances: async (ctx) => ( + { + albert: { $base: '== 0' }, + $comet: { $base: getConfigForScenario(ctx).withdrawBase }, // in units of asset, not wei + } + ), + cometBalances: async (ctx) => ( + { + albert: { $asset0: getConfigForScenario(ctx).withdrawAsset } // in units of asset, not wei + } + ), }, async ({ comet, actors }, context) => { const { albert, betty } = actors; @@ -183,10 +193,10 @@ scenario( await albert.allow(betty, true); // Betty borrows 1000 unit of base using Albert's account - const txn = await betty.withdrawAssetFrom({ src: albert.address, dst: betty.address, asset: baseAsset.address, amount: 1000n * scale }); + const txn = await betty.withdrawAssetFrom({ src: albert.address, dst: betty.address, asset: baseAsset.address, amount: BigInt(getConfigForScenario(context).withdrawBase) * scale }); - expect(await baseAsset.balanceOf(betty.address)).to.be.equal(1000n * scale); - expectApproximately(await albert.getCometBaseBalance(), -1000n * scale, precision); + expect(await baseAsset.balanceOf(betty.address)).to.be.equal(BigInt(getConfigForScenario(context).withdrawBase) * scale); + expectApproximately(await albert.getCometBaseBalance(), -BigInt(getConfigForScenario(context).withdrawBase) * scale, precision); return txn; // return txn to measure gas } diff --git a/scenario/constraints/ProposalConstraint.ts b/scenario/constraints/ProposalConstraint.ts index d906d89fb..2e4d968cf 100644 --- a/scenario/constraints/ProposalConstraint.ts +++ b/scenario/constraints/ProposalConstraint.ts @@ -62,9 +62,9 @@ export class ProposalConstraint implements StaticConstra ); } - // temporary hack to skip proposal 353 - if (proposal.id.eq(353)) { - console.log('Skipping proposal 353'); + // temporary hack to skip proposal 385 + if (proposal.id.eq(385)) { + console.log('Skipping proposal 385'); continue; } diff --git a/scenario/utils/index.ts b/scenario/utils/index.ts index 0b3e16d85..567c3c276 100644 --- a/scenario/utils/index.ts +++ b/scenario/utils/index.ts @@ -533,8 +533,7 @@ export async function createCrossChainProposal(context: CometContext, l2Proposal // Create the chain-specific wrapper around the L2 proposal data switch (bridgeNetwork) { - case 'arbitrum': - case 'arbitrum-goerli': { + case 'arbitrum': { const inbox = await govDeploymentManager.getContractOrThrow('arbitrumInbox'); const refundAddress = constants.AddressZero; const createRetryableTicketCalldata = utils.defaultAbiCoder.encode( @@ -558,8 +557,7 @@ export async function createCrossChainProposal(context: CometContext, l2Proposal calldata.push(createRetryableTicketCalldata); break; } - case 'base': - case 'base-goerli': { + case 'base': { const sendMessageCalldata = utils.defaultAbiCoder.encode( ['address', 'bytes', 'uint32'], [bridgeReceiver.address, l2ProposalData, 1_000_000] // XXX find a reliable way to estimate the gasLimit @@ -574,7 +572,6 @@ export async function createCrossChainProposal(context: CometContext, l2Proposal calldata.push(sendMessageCalldata); break; } - case 'mumbai': case 'polygon': { const sendMessageToChildCalldata = utils.defaultAbiCoder.encode( ['address', 'bytes'], @@ -588,20 +585,20 @@ export async function createCrossChainProposal(context: CometContext, l2Proposal calldata.push(sendMessageToChildCalldata); break; } - case 'linea-goerli': { - const sendMessageCalldata = utils.defaultAbiCoder.encode( - ['address', 'uint256', 'bytes'], - [bridgeReceiver.address, 0, l2ProposalData] - ); - const lineaMessageService = await govDeploymentManager.getContractOrThrow( - 'lineaMessageService' - ); - targets.push(lineaMessageService.address); - values.push(0); - signatures.push('sendMessage(address,uint256,bytes)'); - calldata.push(sendMessageCalldata); - break; - } + // case 'linea-goerli': { + // const sendMessageCalldata = utils.defaultAbiCoder.encode( + // ['address', 'uint256', 'bytes'], + // [bridgeReceiver.address, 0, l2ProposalData] + // ); + // const lineaMessageService = await govDeploymentManager.getContractOrThrow( + // 'lineaMessageService' + // ); + // targets.push(lineaMessageService.address); + // values.push(0); + // signatures.push('sendMessage(address,uint256,bytes)'); + // calldata.push(sendMessageCalldata); + // break; + // } case 'optimism': { const sendMessageCalldata = utils.defaultAbiCoder.encode( ['address', 'bytes', 'uint32'], @@ -631,8 +628,7 @@ export async function createCrossChainProposal(context: CometContext, l2Proposal calldata.push(sendMessageCalldata); break; } - case 'scroll': - case 'scroll-goerli': { + case 'scroll': { const sendMessageCalldata = utils.defaultAbiCoder.encode( ['address', 'uint256', 'bytes', 'uint256'], [bridgeReceiver.address, 0, l2ProposalData, 1_000_000] // XXX find a reliable way to estimate the gasLimit diff --git a/scenario/utils/isBridgeProposal.ts b/scenario/utils/isBridgeProposal.ts index 8bad488e8..97d87bcd0 100644 --- a/scenario/utils/isBridgeProposal.ts +++ b/scenario/utils/isBridgeProposal.ts @@ -8,8 +8,7 @@ export async function isBridgeProposal( ) { const bridgeNetwork = bridgeDeploymentManager.network; switch (bridgeNetwork) { - case 'arbitrum': - case 'arbitrum-goerli': { + case 'arbitrum': { const governor = await governanceDeploymentManager.getContractOrThrow('governor'); const inbox = await governanceDeploymentManager.getContractOrThrow('arbitrumInbox'); const l1GatewayRouter = await governanceDeploymentManager.getContractOrThrow( @@ -18,7 +17,6 @@ export async function isBridgeProposal( const { targets } = await governor.getActions(openProposal.id); return targets.includes(inbox.address) || targets.includes(l1GatewayRouter.address); } - case 'mumbai': case 'polygon': { const { governor, @@ -31,8 +29,7 @@ export async function isBridgeProposal( const { targets } = await governor.getActions(openProposal.id); return targets.some(t => bridgeAddresses.includes(t.toLowerCase())); } - case 'base': - case 'base-goerli': { + case 'base': { const governor = await governanceDeploymentManager.getContractOrThrow('governor'); const baseL1CrossDomainMessenger = await governanceDeploymentManager.getContractOrThrow( 'baseL1CrossDomainMessenger' @@ -44,14 +41,14 @@ export async function isBridgeProposal( const bridgeContracts = [baseL1CrossDomainMessenger.address, baseL1StandardBridge.address]; return targets.some(t => bridgeContracts.includes(t)); } - case 'linea-goerli': { - const governor = await governanceDeploymentManager.getContractOrThrow('governor'); - const lineaMessageService = await governanceDeploymentManager.getContractOrThrow( - 'lineaMessageService' - ); - const { targets } = await governor.getActions(openProposal.id); - return targets.includes(lineaMessageService.address); - } + // case 'linea': { + // const governor = await governanceDeploymentManager.getContractOrThrow('governor'); + // const lineaMessageService = await governanceDeploymentManager.getContractOrThrow( + // 'lineaMessageService' + // ); + // const { targets } = await governor.getActions(openProposal.id); + // return targets.includes(lineaMessageService.address); + // } case 'optimism': { const governor = await governanceDeploymentManager.getContractOrThrow('governor'); const opL1CrossDomainMessenger = await governanceDeploymentManager.getContractOrThrow( @@ -79,8 +76,7 @@ export async function isBridgeProposal( ]; return targets.some(t => bridgeContracts.includes(t)); } - case 'scroll': - case 'scroll-goerli': { + case 'scroll': { const governor = await governanceDeploymentManager.getContractOrThrow('governor'); const scrollMessenger = await governanceDeploymentManager.getContractOrThrow( 'scrollMessenger' diff --git a/scenario/utils/relayArbitrumMessage.ts b/scenario/utils/relayArbitrumMessage.ts index 442d45a27..ee434bb4b 100644 --- a/scenario/utils/relayArbitrumMessage.ts +++ b/scenario/utils/relayArbitrumMessage.ts @@ -147,10 +147,7 @@ export async function relayCCTPMint( // L1 contracts const L1MessageTransmitter = await governanceDeploymentManager.getContractOrThrow('CCTPMessageTransmitter'); // Arbitrum TokenMinter which is L2 contracts - const TokenMinter = - bridgeDeploymentManager.network === 'arbitrum' ? - await bridgeDeploymentManager.existing('TokenMinter', '0xE7Ed1fa7f45D05C508232aa32649D89b73b8bA48', 'arbitrum') : - await bridgeDeploymentManager.existing('TokenMinter', '0xE997d7d2F6E065a9A93Fa2175E878Fb9081F1f0A', 'arbitrum-goerli'); + const TokenMinter = await bridgeDeploymentManager.existing('TokenMinter', '0xE7Ed1fa7f45D05C508232aa32649D89b73b8bA48', 'arbitrum'); const depositForBurnEvents: Log[] = await governanceDeploymentManager.hre.ethers.provider.getLogs({ @@ -232,10 +229,7 @@ export async function relayCCTPMint( }); // Impersonate the Arbitrum TokenMinter and mint token to recipient - const ImpersonateLocalTokenMessenger = - bridgeDeploymentManager.network === 'arbitrum' ? '0x19330d10d9cc8751218eaf51e8885d058642e08a' : - bridgeDeploymentManager.network === 'arbitrum-goerli' ? '0x12dcfd3fe2e9eac2859fd1ed86d2ab8c5a2f9352' : - '0x0'; + const ImpersonateLocalTokenMessenger = bridgeDeploymentManager.network === 'arbitrum' ? '0x19330d10d9cc8751218eaf51e8885d058642e08a' : '0x0'; // Impersonate the Arbitrum TokenMinter and mint token to recipient for (let burnEvent of burnEvents) { const { recipient, amount, sourceDomain, burnToken } = burnEvent; diff --git a/scenario/utils/relayBaseMessage.ts b/scenario/utils/relayBaseMessage.ts index 397faa7d2..3625deb78 100644 --- a/scenario/utils/relayBaseMessage.ts +++ b/scenario/utils/relayBaseMessage.ts @@ -11,7 +11,7 @@ The Base relayer applies an offset to the message sender. applyL1ToL2Alias mimics the AddressAliasHelper.applyL1ToL2Alias fn that converts an L1 address to its offset, L2 equivalent. -https://goerli.basescan.org/address/0x4200000000000000000000000000000000000007#code +https://sepolia.basescan.org/address/0x4200000000000000000000000000000000000007#code */ function applyL1ToL2Alias(address: string) { const offset = BigInt('0x1111000000000000000000000000000000001111'); diff --git a/scenario/utils/relayMessage.ts b/scenario/utils/relayMessage.ts index eb7db32e0..1329a0da3 100644 --- a/scenario/utils/relayMessage.ts +++ b/scenario/utils/relayMessage.ts @@ -15,7 +15,6 @@ export default async function relayMessage( const bridgeNetwork = bridgeDeploymentManager.network; switch (bridgeNetwork) { case 'base': - case 'base-goerli': await relayBaseMessage( governanceDeploymentManager, bridgeDeploymentManager, @@ -36,7 +35,6 @@ export default async function relayMessage( startingBlockNumber ); break; - case 'mumbai': case 'polygon': await relayPolygonMessage( governanceDeploymentManager, @@ -45,7 +43,6 @@ export default async function relayMessage( ); break; case 'arbitrum': - case 'arbitrum-goerli': await relayArbitrumMessage( governanceDeploymentManager, bridgeDeploymentManager, @@ -57,7 +54,7 @@ export default async function relayMessage( startingBlockNumber ); break; - case 'linea-goerli': + case 'linea': await relayLineaMessage( governanceDeploymentManager, bridgeDeploymentManager, @@ -65,7 +62,6 @@ export default async function relayMessage( ); break; case 'scroll': - case 'scroll-goerli': await relayScrollMessage( governanceDeploymentManager, bridgeDeploymentManager, diff --git a/scenario/utils/relayScrollMessage.ts b/scenario/utils/relayScrollMessage.ts index e6feb53d9..161b4bccb 100644 --- a/scenario/utils/relayScrollMessage.ts +++ b/scenario/utils/relayScrollMessage.ts @@ -48,19 +48,10 @@ export default async function relayScrollMessage( await setNextBaseFeeToZero(bridgeDeploymentManager); - let aliasAccount; - if (bridgeDeploymentManager.network == 'scroll-goerli'){ - aliasAccount = await impersonateAddress( - bridgeDeploymentManager, - '0xD69c917c7F1C0a724A51c189B4A8F4F8C8E8cA0a' - ); - } else { - aliasAccount = await impersonateAddress( - bridgeDeploymentManager, - applyL1ToL2Alias(scrollMessenger.address) - ); - } - + let aliasAccount = await impersonateAddress( + bridgeDeploymentManager, + applyL1ToL2Alias(scrollMessenger.address) + ); const relayMessageTxn = await ( await l2Messenger.connect(aliasAccount).relayMessage( sender, diff --git a/scenario/utils/scenarioHelper.ts b/scenario/utils/scenarioHelper.ts index 80134f6e7..a5a8d82a7 100644 --- a/scenario/utils/scenarioHelper.ts +++ b/scenario/utils/scenarioHelper.ts @@ -16,6 +16,8 @@ const config = { transferBase: 1000, transferAsset: 5000, interestSeconds: 110, + withdrawBase: 1000, + withdrawAsset: 3000, }; export function getConfigForScenario(ctx: CometContext) { @@ -55,5 +57,20 @@ export function getConfigForScenario(ctx: CometContext) { config.interestSeconds = 110; } + if (ctx.world.base.network === 'arbitrum' && ctx.world.base.deployment === 'usdc.e') { + config.liquidationDenominator = 84; + config.liquidationBase = 100000; + config.liquidationBase1 = 50000; + config.liquidationAsset = 10000; + } + + if (ctx.world.base.network === 'polygon' && ctx.world.base.deployment === 'usdc') { + config.bulkerAsset = 200; + } + + if (ctx.world.base.network === 'polygon' && ctx.world.base.deployment === 'usdt') { + config.withdrawAsset = 10000; + } + return config; } \ No newline at end of file diff --git a/scripts/CCTP-attestation.ts b/scripts/CCTP-attestation.ts index dd82b0f5b..6eca4aaa1 100644 --- a/scripts/CCTP-attestation.ts +++ b/scripts/CCTP-attestation.ts @@ -1,7 +1,7 @@ /* A script to help check if CCTP's attestation server to acquire signature to mint native USDC on arbitrum Example: - DEPLOYMENT=usdc BURN_TXN_HASH= SOURCE_NETWORK=goerli DEST_NETWORK=arbitrum-goerli ETH_PK= npx hardhat run scripts/CCTP-attestation.ts + DEPLOYMENT=usdc BURN_TXN_HASH= SOURCE_NETWORK=sepolia DEST_NETWORK=arbitrum-sepolia ETH_PK= npx hardhat run scripts/CCTP-attestation.ts */ import hre from 'hardhat'; import { DeploymentManager } from '../plugins/deployment_manager/DeploymentManager'; diff --git a/scripts/liquidation_bot/index.ts b/scripts/liquidation_bot/index.ts index 16380c25d..6092e6c72 100644 --- a/scripts/liquidation_bot/index.ts +++ b/scripts/liquidation_bot/index.ts @@ -66,12 +66,12 @@ async function main() { hre.ethers.provider, // a normal ethers.js provider, to perform gas estimations and nonce lookups authSigner, // ethers.js signer wallet, only for signing request payloads, not transactions ); - } else if (network === 'goerli') { + } else if (network === 'sepolia') { flashbotsProvider = await FlashbotsBundleProvider.create( hre.ethers.provider, // a normal ethers.js provider, to perform gas estimations and nonce lookups authSigner, // ethers.js signer wallet, only for signing request payloads, not transactions - 'https://relay-goerli.flashbots.net', - 'goerli' + 'https://relay-sepolia.flashbots.net', + 'sepolia' ); } else { throw new Error(`Unsupported network: ${network}`); diff --git a/scripts/liquidation_bot/liquidateUnderwaterBorrowers.ts b/scripts/liquidation_bot/liquidateUnderwaterBorrowers.ts index 29a70303e..1c42437c0 100644 --- a/scripts/liquidation_bot/liquidateUnderwaterBorrowers.ts +++ b/scripts/liquidation_bot/liquidateUnderwaterBorrowers.ts @@ -42,9 +42,6 @@ const addresses = { RS_ETH: '0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7', USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7' }, - goerli: { - WETH: '0xB4FBF271143F4FBf7B91A5ded31805e42b2208d' - }, polygon: { WBTC: '0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6', WETH: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619', @@ -70,9 +67,6 @@ const liquidationThresholds = { 'usdc': 10e6, 'weth': 1e18 }, - goerli: { - 'usdc': 10e6 - }, polygon: { 'usdc': 10e6 }, @@ -105,12 +99,6 @@ export const flashLoanPools = { poolFee: 3000, } }, - goerli: { - usdc: { - tokenAddress: addresses.goerli.WETH, - poolFee: 3000 - } - }, polygon: { usdc: { tokenAddress: addresses.polygon.BOB, diff --git a/src/deploy/index.ts b/src/deploy/index.ts index fde711912..938362227 100644 --- a/src/deploy/index.ts +++ b/src/deploy/index.ts @@ -89,15 +89,17 @@ export const WHALES = { '0x2775b1c75658be0f640272ccb8c72ac986009e38', '0x1a9c8182c09f50c8318d769245bea52c32be35bc', '0x3c22ec75ea5D745c78fc84762F7F1E6D82a2c5BF', - '0x426c4966fC76Bf782A663203c023578B744e4C5E', // wUSDM whale + '0x3B95bC951EE0f553ba487327278cAc44f29715E5', // wUSDM whale '0x88a1493366D48225fc3cEFbdae9eBb23E323Ade3', // USDe whale '0x43594da5d6A03b2137a04DF5685805C676dEf7cB', // rsETH whale - '0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b' + '0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b', + '0x0B925eD163218f6662a35e0f0371Ac234f9E9371', // wstETH whale ], polygon: [ '0x2093b4281990a568c9d588b8bce3bfd7a1557ebd', // WETH whale '0xd814b26554204245a30f8a42c289af582421bf04', // WBTC whale - '0x167384319b41f7094e62f7506409eb38079abff8' // WMATIC whale + '0x167384319b41f7094e62f7506409eb38079abff8', // WMATIC whale + '0x4D97DCd97eC945f40cF65F87097ACe5EA0476045', // USDC.e whale ], arbitrum: [ '0x8eb270e296023e9d92081fdf967ddd7878724424', // rETH whale @@ -128,19 +130,6 @@ export const WHALES = { scroll: [ '0xaaaaAAAACB71BF2C8CaE522EA5fa455571A74106' // USDC whale ], - 'arbitrum-goerli': [ - '0x4984cbfa5b199e5920995883d345bbe14b005db7', // USDC whale - '0xbbfe34e868343e6f4f5e8b5308de980d7bd88c46', // LINK whale - '0x8DA65F8E3Aa22A498211fc4204C498ae9050DAE4', // COMP whale - '0x6ed0c4addc308bb800096b8daa41de5ae219cd36' // native USDC whale - ], - 'base-goerli': [ - '0x21856935e5689490c72865f34CC665D0FF25664b' // USDC whale - ], - 'linea-goerli': [ - '0xC858966280Da3Fa0348E51D2c3B892EcC889fC98', // USDC whale - '0x44411c605eb7e009cad03f3847cfbbfcf8895130' // COMP whale - ], optimism: [ '0x2A82Ae142b2e62Cb7D10b55E323ACB1Cab663a26', // OP whale '0x8af3827a41c26c7f32c81e93bb66e837e0210d5c', // USDC whale @@ -152,6 +141,7 @@ export const WHALES = { '0x651C9D1F9da787688225f49d63ad1623ba89A8D5', // FBTC whale '0xC455fE28a76da80022d4C35A37eB08FF405Eb78f', // FBTC whale '0x524db930F0886CdE7B5FFFc920Aae85e98C2abfb', // FBTC whale + '0xCd83CbBFCE149d141A5171C3D6a0F0fCCeE225Ab', // COMP whale ], }; From 4ba3b92488a557d3ad4de4d5b7d37eeb492ca397 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Fri, 27 Dec 2024 15:05:57 +0200 Subject: [PATCH 27/45] feat: migrations and working scenarios --- .github/workflows/run-slither.yaml | 2 +- ...pdate_comet_to_support_more_collaterals.ts | 170 ++++++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 170 ++++++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 170 ++++++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 170 ++++++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 147 +++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 147 +++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 147 +++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 147 +++++++++++++++ ...date_comet_to_support_more_collaterals.ts} | 2 +- ...pdate_comet_to_support_more_collaterals.ts | 126 +++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 126 +++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 126 +++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 126 +++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 147 +++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 143 +++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 143 +++++++++++++++ .../migrations/1735299805_my_migration.ts | 14 ++ ...pdate_comet_to_support_more_collaterals.ts | 143 +++++++++++++++ .../migrations/1735299811_my_migration.ts | 14 ++ ...pdate_comet_to_support_more_collaterals.ts | 143 +++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 143 +++++++++++++++ ...pdate_comet_to_support_more_collaterals.ts | 143 +++++++++++++++ hardhat.config.ts | 5 +- plugins/deployment_manager/test/VerifyTest.ts | 10 +- plugins/scenario/utils/hreForBase.ts | 2 +- scenario/BulkerScenario.ts | 24 +-- scenario/context/CometContext.ts | 2 +- scenario/utils/index.ts | 5 + scenario/utils/relayScrollMessage.ts | 43 +++-- scenario/utils/scenarioHelper.ts | 12 ++ src/deploy/index.ts | 3 +- 32 files changed, 2872 insertions(+), 43 deletions(-) create mode 100644 deployments/arbitrum/usdc.e/migrations/1735299634_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/arbitrum/usdt/migrations/1735299656_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/arbitrum/weth/migrations/1735299663_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/base/usdbc/migrations/1735299714_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/base/usdc/migrations/1735299718_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/base/weth/migrations/1735299723_update_comet_to_support_more_collaterals.ts rename deployments/mainnet/{weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts => usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts} (98%) create mode 100644 deployments/mainnet/usds/migrations/1735299744_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/mainnet/usdt/migrations/1735299748_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/mainnet/wsteth/migrations/1735299760_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/optimism/usdt/migrations/1735054359_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/optimism/usdt/migrations/1735299805_my_migration.ts create mode 100644 deployments/optimism/weth/migrations/1735054364_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/optimism/weth/migrations/1735299811_my_migration.ts create mode 100644 deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/polygon/usdt/migrations/1735299832_update_comet_to_support_more_collaterals.ts create mode 100644 deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts diff --git a/.github/workflows/run-slither.yaml b/.github/workflows/run-slither.yaml index bab788973..80dfa2f8c 100644 --- a/.github/workflows/run-slither.yaml +++ b/.github/workflows/run-slither.yaml @@ -28,4 +28,4 @@ jobs: run: solc-select install 0.8.15;solc-select use 0.8.15 - name: Function clash analysis - run: yarn slither:fn-clashes &> tmp_res; cat tmp_res | { grep 'Function id collision found' || false; } && exit 1 || exit 0 + run: yarn slither:fn-clashes &> tmp_res; cat tmp_res | grep 'Function id collision found' && exit 1 || exit 0 \ No newline at end of file diff --git a/deployments/arbitrum/usdc.e/migrations/1735299634_update_comet_to_support_more_collaterals.ts b/deployments/arbitrum/usdc.e/migrations/1735299634_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..762cdcf21 --- /dev/null +++ b/deployments/arbitrum/usdc.e/migrations/1735299634_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,170 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; +import { applyL1ToL2Alias, estimateL2Transaction } from '../../../../scenario/utils/arbitrumUtils'; + +let newCometExtAddress: string; + +export default migration('1735299634_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + timelock: l2Timelock, + } = await deploymentManager.getContracts(); + + const { + arbitrumInbox, + timelock, + governor + } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + const createRetryableTicketGasParams = await estimateL2Transaction( + { + from: applyL1ToL2Alias(timelock.address), + to: bridgeReceiver.address, + data: l2ProposalData + }, + deploymentManager + ); + const refundAddress = l2Timelock.address; + + const mainnetActions = [ + // 1. Set Comet configuration and deployAndUpgradeTo WETH Comet on Arbitrum. + { + contract: arbitrumInbox, + signature: 'createRetryableTicket(address,uint256,uint256,address,address,uint256,uint256,bytes)', + args: [ + bridgeReceiver.address, // address to, + 0, // uint256 l2CallValue, + createRetryableTicketGasParams.maxSubmissionCost, // uint256 maxSubmissionCost, + refundAddress, // address excessFeeRefundAddress, + refundAddress, // address callValueRefundAddress, + createRetryableTicketGasParams.gasLimit, // uint256 gasLimit, + createRetryableTicketGasParams.maxFeePerGas, // uint256 maxFeePerGas, + l2ProposalData, // bytes calldata data + ], + value: createRetryableTicketGasParams.deposit + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts b/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..b55987a78 --- /dev/null +++ b/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,170 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; +import { applyL1ToL2Alias, estimateL2Transaction } from '../../../../scenario/utils/arbitrumUtils'; + +let newCometExtAddress: string; + +export default migration('1735299626_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + timelock: l2Timelock, + } = await deploymentManager.getContracts(); + + const { + arbitrumInbox, + timelock, + governor + } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + const createRetryableTicketGasParams = await estimateL2Transaction( + { + from: applyL1ToL2Alias(timelock.address), + to: bridgeReceiver.address, + data: l2ProposalData + }, + deploymentManager + ); + const refundAddress = l2Timelock.address; + + const mainnetActions = [ + // 1. Set Comet configuration and deployAndUpgradeTo WETH Comet on Arbitrum. + { + contract: arbitrumInbox, + signature: 'createRetryableTicket(address,uint256,uint256,address,address,uint256,uint256,bytes)', + args: [ + bridgeReceiver.address, // address to, + 0, // uint256 l2CallValue, + createRetryableTicketGasParams.maxSubmissionCost, // uint256 maxSubmissionCost, + refundAddress, // address excessFeeRefundAddress, + refundAddress, // address callValueRefundAddress, + createRetryableTicketGasParams.gasLimit, // uint256 gasLimit, + createRetryableTicketGasParams.maxFeePerGas, // uint256 maxFeePerGas, + l2ProposalData, // bytes calldata data + ], + value: createRetryableTicketGasParams.deposit + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/arbitrum/usdt/migrations/1735299656_update_comet_to_support_more_collaterals.ts b/deployments/arbitrum/usdt/migrations/1735299656_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..7e008e321 --- /dev/null +++ b/deployments/arbitrum/usdt/migrations/1735299656_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,170 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; +import { applyL1ToL2Alias, estimateL2Transaction } from '../../../../scenario/utils/arbitrumUtils'; + +let newCometExtAddress: string; + +export default migration('1735299656_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + timelock: l2Timelock, + } = await deploymentManager.getContracts(); + + const { + arbitrumInbox, + timelock, + governor + } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + const createRetryableTicketGasParams = await estimateL2Transaction( + { + from: applyL1ToL2Alias(timelock.address), + to: bridgeReceiver.address, + data: l2ProposalData + }, + deploymentManager + ); + const refundAddress = l2Timelock.address; + + const mainnetActions = [ + // 1. Set Comet configuration and deployAndUpgradeTo WETH Comet on Arbitrum. + { + contract: arbitrumInbox, + signature: 'createRetryableTicket(address,uint256,uint256,address,address,uint256,uint256,bytes)', + args: [ + bridgeReceiver.address, // address to, + 0, // uint256 l2CallValue, + createRetryableTicketGasParams.maxSubmissionCost, // uint256 maxSubmissionCost, + refundAddress, // address excessFeeRefundAddress, + refundAddress, // address callValueRefundAddress, + createRetryableTicketGasParams.gasLimit, // uint256 gasLimit, + createRetryableTicketGasParams.maxFeePerGas, // uint256 maxFeePerGas, + l2ProposalData, // bytes calldata data + ], + value: createRetryableTicketGasParams.deposit + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/arbitrum/weth/migrations/1735299663_update_comet_to_support_more_collaterals.ts b/deployments/arbitrum/weth/migrations/1735299663_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..7641ccc30 --- /dev/null +++ b/deployments/arbitrum/weth/migrations/1735299663_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,170 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; +import { applyL1ToL2Alias, estimateL2Transaction } from '../../../../scenario/utils/arbitrumUtils'; + +let newCometExtAddress: string; + +export default migration('1735299663_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + timelock: l2Timelock, + } = await deploymentManager.getContracts(); + + const { + arbitrumInbox, + timelock, + governor + } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + const createRetryableTicketGasParams = await estimateL2Transaction( + { + from: applyL1ToL2Alias(timelock.address), + to: bridgeReceiver.address, + data: l2ProposalData + }, + deploymentManager + ); + const refundAddress = l2Timelock.address; + + const mainnetActions = [ + // 1. Set Comet configuration and deployAndUpgradeTo WETH Comet on Arbitrum. + { + contract: arbitrumInbox, + signature: 'createRetryableTicket(address,uint256,uint256,address,address,uint256,uint256,bytes)', + args: [ + bridgeReceiver.address, // address to, + 0, // uint256 l2CallValue, + createRetryableTicketGasParams.maxSubmissionCost, // uint256 maxSubmissionCost, + refundAddress, // address excessFeeRefundAddress, + refundAddress, // address callValueRefundAddress, + createRetryableTicketGasParams.gasLimit, // uint256 gasLimit, + createRetryableTicketGasParams.maxFeePerGas, // uint256 maxFeePerGas, + l2ProposalData, // bytes calldata data + ], + value: createRetryableTicketGasParams.deposit + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts b/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..9bdec850e --- /dev/null +++ b/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,147 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299703_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + + const { + baseL1CrossDomainMessenger, + governor + } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, 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 = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/base/usdbc/migrations/1735299714_update_comet_to_support_more_collaterals.ts b/deployments/base/usdbc/migrations/1735299714_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..a78ef3c7d --- /dev/null +++ b/deployments/base/usdbc/migrations/1735299714_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,147 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299714_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + + const { + baseL1CrossDomainMessenger, + governor + } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, 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 = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/base/usdc/migrations/1735299718_update_comet_to_support_more_collaterals.ts b/deployments/base/usdc/migrations/1735299718_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..5d1501a3d --- /dev/null +++ b/deployments/base/usdc/migrations/1735299718_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,147 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299718_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + + const { + baseL1CrossDomainMessenger, + governor + } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, 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 = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/base/weth/migrations/1735299723_update_comet_to_support_more_collaterals.ts b/deployments/base/weth/migrations/1735299723_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..a9be12cdd --- /dev/null +++ b/deployments/base/weth/migrations/1735299723_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,147 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299723_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + + const { + baseL1CrossDomainMessenger, + governor + } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, 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 = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts similarity index 98% rename from deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts rename to deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts index 7235fba0c..4aa8a8743 100644 --- a/deployments/mainnet/weth/migrations/1723198576_update_comet_to_support_more_collaterals.ts +++ b/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts @@ -7,7 +7,7 @@ import { Contract } from 'ethers'; let newCometExtAddress: string; -export default migration('1723198576_update_comet_to_support_more_collaterals', { +export default migration('1735299739_update_comet_to_support_more_collaterals', { async prepare(deploymentManager: DeploymentManager) { const _assetListFactory = await deploymentManager.deploy( 'assetListFactory', diff --git a/deployments/mainnet/usds/migrations/1735299744_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/usds/migrations/1735299744_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..ed41f83a3 --- /dev/null +++ b/deployments/mainnet/usds/migrations/1735299744_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,126 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299744_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, _, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + governor, + comet, + cometAdmin, + configurator, + } = await deploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const mainnetActions = [ + // 1. Set the factory in the Configurator + { + contract: configurator, + signature: 'setFactory(address,address)', + args: [comet.address, cometFactoryExtendedAssetList], + }, + // 2. Set new CometExt as the extension delegate + { + contract: configurator, + signature: 'setExtensionDelegate(address,address)', + args: [comet.address, newCometExt], + }, + // 3. Deploy and upgrade to a new version of Comet + { + contract: cometAdmin, + signature: 'deployAndUpgradeTo(address,address)', + args: [configurator.address, comet.address], + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/mainnet/usdt/migrations/1735299748_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/usdt/migrations/1735299748_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..defc79f86 --- /dev/null +++ b/deployments/mainnet/usdt/migrations/1735299748_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,126 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299748_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, _, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + governor, + comet, + cometAdmin, + configurator, + } = await deploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const mainnetActions = [ + // 1. Set the factory in the Configurator + { + contract: configurator, + signature: 'setFactory(address,address)', + args: [comet.address, cometFactoryExtendedAssetList], + }, + // 2. Set new CometExt as the extension delegate + { + contract: configurator, + signature: 'setExtensionDelegate(address,address)', + args: [comet.address, newCometExt], + }, + // 3. Deploy and upgrade to a new version of Comet + { + contract: cometAdmin, + signature: 'deployAndUpgradeTo(address,address)', + args: [configurator.address, comet.address], + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..4049619f2 --- /dev/null +++ b/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,126 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299752_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, _, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + governor, + comet, + cometAdmin, + configurator, + } = await deploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const mainnetActions = [ + // 1. Set the factory in the Configurator + { + contract: configurator, + signature: 'setFactory(address,address)', + args: [comet.address, cometFactoryExtendedAssetList], + }, + // 2. Set new CometExt as the extension delegate + { + contract: configurator, + signature: 'setExtensionDelegate(address,address)', + args: [comet.address, newCometExt], + }, + // 3. Deploy and upgrade to a new version of Comet + { + contract: cometAdmin, + signature: 'deployAndUpgradeTo(address,address)', + args: [configurator.address, comet.address], + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/mainnet/wsteth/migrations/1735299760_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/wsteth/migrations/1735299760_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..4ee265202 --- /dev/null +++ b/deployments/mainnet/wsteth/migrations/1735299760_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,126 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299760_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, _, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + governor, + comet, + cometAdmin, + configurator, + } = await deploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const mainnetActions = [ + // 1. Set the factory in the Configurator + { + contract: configurator, + signature: 'setFactory(address,address)', + args: [comet.address, cometFactoryExtendedAssetList], + }, + // 2. Set new CometExt as the extension delegate + { + contract: configurator, + signature: 'setExtensionDelegate(address,address)', + args: [comet.address, newCometExt], + }, + // 3. Deploy and upgrade to a new version of Comet + { + contract: cometAdmin, + signature: 'deployAndUpgradeTo(address,address)', + args: [configurator.address, comet.address], + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts b/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..be1c8bb1c --- /dev/null +++ b/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,147 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299778_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + + const { + mantleL1CrossDomainMessenger, + governor + } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + const mainnetActions = [ + // 1. Set Comet configuration + deployAndUpgradeTo new Comet and set reward config on Mantle. + { + contract: mantleL1CrossDomainMessenger, + signature: 'sendMessage(address,bytes,uint32)', + args: [bridgeReceiver.address, l2ProposalData, 2_500_000], + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts b/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..b5bd49600 --- /dev/null +++ b/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,143 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299799_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + const { governor, opL1CrossDomainMessenger } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + 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 = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/optimism/usdt/migrations/1735054359_update_comet_to_support_more_collaterals.ts b/deployments/optimism/usdt/migrations/1735054359_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..efe8db336 --- /dev/null +++ b/deployments/optimism/usdt/migrations/1735054359_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,143 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735054359_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + const { governor, opL1CrossDomainMessenger } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + 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 = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/optimism/usdt/migrations/1735299805_my_migration.ts b/deployments/optimism/usdt/migrations/1735299805_my_migration.ts new file mode 100644 index 000000000..2c56259f4 --- /dev/null +++ b/deployments/optimism/usdt/migrations/1735299805_my_migration.ts @@ -0,0 +1,14 @@ +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; + +interface Vars {}; + +export default migration('1735299805_my_migration', { + prepare: async (deploymentManager: DeploymentManager) => { + return {}; + }, + + enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, vars: Vars) => { + // No governance changes + } +}); diff --git a/deployments/optimism/weth/migrations/1735054364_update_comet_to_support_more_collaterals.ts b/deployments/optimism/weth/migrations/1735054364_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..717387093 --- /dev/null +++ b/deployments/optimism/weth/migrations/1735054364_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,143 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735054364_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + const { governor, opL1CrossDomainMessenger } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + 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 = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/optimism/weth/migrations/1735299811_my_migration.ts b/deployments/optimism/weth/migrations/1735299811_my_migration.ts new file mode 100644 index 000000000..045229c67 --- /dev/null +++ b/deployments/optimism/weth/migrations/1735299811_my_migration.ts @@ -0,0 +1,14 @@ +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; + +interface Vars {}; + +export default migration('1735299811_my_migration', { + prepare: async (deploymentManager: DeploymentManager) => { + return {}; + }, + + enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, vars: Vars) => { + // No governance changes + } +}); diff --git a/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts b/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..b8fa2aa26 --- /dev/null +++ b/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,143 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299827_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + const { governor, fxRoot } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + const mainnetActions = [ + // 1. Set Comet configuration and deployAndUpgradeTo new Comet on Polygon. + { + contract: fxRoot, + signature: 'sendMessageToChild(address,bytes)', + args: [bridgeReceiver.address, l2ProposalData], + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/polygon/usdt/migrations/1735299832_update_comet_to_support_more_collaterals.ts b/deployments/polygon/usdt/migrations/1735299832_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..55e772a1c --- /dev/null +++ b/deployments/polygon/usdt/migrations/1735299832_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,143 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299832_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + const { governor, fxRoot } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + const mainnetActions = [ + // 1. Set Comet configuration and deployAndUpgradeTo new Comet on Polygon. + { + contract: fxRoot, + signature: 'sendMessageToChild(address,bytes)', + args: [bridgeReceiver.address, l2ProposalData], + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts b/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts new file mode 100644 index 000000000..36788dd99 --- /dev/null +++ b/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts @@ -0,0 +1,143 @@ +import { expect } from 'chai'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { calldata, proposal, exp } from '../../../../src/deploy'; +import { ethers } from 'ethers'; +import { Contract } from 'ethers'; +import { utils } from 'ethers'; + +let newCometExtAddress: string; + +export default migration('1735299855_update_comet_to_support_more_collaterals', { + async prepare(deploymentManager: DeploymentManager) { + const _assetListFactory = await deploymentManager.deploy( + 'assetListFactory', + 'AssetListFactory.sol', + [] + ); + + const cometFactoryExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryExtendedAssetList', + 'CometFactoryExtendedAssetList.sol', + [] + ); + const { + comet + } = await deploymentManager.getContracts(); + + const extensionDelegate = new Contract( + await comet.extensionDelegate(), + [ + 'function name() external view returns (string)', + 'function symbol() external view returns (string)', + ], + deploymentManager.hre.ethers.provider + ); + const name = await extensionDelegate.name(); + const symbol = await extensionDelegate.symbol(); + + const _newCometExt = await deploymentManager.deploy( + 'CometExtAssetList', + 'CometExtAssetList.sol', + [ + { + name32: ethers.utils.formatBytes32String(name), + symbol32: ethers.utils.formatBytes32String(symbol) + }, + _assetListFactory.address + ] + ); + return { + cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + newCometExt: _newCometExt.address + }; + }, + + async enact(deploymentManager: DeploymentManager, govDeploymentManager, { + cometFactoryExtendedAssetList, + newCometExt, + }) { + + const trace = deploymentManager.tracer(); + const { + comet, + cometAdmin, + configurator, + bridgeReceiver, + } = await deploymentManager.getContracts(); + const { governor, scrollMessenger } = await govDeploymentManager.getContracts(); + + newCometExtAddress = newCometExt; + + const setFactoryCalldata = await calldata( + configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + ); + + const setExtensionDelegateCalldata = await calldata( + configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) + ); + + const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, comet.address] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'string[]', 'bytes[]'], + [ + [configurator.address, configurator.address, cometAdmin.address], + [0, 0, 0], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + ] + ); + + const mainnetActions = [ + { + contract: scrollMessenger, + signature: 'sendMessage(address,uint256,bytes,uint256)', + args: [bridgeReceiver.address, 0, l2ProposalData, 1_000_000], + value: exp(0.2, 18) + }, + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { comet } = await deploymentManager.getContracts(); + + const cometNew = new Contract( + comet.address, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddress = await cometNew.assetList(); + + expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + }, +}); diff --git a/hardhat.config.ts b/hardhat.config.ts index 86661713e..9e0512f98 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -56,7 +56,6 @@ const { BASESCAN_KEY, OPTIMISMSCAN_KEY, MANTLESCAN_KEY, - INFURA_KEY, ANKR_KEY, MNEMONIC = 'myth like bonus scare over problem client lizard pioneer submit female collect', REPORT_GAS = 'false', @@ -158,7 +157,7 @@ const networkConfigs: NetworkConfig[] = [ ]; function getDefaultProviderURL(network: string) { - return `https://${network}.infura.io/v3/${INFURA_KEY}`; + return `https://rpc.ankr.com/${network}/${ANKR_KEY}`; } function setupDefaultNetworkProviders(hardhatConfig: HardhatUserConfig) { @@ -225,8 +224,6 @@ const config: HardhatUserConfig = { apiKey: { // Ethereum mainnet: ETHERSCAN_KEY, - ropsten: ETHERSCAN_KEY, - rinkeby: ETHERSCAN_KEY, sepolia: ETHERSCAN_KEY, // Avalanche avalanche: SNOWTRACE_KEY, diff --git a/plugins/deployment_manager/test/VerifyTest.ts b/plugins/deployment_manager/test/VerifyTest.ts index 2c63e3937..e2e48f0c6 100644 --- a/plugins/deployment_manager/test/VerifyTest.ts +++ b/plugins/deployment_manager/test/VerifyTest.ts @@ -16,12 +16,12 @@ export function mockVerifySuccess(hre: HardhatRuntimeEnvironment) { let solcList = JSON.parse(fs.readFileSync(path.join(__dirname, './SolcList.json'), 'utf8')); - // Note: we need to convince the prober task that this is sepolia, which it's not. + // Note: we need to convince the prober task that this is goerli, which it's not. // So we'll fake the network name and the chain ID hre.config.etherscan.apiKey = { - sepolia: 'SEPOLIA_KEY', + goerli: 'GOERLI_KEY', }; - hre.network.name = 'sepolia'; + hre.network.name = 'goerli'; let sendOld = hre.network.provider.send.bind(hre.network.provider); hre.network.provider.send = function (...args) { if (args.length === 1 && args[0] === 'eth_chainId') { @@ -32,7 +32,7 @@ export function mockVerifySuccess(hre: HardhatRuntimeEnvironment) { }; const solcMockPool = mockAgent.get('https://solc-bin.ethereum.org'); - const etherscanMockPool = mockAgent.get('https://api-sepolia.etherscan.io'); + const etherscanMockPool = mockAgent.get('https://api-goerli.etherscan.io'); solcMockPool.intercept({ path: '/bin/list.json', @@ -53,7 +53,7 @@ export function mockVerifySuccess(hre: HardhatRuntimeEnvironment) { path: '/api', method: 'GET', query: { - apikey: 'SEPOLIA_KEY', + apikey: 'GOERLI_KEY', module: 'contract', action: 'checkverifystatus', guid: 'MYGUID', diff --git a/plugins/scenario/utils/hreForBase.ts b/plugins/scenario/utils/hreForBase.ts index f7dd53b7d..326db975a 100644 --- a/plugins/scenario/utils/hreForBase.ts +++ b/plugins/scenario/utils/hreForBase.ts @@ -76,7 +76,7 @@ export async function forkedHreForBase(base: ForkSpec): Promise ( { $asset0: getConfigForScenario(ctx).bulkerAsset, - $asset1: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset1, } ), tokenBalances: async (ctx) => ( @@ -35,7 +35,7 @@ scenario( albert: { $base: '== 0', $asset0: getConfigForScenario(ctx).bulkerAsset, - $asset1: getConfigForScenario(ctx).bulkerAsset + $asset1: getConfigForScenario(ctx).bulkerAsset1 }, $comet: { $base: getConfigForScenario(ctx).bulkerComet }, } @@ -53,7 +53,7 @@ scenario( const { asset: collateralAssetAddress, scale: scaleBN } = asset0 === wrappedNativeToken ? { asset: asset1, scale: scale1 } : { asset: asset0, scale: scale0 }; const collateralAsset = context.getAssetByAddress(collateralAssetAddress); const collateralScale = scaleBN.toBigInt(); - const toSupplyCollateral = BigInt(getConfigForScenario(context).bulkerAsset) * collateralScale; + const toSupplyCollateral = BigInt(asset0 === wrappedNativeToken ? getConfigForScenario(context).bulkerAsset1 : getConfigForScenario(context).bulkerAsset) * collateralScale; const toBorrowBase = BigInt(getConfigForScenario(context).bulkerBorrowBase) * baseScale; const toTransferBase = BigInt(getConfigForScenario(context).bulkerBorrowAsset) * baseScale; const toSupplyEth = exp(0.01, 18); @@ -120,7 +120,7 @@ scenario( supplyCaps: async (ctx) => ( { $asset0: getConfigForScenario(ctx).bulkerAsset, - $asset1: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset1, } ), tokenBalances: async (ctx) => ( @@ -128,7 +128,7 @@ scenario( albert: { $base: '== 0', $asset0: getConfigForScenario(ctx).bulkerAsset, - $asset1: getConfigForScenario(ctx).bulkerAsset + $asset1: getConfigForScenario(ctx).bulkerAsset1 }, $comet: { $base: getConfigForScenario(ctx).bulkerComet }, } @@ -146,7 +146,7 @@ scenario( const { asset: collateralAssetAddress, scale: scaleBN } = asset0 === wrappedNativeToken ? { asset: asset1, scale: scale1 } : { asset: asset0, scale: scale0 }; const collateralAsset = context.getAssetByAddress(collateralAssetAddress); const collateralScale = scaleBN.toBigInt(); - const toSupplyCollateral = BigInt(getConfigForScenario(context).bulkerAsset) * collateralScale; + const toSupplyCollateral = BigInt(asset0 === wrappedNativeToken ? getConfigForScenario(context).bulkerAsset1 : getConfigForScenario(context).bulkerAsset) * collateralScale; const toBorrowBase = BigInt(getConfigForScenario(context).bulkerBorrowBase) * baseScale; const toTransferBase = BigInt(getConfigForScenario(context).bulkerBorrowAsset) * baseScale; const toSupplyEth = exp(0.01, 18); @@ -296,7 +296,7 @@ scenario( supplyCaps: async (ctx) => ( { $asset0: getConfigForScenario(ctx).bulkerAsset, - $asset1: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset1, } ), tokenBalances: async (ctx) => ( @@ -304,7 +304,7 @@ scenario( albert: { $base: `== ${getConfigForScenario(ctx).bulkerBase}`, $asset0: getConfigForScenario(ctx).bulkerAsset, - $asset1: getConfigForScenario(ctx).bulkerAsset + $asset1: getConfigForScenario(ctx).bulkerAsset1 }, $comet: { $base: getConfigForScenario(ctx).bulkerComet }, } @@ -324,7 +324,7 @@ scenario( const collateralScale = scaleBN.toBigInt(); const [rewardTokenAddress] = await rewards.rewardConfig(comet.address); const toSupplyBase = BigInt(getConfigForScenario(context).bulkerBase) * baseScale; - const toSupplyCollateral = BigInt(getConfigForScenario(context).bulkerAsset) * collateralScale; + const toSupplyCollateral = BigInt(asset0 === wrappedNativeToken ? getConfigForScenario(context).bulkerAsset1 : getConfigForScenario(context).bulkerAsset) * collateralScale; const toBorrowBase = BigInt(getConfigForScenario(context).bulkerBorrowBase) * baseScale; const toTransferBase = BigInt(getConfigForScenario(context).bulkerBorrowAsset) * baseScale; const toSupplyEth = exp(0.01, 18); @@ -408,7 +408,7 @@ scenario( supplyCaps: async (ctx) => ( { $asset0: getConfigForScenario(ctx).bulkerAsset, - $asset1: getConfigForScenario(ctx).bulkerAsset, + $asset1: getConfigForScenario(ctx).bulkerAsset1, } ), tokenBalances: async (ctx) => ( @@ -416,7 +416,7 @@ scenario( albert: { $base: `== ${getConfigForScenario(ctx).bulkerBase}`, $asset0: getConfigForScenario(ctx).bulkerAsset, - $asset1: getConfigForScenario(ctx).bulkerAsset + $asset1: getConfigForScenario(ctx).bulkerAsset1 }, $comet: { $base: getConfigForScenario(ctx).bulkerComet }, } @@ -436,7 +436,7 @@ scenario( const collateralScale = scaleBN.toBigInt(); const [rewardTokenAddress] = await rewards.rewardConfig(comet.address); const toSupplyBase = BigInt(getConfigForScenario(context).bulkerBase) * baseScale; - const toSupplyCollateral = BigInt(getConfigForScenario(context).bulkerAsset) * collateralScale; + const toSupplyCollateral = BigInt(asset0 === wrappedNativeToken ? getConfigForScenario(context).bulkerAsset1 : getConfigForScenario(context).bulkerAsset) * collateralScale; const toBorrowBase = BigInt(getConfigForScenario(context).bulkerBorrowBase) * baseScale; const toTransferBase = BigInt(getConfigForScenario(context).bulkerBorrowAsset) * baseScale; const toSupplyEth = exp(0.01, 18); diff --git a/scenario/context/CometContext.ts b/scenario/context/CometContext.ts index 9687cdd1c..e72b5a3dc 100644 --- a/scenario/context/CometContext.ts +++ b/scenario/context/CometContext.ts @@ -74,7 +74,7 @@ export class CometContext { } async getCompWhales(): Promise { - const useMainnetComp = ['mainnet', 'polygon', 'arbitrum', 'base', 'optimism', 'mantle'].includes(this.world.base.network); + const useMainnetComp = ['mainnet', 'polygon', 'arbitrum', 'base', 'optimism', 'scroll', 'mantle'].includes(this.world.base.network); return COMP_WHALES[useMainnetComp ? 'mainnet' : 'testnet']; } diff --git a/scenario/utils/index.ts b/scenario/utils/index.ts index 567c3c276..ccf143c19 100644 --- a/scenario/utils/index.ts +++ b/scenario/utils/index.ts @@ -299,11 +299,16 @@ export function matchesDeployment(ctx: CometContext, deploymentCriteria: Deploym export async function isRewardSupported(ctx: CometContext): Promise { const rewards = await ctx.getRewards(); const comet = await ctx.getComet(); + const COMP = await ctx.getComp(); + if (rewards == null) return false; const [rewardTokenAddress] = await rewards.rewardConfig(comet.address); if (rewardTokenAddress === constants.AddressZero) return false; + const totalSupply = await COMP.totalSupply(); + if (totalSupply.toBigInt() < exp(1, 18)) return false; + return true; } diff --git a/scenario/utils/relayScrollMessage.ts b/scenario/utils/relayScrollMessage.ts index 161b4bccb..4b7672778 100644 --- a/scenario/utils/relayScrollMessage.ts +++ b/scenario/utils/relayScrollMessage.ts @@ -48,10 +48,19 @@ export default async function relayScrollMessage( await setNextBaseFeeToZero(bridgeDeploymentManager); - let aliasAccount = await impersonateAddress( - bridgeDeploymentManager, - applyL1ToL2Alias(scrollMessenger.address) - ); + let aliasAccount; + if (bridgeDeploymentManager.network == 'scroll-goerli'){ + aliasAccount = await impersonateAddress( + bridgeDeploymentManager, + '0xD69c917c7F1C0a724A51c189B4A8F4F8C8E8cA0a' + ); + } else { + aliasAccount = await impersonateAddress( + bridgeDeploymentManager, + applyL1ToL2Alias(scrollMessenger.address) + ); + } + const relayMessageTxn = await ( await l2Messenger.connect(aliasAccount).relayMessage( sender, @@ -72,21 +81,21 @@ export default async function relayScrollMessage( // 2. Cross-chain message passing if (target === l2ERC20Gateway.address) { // 1a. Bridging ERC20 token - const { l1Token, _l2Token, _from, to, amount, _data } = ethers.utils.defaultAbiCoder.decode( + const [ l1Token, _l2Token, _from, to, amount, _data ] = ethers.utils.defaultAbiCoder.decode( ['address _l1Token', 'address _l2Token','address _from', 'address _to','uint256 _amount', 'bytes _data'], messageWithoutSigHash ); - + console.log( `[${governanceDeploymentManager.network} -> ${bridgeDeploymentManager.network}] Bridged over ${amount} of ${l1Token} to user ${to}` ); } else if (target === l2ETHGateway.address){ // 1a. Bridging ETH - const { _from, to, amount, _data } = ethers.utils.defaultAbiCoder.decode( + const [ _from, to, amount, _data ] = ethers.utils.defaultAbiCoder.decode( ['address _from', 'address _to', 'uint256 _amount', 'bytes _data'], messageWithoutSigHash ); - + const oldBalance = await bridgeDeploymentManager.hre.ethers.provider.getBalance(to); const newBalance = oldBalance.add(BigNumber.from(amount)); // This is our best attempt to mimic the deposit transaction type (not supported in Hardhat) that Optimism uses to deposit ETH to an L2 address @@ -94,48 +103,48 @@ export default async function relayScrollMessage( to, ethers.utils.hexStripZeros(newBalance.toHexString()), ]); - + console.log( `[${governanceDeploymentManager.network} -> ${bridgeDeploymentManager.network}] Bridged over ${amount} of ETH to user ${to}` ); }else if (target === l2WETHGateway.address){ // 1c. Bridging WETH - const { _l1Token, _l2Token, _from, to, amount, _data } = ethers.utils.defaultAbiCoder.decode( + const [ _l1Token, _l2Token, _from, to, amount, _data ] = ethers.utils.defaultAbiCoder.decode( ['address _l1Token', 'address _l2Token','address _from', 'address _to','uint256 _amount', 'bytes _data'], messageWithoutSigHash ); - + console.log( `[${governanceDeploymentManager.network} -> ${bridgeDeploymentManager.network}] Bridged over ${amount} of WETH to user ${to}` ); } else if (target === l2WstETHGateway.address){ // 1d. Bridging WstETH - const { _l1Token, _l2Token, _from, to, amount, _data } = ethers.utils.defaultAbiCoder.decode( + const [ _l1Token, _l2Token, _from, to, amount, _data ] = ethers.utils.defaultAbiCoder.decode( ['address _l1Token', 'address _l2Token','address _from', 'address _to','uint256 _amount', 'bytes _data'], messageWithoutSigHash ); - + console.log( `[${governanceDeploymentManager.network} -> ${bridgeDeploymentManager.network}] Bridged over ${amount} of WstETH to user ${to}` ); } else if (target === bridgeReceiver.address) { // Cross-chain message passing - const proposalCreatedEvent = relayMessageTxn.events.find(event => event.address === bridgeReceiver.address); + const proposalCreatedEvent = relayMessageTxn.events.find(event => event.address.toLowerCase() === bridgeReceiver.address.toLowerCase()); const { args: { id, eta } } = bridgeReceiver.interface.parseLog(proposalCreatedEvent); - + // Add the proposal to the list of open bridged proposals to be executed after all the messages have been relayed openBridgedProposals.push({ id, eta }); } else { throw new Error(`[${governanceDeploymentManager.network} -> ${bridgeDeploymentManager.network}] Unrecognized target for cross-chain message`); } } - + // Execute open bridged proposals now that all messages have been bridged for (let proposal of openBridgedProposals) { const { eta, id } = proposal; // Fast forward l2 time await setNextBlockTimestamp(bridgeDeploymentManager, eta.toNumber() + 1); - + // Execute queued proposal await setNextBaseFeeToZero(bridgeDeploymentManager); await bridgeReceiver.executeProposal(id, { gasPrice: 0 }); diff --git a/scenario/utils/scenarioHelper.ts b/scenario/utils/scenarioHelper.ts index a5a8d82a7..9d2ddbc76 100644 --- a/scenario/utils/scenarioHelper.ts +++ b/scenario/utils/scenarioHelper.ts @@ -3,6 +3,7 @@ import { CometContext } from '../context/CometContext'; const config = { bulkerBase: 1000000, bulkerAsset: 5000, + bulkerAsset1: 5000, bulkerComet: 5000, bulkerBorrowBase: 1000, bulkerBorrowAsset: 500, @@ -24,6 +25,7 @@ export function getConfigForScenario(ctx: CometContext) { if (ctx.world.base.network === 'mainnet' && ctx.world.base.deployment === 'wbtc') { config.bulkerBase = 5000; config.bulkerAsset = 200; + config.bulkerAsset1 = 200; config.bulkerComet = 200; config.bulkerBorrowBase = 100; config.bulkerBorrowAsset = 50; @@ -66,11 +68,21 @@ export function getConfigForScenario(ctx: CometContext) { if (ctx.world.base.network === 'polygon' && ctx.world.base.deployment === 'usdc') { config.bulkerAsset = 200; + config.bulkerAsset1 = 200; } if (ctx.world.base.network === 'polygon' && ctx.world.base.deployment === 'usdt') { config.withdrawAsset = 10000; } + if (ctx.world.base.network === 'scroll' && ctx.world.base.deployment === 'usdc') { + config.bulkerAsset = 500; + config.bulkerAsset1 = 500; + } + + if (ctx.world.base.network === 'sepolia' && ctx.world.base.deployment === 'usdc') { + config.bulkerAsset1 = 10; + } + return config; } \ No newline at end of file diff --git a/src/deploy/index.ts b/src/deploy/index.ts index 938362227..134c23a91 100644 --- a/src/deploy/index.ts +++ b/src/deploy/index.ts @@ -128,7 +128,8 @@ export const WHALES = { '0xb125E6687d4313864e53df431d5425969c15Eb2F', // cbETH whale ], scroll: [ - '0xaaaaAAAACB71BF2C8CaE522EA5fa455571A74106' // USDC whale + '0xaaaaAAAACB71BF2C8CaE522EA5fa455571A74106', // USDC whale + '0x5B1322eeb46240b02e20062b8F0F9908d525B09c', // wstETH whale ], optimism: [ '0x2A82Ae142b2e62Cb7D10b55E323ACB1Cab663a26', // OP whale From c7920112e5a511604411a2d871fafdc6cbf33370 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Fri, 27 Dec 2024 15:25:10 +0200 Subject: [PATCH 28/45] fix --- .../usdt/migrations/1735299805_my_migration.ts | 14 -------------- ...05_update_comet_to_support_more_collaterals.ts} | 2 +- .../weth/migrations/1735299811_my_migration.ts | 14 -------------- ...11_update_comet_to_support_more_collaterals.ts} | 2 +- hardhat.config.ts | 3 ++- 5 files changed, 4 insertions(+), 31 deletions(-) delete mode 100644 deployments/optimism/usdt/migrations/1735299805_my_migration.ts rename deployments/optimism/usdt/migrations/{1735054359_update_comet_to_support_more_collaterals.ts => 1735299805_update_comet_to_support_more_collaterals.ts} (98%) delete mode 100644 deployments/optimism/weth/migrations/1735299811_my_migration.ts rename deployments/optimism/weth/migrations/{1735054364_update_comet_to_support_more_collaterals.ts => 1735299811_update_comet_to_support_more_collaterals.ts} (98%) diff --git a/deployments/optimism/usdt/migrations/1735299805_my_migration.ts b/deployments/optimism/usdt/migrations/1735299805_my_migration.ts deleted file mode 100644 index 2c56259f4..000000000 --- a/deployments/optimism/usdt/migrations/1735299805_my_migration.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; - -interface Vars {}; - -export default migration('1735299805_my_migration', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, vars: Vars) => { - // No governance changes - } -}); diff --git a/deployments/optimism/usdt/migrations/1735054359_update_comet_to_support_more_collaterals.ts b/deployments/optimism/usdt/migrations/1735299805_update_comet_to_support_more_collaterals.ts similarity index 98% rename from deployments/optimism/usdt/migrations/1735054359_update_comet_to_support_more_collaterals.ts rename to deployments/optimism/usdt/migrations/1735299805_update_comet_to_support_more_collaterals.ts index efe8db336..aaeaf80ad 100644 --- a/deployments/optimism/usdt/migrations/1735054359_update_comet_to_support_more_collaterals.ts +++ b/deployments/optimism/usdt/migrations/1735299805_update_comet_to_support_more_collaterals.ts @@ -8,7 +8,7 @@ import { utils } from 'ethers'; let newCometExtAddress: string; -export default migration('1735054359_update_comet_to_support_more_collaterals', { +export default migration('1735299805_update_comet_to_support_more_collaterals', { async prepare(deploymentManager: DeploymentManager) { const _assetListFactory = await deploymentManager.deploy( 'assetListFactory', diff --git a/deployments/optimism/weth/migrations/1735299811_my_migration.ts b/deployments/optimism/weth/migrations/1735299811_my_migration.ts deleted file mode 100644 index 045229c67..000000000 --- a/deployments/optimism/weth/migrations/1735299811_my_migration.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; -import { migration } from '../../../../plugins/deployment_manager/Migration'; - -interface Vars {}; - -export default migration('1735299811_my_migration', { - prepare: async (deploymentManager: DeploymentManager) => { - return {}; - }, - - enact: async (deploymentManager: DeploymentManager, govDeploymentManager: DeploymentManager, vars: Vars) => { - // No governance changes - } -}); diff --git a/deployments/optimism/weth/migrations/1735054364_update_comet_to_support_more_collaterals.ts b/deployments/optimism/weth/migrations/1735299811_update_comet_to_support_more_collaterals.ts similarity index 98% rename from deployments/optimism/weth/migrations/1735054364_update_comet_to_support_more_collaterals.ts rename to deployments/optimism/weth/migrations/1735299811_update_comet_to_support_more_collaterals.ts index 717387093..9ffa7939a 100644 --- a/deployments/optimism/weth/migrations/1735054364_update_comet_to_support_more_collaterals.ts +++ b/deployments/optimism/weth/migrations/1735299811_update_comet_to_support_more_collaterals.ts @@ -8,7 +8,7 @@ import { utils } from 'ethers'; let newCometExtAddress: string; -export default migration('1735054364_update_comet_to_support_more_collaterals', { +export default migration('1735299811_update_comet_to_support_more_collaterals', { async prepare(deploymentManager: DeploymentManager) { const _assetListFactory = await deploymentManager.deploy( 'assetListFactory', diff --git a/hardhat.config.ts b/hardhat.config.ts index 9e0512f98..dd2b601b1 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -56,6 +56,7 @@ const { BASESCAN_KEY, OPTIMISMSCAN_KEY, MANTLESCAN_KEY, + SCROLLSCAN_KEY, ANKR_KEY, MNEMONIC = 'myth like bonus scare over problem client lizard pioneer submit female collect', REPORT_GAS = 'false', @@ -241,7 +242,7 @@ const config: HardhatUserConfig = { // Mantle mantle: MANTLESCAN_KEY, // Scroll - 'scroll': ETHERSCAN_KEY, + scroll: SCROLLSCAN_KEY, }, customChains: [ { From 9d67b3362ef15a1a1ca7518ee8be88bbaebf5ed2 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Fri, 27 Dec 2024 16:04:15 +0200 Subject: [PATCH 29/45] fix: secret fix for scroll --- .github/workflows/run-scenarios.yaml | 1 + plugins/scenario/Runner.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-scenarios.yaml b/.github/workflows/run-scenarios.yaml index 9590bd18c..49d63b2a1 100644 --- a/.github/workflows/run-scenarios.yaml +++ b/.github/workflows/run-scenarios.yaml @@ -20,6 +20,7 @@ jobs: LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} runs-on: ubuntu-latest steps: - name: Checkout repository diff --git a/plugins/scenario/Runner.ts b/plugins/scenario/Runner.ts index 1791e3198..e7df109cf 100644 --- a/plugins/scenario/Runner.ts +++ b/plugins/scenario/Runner.ts @@ -154,7 +154,7 @@ export class Runner { } -async function retry(fn: () => Promise, retries: number = 10, timeLimit?: number, wait: number = 100) { +async function retry(fn: () => Promise, retries: number = 10, timeLimit?: number, wait: number = 250) { try { return await asyncCallWithTimeout(fn(), timeLimit); } catch (e) { From 978dec091b40219f52bfa859f3e6f6f5302405bb Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Fri, 27 Dec 2024 16:06:10 +0200 Subject: [PATCH 30/45] fix: increase arbitrary number --- plugins/scenario/utils/hreForBase.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scenario/utils/hreForBase.ts b/plugins/scenario/utils/hreForBase.ts index 326db975a..7855d8b77 100644 --- a/plugins/scenario/utils/hreForBase.ts +++ b/plugins/scenario/utils/hreForBase.ts @@ -77,7 +77,7 @@ export async function forkedHreForBase(base: ForkSpec): Promise Date: Fri, 27 Dec 2024 16:31:07 +0200 Subject: [PATCH 31/45] fix: scroll scan fix --- .github/workflows/deploy-market.yaml | 1 + .github/workflows/enact-migration.yaml | 1 + .github/workflows/prepare-migration.yaml | 1 + .github/workflows/run-contract-linter.yaml | 1 + .github/workflows/run-coverage.yaml | 1 + .github/workflows/run-eslint.yaml | 1 + .github/workflows/run-forge-tests.yaml | 1 + .github/workflows/run-gas-profiler.yaml | 1 + .github/workflows/run-semgrep.yaml | 1 + .github/workflows/run-unit-tests.yaml | 1 + hardhat.config.ts | 3 ++- plugins/import/etherscan.ts | 2 +- 12 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-market.yaml b/.github/workflows/deploy-market.yaml index 9fea27076..374a58bae 100644 --- a/.github/workflows/deploy-market.yaml +++ b/.github/workflows/deploy-market.yaml @@ -38,6 +38,7 @@ jobs: LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} steps: - name: Seacrest uses: hayesgm/seacrest@5748b3a066f517973ca2ca03d0af39bbf2b82d10 diff --git a/.github/workflows/enact-migration.yaml b/.github/workflows/enact-migration.yaml index 3de7f204a..9dfa8079a 100644 --- a/.github/workflows/enact-migration.yaml +++ b/.github/workflows/enact-migration.yaml @@ -55,6 +55,7 @@ jobs: LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} steps: - name: Get governance network run: | diff --git a/.github/workflows/prepare-migration.yaml b/.github/workflows/prepare-migration.yaml index 2ba4f7213..9bd5f8334 100644 --- a/.github/workflows/prepare-migration.yaml +++ b/.github/workflows/prepare-migration.yaml @@ -40,6 +40,7 @@ jobs: LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} steps: - name: Seacrest uses: hayesgm/seacrest@5748b3a066f517973ca2ca03d0af39bbf2b82d10 diff --git a/.github/workflows/run-contract-linter.yaml b/.github/workflows/run-contract-linter.yaml index 731cb5e1e..cc840f887 100644 --- a/.github/workflows/run-contract-linter.yaml +++ b/.github/workflows/run-contract-linter.yaml @@ -16,6 +16,7 @@ jobs: LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/run-coverage.yaml b/.github/workflows/run-coverage.yaml index cb3672b14..7eff80fba 100644 --- a/.github/workflows/run-coverage.yaml +++ b/.github/workflows/run-coverage.yaml @@ -18,6 +18,7 @@ jobs: LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/run-eslint.yaml b/.github/workflows/run-eslint.yaml index 3e9a3e05c..42b758479 100644 --- a/.github/workflows/run-eslint.yaml +++ b/.github/workflows/run-eslint.yaml @@ -16,6 +16,7 @@ jobs: LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/run-forge-tests.yaml b/.github/workflows/run-forge-tests.yaml index 42b4dcbed..700518839 100644 --- a/.github/workflows/run-forge-tests.yaml +++ b/.github/workflows/run-forge-tests.yaml @@ -31,6 +31,7 @@ jobs: LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} - name: Build Comet with older solc versions run: | diff --git a/.github/workflows/run-gas-profiler.yaml b/.github/workflows/run-gas-profiler.yaml index 62fb5879e..fb6718e73 100644 --- a/.github/workflows/run-gas-profiler.yaml +++ b/.github/workflows/run-gas-profiler.yaml @@ -17,6 +17,7 @@ jobs: LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/run-semgrep.yaml b/.github/workflows/run-semgrep.yaml index 533539d05..e329c9813 100644 --- a/.github/workflows/run-semgrep.yaml +++ b/.github/workflows/run-semgrep.yaml @@ -21,6 +21,7 @@ jobs: POLYGONSCAN_KEY: ${{ secrets.POLYGONSCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} container: # A Docker image with Semgrep installed. Do not change this. image: returntocorp/semgrep diff --git a/.github/workflows/run-unit-tests.yaml b/.github/workflows/run-unit-tests.yaml index 452207832..a5e2d681d 100644 --- a/.github/workflows/run-unit-tests.yaml +++ b/.github/workflows/run-unit-tests.yaml @@ -16,6 +16,7 @@ jobs: LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} MANTLESCAN_KEY: ${{ secrets.MANTLESCAN_KEY }} + SCROLLSCAN_KEY: ${{ secrets.SCROLLSCAN_KEY }} steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/hardhat.config.ts b/hardhat.config.ts index dd2b601b1..a50fbd87a 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -90,6 +90,7 @@ export function requireEnv(varName, msg?: string): string { 'LINEASCAN_KEY', 'OPTIMISMSCAN_KEY', 'MANTLESCAN_KEY', + 'SCROLLSCAN_KEY' ].map((v) => requireEnv(v)); // Networks @@ -242,7 +243,7 @@ const config: HardhatUserConfig = { // Mantle mantle: MANTLESCAN_KEY, // Scroll - scroll: SCROLLSCAN_KEY, + 'scroll': SCROLLSCAN_KEY, }, customChains: [ { diff --git a/plugins/import/etherscan.ts b/plugins/import/etherscan.ts index c770ff1a1..c16016a4d 100644 --- a/plugins/import/etherscan.ts +++ b/plugins/import/etherscan.ts @@ -65,7 +65,7 @@ export function getEtherscanApiKey(network: string): string { base: process.env.BASESCAN_KEY, optimism: process.env.OPTIMISMSCAN_KEY, mantle: process.env.MANTLESCAN_KEY, - scroll: process.env.ETHERSCAN_KEY + scroll: process.env.SCROLLSCAN_KEY }[network]; if (!apiKey) { From 6a7f18a90b131133bc6b6feae82a947a095c09fc Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Mon, 6 Jan 2025 19:29:58 +0200 Subject: [PATCH 32/45] feat: migrations and descriptions --- ...pdate_comet_to_support_more_collaterals.ts | 112 ++++++++++++++++-- ...pdate_comet_to_support_more_collaterals.ts | 109 ++++++++++++++++- ...pdate_comet_to_support_more_collaterals.ts | 87 ++++++++++++-- ...pdate_comet_to_support_more_collaterals.ts | 35 +++++- ...pdate_comet_to_support_more_collaterals.ts | 2 +- ...pdate_comet_to_support_more_collaterals.ts | 78 +++++++++++- ...pdate_comet_to_support_more_collaterals.ts | 36 +++++- ...pdate_comet_to_support_more_collaterals.ts | 2 +- plugins/scenario/utils/hreForBase.ts | 2 +- scenario/utils/index.ts | 2 +- src/deploy/index.ts | 3 +- 11 files changed, 428 insertions(+), 40 deletions(-) diff --git a/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts b/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts index b55987a78..f439de569 100644 --- a/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts +++ b/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts @@ -9,6 +9,10 @@ import { applyL1ToL2Alias, estimateL2Transaction } from '../../../../scenario/ut let newCometExtAddress: string; +const USDCE_COMET = '0xA5EDBDD9646f8dFF606d7448e414884C7d905dCA'; +const USDT_COMET = '0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07'; +const WETH_COMET = '0x6f7D514bbD4aFf3BcD1140B7344b32f063dEe486'; + export default migration('1735299626_update_comet_to_support_more_collaterals', { async prepare(deploymentManager: DeploymentManager) { const _assetListFactory = await deploymentManager.deploy( @@ -79,27 +83,83 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', const setFactoryCalldata = await calldata( configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) ); - const setExtensionDelegateCalldata = await calldata( configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) ); - const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( ['address', 'address'], [configurator.address, comet.address] ); + const setFactoryCalldataUSDCE = await calldata( + configurator.populateTransaction.setFactory(USDCE_COMET, cometFactoryExtendedAssetList) + ); + const setExtensionDelegateCalldataUSDCE = await calldata( + configurator.populateTransaction.setExtensionDelegate(USDCE_COMET, newCometExt) + ); + const deployAndUpgradeToCalldataUSDCE = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, USDCE_COMET] + ); + + const setFactoryCalldataUSDT = await calldata( + configurator.populateTransaction.setFactory(USDT_COMET, cometFactoryExtendedAssetList) + ); + const setExtensionDelegateCalldataUSDT = await calldata( + configurator.populateTransaction.setExtensionDelegate(USDT_COMET, newCometExt) + ); + const deployAndUpgradeToCalldataUSDT = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, USDT_COMET] + ); + + const setFactoryCalldataWETH = await calldata( + configurator.populateTransaction.setFactory(WETH_COMET, cometFactoryExtendedAssetList) + ); + const setExtensionDelegateCalldataWETH = await calldata( + configurator.populateTransaction.setExtensionDelegate(WETH_COMET, newCometExt) + ); + const deployAndUpgradeToCalldataWETH = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, WETH_COMET] + ); + + const l2ProposalData = utils.defaultAbiCoder.encode( ['address[]', 'uint256[]', 'string[]', 'bytes[]'], [ - [configurator.address, configurator.address, cometAdmin.address], - [0, 0, 0], [ + configurator.address, configurator.address, cometAdmin.address, + configurator.address, configurator.address, cometAdmin.address, + configurator.address, configurator.address, cometAdmin.address, + configurator.address, configurator.address, cometAdmin.address, + ], + [ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + ], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', 'setFactory(address,address)', 'setExtensionDelegate(address,address)', 'deployAndUpgradeTo(address,address)', ], - [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + [ + setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata, + setFactoryCalldataUSDCE, setExtensionDelegateCalldataUSDCE, deployAndUpgradeToCalldataUSDCE, + setFactoryCalldataUSDT, setExtensionDelegateCalldataUSDT, deployAndUpgradeToCalldataUSDT, + setFactoryCalldataWETH, setExtensionDelegateCalldataWETH, deployAndUpgradeToCalldataWETH, + ], ] ); @@ -114,7 +174,7 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', const refundAddress = l2Timelock.address; const mainnetActions = [ - // 1. Set Comet configuration and deployAndUpgradeTo WETH Comet on Arbitrum. + // 1. Sends the proposal to the L2 { contract: arbitrumInbox, signature: 'createRetryableTicket(address,uint256,uint256,address,address,uint256,uint256,bytes)', @@ -132,7 +192,7 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', }, ]; - const description = 'DESCRIPTION'; + const description = '# Update USDC, USDT, WETH and USDC.e Comets on Arbitrum to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 4 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDT, USDC, WETH and USDC.e markets on Arbitrum. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cUSDTv3, cUSDCv3, cWETHv3 and cUSDCev3.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) @@ -164,7 +224,45 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', const assetListAddress = await cometNew.assetList(); expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewUSDCE = new Contract( + USDCE_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddressUSDCE = await cometNewUSDCE.assetList(); + + expect(assetListAddressUSDCE).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewUSDT = new Contract( + USDT_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddressUSDT = await cometNewUSDT.assetList(); + + expect(assetListAddressUSDT).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewWETH = new Contract( + WETH_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddressWETH = await cometNewWETH.assetList(); + expect(assetListAddressWETH).to.not.be.equal(ethers.constants.AddressZero); expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); }, }); diff --git a/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts b/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts index 9bdec850e..7422f9500 100644 --- a/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts +++ b/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts @@ -8,6 +8,10 @@ import { utils } from 'ethers'; let newCometExtAddress: string; +const USDC_COMET = '0xb125E6687d4313864e53df431d5425969c15Eb2F'; +const WETH_COMET = '0x46e6b214b524310239732D51387075E0e70970bf'; +const USDBC_COMET = '0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf'; + export default migration('1735299703_update_comet_to_support_more_collaterals', { async prepare(deploymentManager: DeploymentManager) { const _assetListFactory = await deploymentManager.deploy( @@ -76,27 +80,82 @@ export default migration('1735299703_update_comet_to_support_more_collaterals', const setFactoryCalldata = await calldata( configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) ); - const setExtensionDelegateCalldata = await calldata( configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) ); - const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( ['address', 'address'], [configurator.address, comet.address] ); + const setFactoryCalldataUSDC = await calldata( + configurator.populateTransaction.setFactory(USDC_COMET, cometFactoryExtendedAssetList) + ); + const setExtensionDelegateCalldataUSDC = await calldata( + configurator.populateTransaction.setExtensionDelegate(USDC_COMET, newCometExt) + ); + const deployAndUpgradeToCalldataUSDC = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, USDC_COMET] + ); + + const setFactoryCalldataWETH = await calldata( + configurator.populateTransaction.setFactory(WETH_COMET, cometFactoryExtendedAssetList) + ); + const setExtensionDelegateCalldataWETH = await calldata( + configurator.populateTransaction.setExtensionDelegate(WETH_COMET, newCometExt) + ); + const deployAndUpgradeToCalldataWETH = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, WETH_COMET] + ); + + const setFactoryCalldataUSDBC = await calldata( + configurator.populateTransaction.setFactory(USDBC_COMET, cometFactoryExtendedAssetList) + ); + const setExtensionDelegateCalldataUSDBC = await calldata( + configurator.populateTransaction.setExtensionDelegate(USDBC_COMET, newCometExt) + ); + const deployAndUpgradeToCalldataUSDBC = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, USDBC_COMET] + ); + const l2ProposalData = utils.defaultAbiCoder.encode( ['address[]', 'uint256[]', 'string[]', 'bytes[]'], [ - [configurator.address, configurator.address, cometAdmin.address], - [0, 0, 0], + [ + configurator.address, configurator.address, cometAdmin.address, + configurator.address, configurator.address, cometAdmin.address, + configurator.address, configurator.address, cometAdmin.address, + configurator.address, configurator.address, cometAdmin.address, + ], + [ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + ], [ 'setFactory(address,address)', 'setExtensionDelegate(address,address)', 'deployAndUpgradeTo(address,address)', + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [ + setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata, + setFactoryCalldataUSDC, setExtensionDelegateCalldataUSDC, deployAndUpgradeToCalldataUSDC, + setFactoryCalldataWETH, setExtensionDelegateCalldataWETH, deployAndUpgradeToCalldataWETH, + setFactoryCalldataUSDBC, setExtensionDelegateCalldataUSDBC, deployAndUpgradeToCalldataUSDBC, ], - [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], ] ); @@ -109,7 +168,7 @@ export default migration('1735299703_update_comet_to_support_more_collaterals', }, ]; - const description = 'DESCRIPTION'; + const description = '# Update AERO, USDC, WETH and USDbC Comets on Base to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 4 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update a Compound III AERO, USDC, WETH and USDbC markets 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cAEROv3, cUSDCv3, cWETHv3 and cUSDbCv3.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) @@ -141,7 +200,45 @@ export default migration('1735299703_update_comet_to_support_more_collaterals', const assetListAddress = await cometNew.assetList(); expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewUSDC = new Contract( + USDC_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddressUSDC = await cometNewUSDC.assetList(); + + expect(assetListAddressUSDC).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewWETH = new Contract( + WETH_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddressWETH = await cometNewWETH.assetList(); + + expect(assetListAddressWETH).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewUSDBC = new Contract( + USDBC_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddressUSDBC = await cometNewUSDBC.assetList(); + expect(assetListAddressUSDBC).to.not.be.equal(ethers.constants.AddressZero); expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); }, }); diff --git a/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts index 4aa8a8743..b40c9bf6d 100644 --- a/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts +++ b/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts @@ -7,6 +7,9 @@ import { Contract } from 'ethers'; let newCometExtAddress: string; +const USDS_COMET = '0x5D409e56D886231aDAf00c8775665AD0f9897b56'; +const USDT_COMET = '0x3Afdc9BCA9213A35503b077a6072F3D0d5AB0840'; + export default migration('1735299739_update_comet_to_support_more_collaterals', { async prepare(deploymentManager: DeploymentManager) { const _assetListFactory = await deploymentManager.deploy( @@ -68,27 +71,70 @@ export default migration('1735299739_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const mainnetActions = [ - // 1. Set the factory in the Configurator + // 1. Set the factory in the Configurator for the USDC comet { contract: configurator, signature: 'setFactory(address,address)', args: [comet.address, cometFactoryExtendedAssetList], }, - // 2. Set new CometExt as the extension delegate + // 2. Set the factory in the Configurator for the USDS comet + { + contract: configurator, + signature: 'setFactory(address,address)', + args: [USDS_COMET, cometFactoryExtendedAssetList], + }, + // 3. Set the factory in the Configurator for the USDT comet + { + contract: configurator, + signature: 'setFactory(address,address)', + args: [USDT_COMET, cometFactoryExtendedAssetList], + }, + // 4. Set new CometExt as the extension delegate for the USDC comet + { + contract: configurator, + signature: 'setExtensionDelegate(address,address)', + args: [comet.address, newCometExt], + }, + // 5. Set new CometExt as the extension delegate for the USDS comet + { + contract: configurator, + signature: 'setExtensionDelegate(address,address)', + args: [USDS_COMET, newCometExt], + }, + // 6. Set new CometExt as the extension delegate for the USDT comet { contract: configurator, signature: 'setExtensionDelegate(address,address)', - args: [comet.address, newCometExt], + args: [USDT_COMET, newCometExt], }, - // 3. Deploy and upgrade to a new version of Comet + // 7. Deploy and upgrade to a new version of Comet for the USDC comet { contract: cometAdmin, signature: 'deployAndUpgradeTo(address,address)', args: [configurator.address, comet.address], }, + // 8. Deploy and upgrade to a new version of Comet for the USDS comet + { + contract: cometAdmin, + signature: 'deployAndUpgradeTo(address,address)', + args: [configurator.address, USDS_COMET], + }, + // 9. Deploy and upgrade to a new version of Comet for the USDT comet + { + contract: cometAdmin, + signature: 'deployAndUpgradeTo(address,address)', + args: [configurator.address, USDT_COMET], + }, ]; - const description = 'DESCRIPTION'; + const { timelock } = await deploymentManager.getContracts(); + // impersonate the timelock + await deploymentManager.hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [timelock.address], + }); + + const description = '# Update USDC, USDT and USDS Comets on Mainnet to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 3 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update a Compound III USDC, USDT and USDS markets on Ethereum. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory for cUSDCv3 to the newly deployed factory.\n\nThe second action sets the extension delegate for cUSDCv3 to the newly deployed contract.\n\nThe third action deploys and upgrades cUSDCv3 to a new version.\n\nThe fourth action sets the factory for cUSDTv3 to the newly deployed factory.\n\nThe fifth action sets the extension delegate for cUSDTv3 to the newly deployed contract.\n\nThe sixth action deploys and upgrades cUSDTv3 to a new version.\n\nThe seventh action sets the factory for cUSDSv3 to the newly deployed factory.\n\nThe eighth action sets the extension delegate for cUSDSv3 to the newly deployed contract.\n\nThe ninth action deploys and upgrades cUSDSv3 to a new version.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) @@ -109,7 +155,7 @@ export default migration('1735299739_update_comet_to_support_more_collaterals', async verify(deploymentManager: DeploymentManager) { const { comet } = await deploymentManager.getContracts(); - const cometNew = new Contract( + const cometNewUSDC = new Contract( comet.address, [ 'function assetList() external view returns (address)', @@ -117,10 +163,35 @@ export default migration('1735299739_update_comet_to_support_more_collaterals', deploymentManager.hre.ethers.provider ); - const assetListAddress = await cometNew.assetList(); + const assetListAddressUSDC = await cometNewUSDC.assetList(); + + expect(assetListAddressUSDC).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewUSDS = new Contract( + USDS_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddressUSDS = await cometNewUSDS.assetList(); + + expect(assetListAddressUSDS).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewUSDT = new Contract( + USDT_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); - expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + const assetListAddressUSDT = await cometNewUSDT.assetList(); + expect(assetListAddressUSDT).to.not.be.equal(ethers.constants.AddressZero); expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); }, }); diff --git a/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts index 4049619f2..f6544a716 100644 --- a/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts +++ b/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts @@ -6,6 +6,7 @@ import { ethers } from 'ethers'; import { Contract } from 'ethers'; let newCometExtAddress: string; +const WSTETH_COMET = '0x3D0bb1ccaB520A66e607822fC55BC921738fAFE3'; export default migration('1735299752_update_comet_to_support_more_collaterals', { async prepare(deploymentManager: DeploymentManager) { @@ -74,18 +75,36 @@ export default migration('1735299752_update_comet_to_support_more_collaterals', signature: 'setFactory(address,address)', args: [comet.address, cometFactoryExtendedAssetList], }, - // 2. Set new CometExt as the extension delegate + // 2. Set the factory in the Configurator + { + contract: configurator, + signature: 'setFactory(address,address)', + args: [WSTETH_COMET, cometFactoryExtendedAssetList], + }, + // 3. Set new CometExt as the extension delegate { contract: configurator, signature: 'setExtensionDelegate(address,address)', args: [comet.address, newCometExt], }, - // 3. Deploy and upgrade to a new version of Comet + // 4. Set new CometExt as the extension delegate + { + contract: configurator, + signature: 'setExtensionDelegate(address,address)', + args: [WSTETH_COMET, newCometExt], + }, + // 5. Deploy and upgrade to a new version of Comet { contract: cometAdmin, signature: 'deployAndUpgradeTo(address,address)', args: [configurator.address, comet.address], }, + // 6. Deploy and upgrade to a new version of Comet + { + contract: cometAdmin, + signature: 'deployAndUpgradeTo(address,address)', + args: [configurator.address, WSTETH_COMET], + }, ]; const description = 'DESCRIPTION'; @@ -120,7 +139,19 @@ export default migration('1735299752_update_comet_to_support_more_collaterals', const assetListAddress = await cometNew.assetList(); expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewWSTETH = new Contract( + WSTETH_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddressWSTETH = await cometNewWSTETH.assetList(); + expect(assetListAddressWSTETH).to.not.be.equal(ethers.constants.AddressZero); expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); }, }); diff --git a/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts b/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts index be1c8bb1c..af0123e6d 100644 --- a/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts +++ b/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts @@ -109,7 +109,7 @@ export default migration('1735299778_update_comet_to_support_more_collaterals', }, ]; - const description = 'DESCRIPTION'; + const description = '# Update USDe Comet on Mantle to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update Mantle cUSDeV3 Comet to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDe markets on Mantle. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) diff --git a/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts b/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts index b5bd49600..5f4082a5a 100644 --- a/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts +++ b/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts @@ -8,6 +8,9 @@ import { utils } from 'ethers'; let newCometExtAddress: string; +const USDT_COMET = '0x995E394b8B2437aC8Ce61Ee0bC610D617962B214'; +const WETH_COMET = '0xE36A30D249f7761327fd973001A32010b521b6Fd'; + export default migration('1735299799_update_comet_to_support_more_collaterals', { async prepare(deploymentManager: DeploymentManager) { const _assetListFactory = await deploymentManager.deploy( @@ -72,27 +75,65 @@ export default migration('1735299799_update_comet_to_support_more_collaterals', const setFactoryCalldata = await calldata( configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) ); - const setExtensionDelegateCalldata = await calldata( configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) ); - const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( ['address', 'address'], [configurator.address, comet.address] ); + const setFactoryCalldataUSDT = await calldata( + configurator.populateTransaction.setFactory(USDT_COMET, cometFactoryExtendedAssetList) + ); + const setExtensionDelegateCalldataUSDT = await calldata( + configurator.populateTransaction.setExtensionDelegate(USDT_COMET, newCometExt) + ); + const deployAndUpgradeToCalldataUSDT = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, USDT_COMET] + ); + + const setFactoryCalldataWETH = await calldata( + configurator.populateTransaction.setFactory(WETH_COMET, cometFactoryExtendedAssetList) + ); + const setExtensionDelegateCalldataWETH = await calldata( + configurator.populateTransaction.setExtensionDelegate(WETH_COMET, newCometExt) + ); + const deployAndUpgradeToCalldataWETH = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, WETH_COMET] + ); + const l2ProposalData = utils.defaultAbiCoder.encode( ['address[]', 'uint256[]', 'string[]', 'bytes[]'], [ - [configurator.address, configurator.address, cometAdmin.address], - [0, 0, 0], + [ + configurator.address, configurator.address, cometAdmin.address, + configurator.address, configurator.address, cometAdmin.address, + configurator.address, configurator.address, cometAdmin.address, + ], + [ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + ], [ 'setFactory(address,address)', 'setExtensionDelegate(address,address)', 'deployAndUpgradeTo(address,address)', + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', + ], + [ + setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata, + setFactoryCalldataUSDT, setExtensionDelegateCalldataUSDT, deployAndUpgradeToCalldataUSDT, + setFactoryCalldataWETH, setExtensionDelegateCalldataWETH, deployAndUpgradeToCalldataWETH, ], - [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], ] ); @@ -105,7 +146,7 @@ export default migration('1735299799_update_comet_to_support_more_collaterals', }, ]; - const description = 'DESCRIPTION'; + const description = '# Update USDC, USDT and WETH Comets on Optimism to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 4 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDT, USDC and WETH markets 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cUSDTv3, cUSDCv3 and cWETHv3.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) @@ -137,7 +178,32 @@ export default migration('1735299799_update_comet_to_support_more_collaterals', const assetListAddress = await cometNew.assetList(); expect(assetListAddress).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewUSDC = new Contract( + USDT_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddressUSDC = await cometNewUSDC.assetList(); + + expect(assetListAddressUSDC).to.not.be.equal(ethers.constants.AddressZero); + expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); + + const cometNewWETH = new Contract( + WETH_COMET, + [ + 'function assetList() external view returns (address)', + ], + deploymentManager.hre.ethers.provider + ); + + const assetListAddressWETH = await cometNewWETH.assetList(); + expect(assetListAddressWETH).to.not.be.equal(ethers.constants.AddressZero); expect(await comet.extensionDelegate()).to.be.equal(newCometExtAddress); }, }); diff --git a/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts b/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts index b8fa2aa26..03cfc3ab0 100644 --- a/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts +++ b/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts @@ -8,6 +8,8 @@ import { utils } from 'ethers'; let newCometExtAddress: string; +const USDT_COMET = '0xaeB318360f27748Acb200CE616E389A6C9409a07'; + export default migration('1735299827_update_comet_to_support_more_collaterals', { async prepare(deploymentManager: DeploymentManager) { const _assetListFactory = await deploymentManager.deploy( @@ -72,27 +74,49 @@ export default migration('1735299827_update_comet_to_support_more_collaterals', const setFactoryCalldata = await calldata( configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) ); - const setExtensionDelegateCalldata = await calldata( configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) ); - const deployAndUpgradeToCalldata = utils.defaultAbiCoder.encode( ['address', 'address'], [configurator.address, comet.address] ); + + const setFactoryCalldataUSDT = await calldata( + configurator.populateTransaction.setFactory(USDT_COMET, cometFactoryExtendedAssetList) + ); + const setExtensionDelegateCalldataUSDT = await calldata( + configurator.populateTransaction.setExtensionDelegate(USDT_COMET, newCometExt) + ); + const deployAndUpgradeToCalldataUSDT = utils.defaultAbiCoder.encode( + ['address', 'address'], + [configurator.address, USDT_COMET] + ); + const l2ProposalData = utils.defaultAbiCoder.encode( ['address[]', 'uint256[]', 'string[]', 'bytes[]'], [ - [configurator.address, configurator.address, cometAdmin.address], - [0, 0, 0], [ + configurator.address, configurator.address, cometAdmin.address, + configurator.address, configurator.address, cometAdmin.address + ], + [ + 0, 0, 0, + 0, 0, 0 + ], + [ + 'setFactory(address,address)', + 'setExtensionDelegate(address,address)', + 'deployAndUpgradeTo(address,address)', 'setFactory(address,address)', 'setExtensionDelegate(address,address)', 'deployAndUpgradeTo(address,address)', ], - [setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata], + [ + setFactoryCalldata, setExtensionDelegateCalldata, deployAndUpgradeToCalldata, + setFactoryCalldataUSDT, setExtensionDelegateCalldataUSDT, deployAndUpgradeToCalldataUSDT + ], ] ); @@ -105,7 +129,7 @@ export default migration('1735299827_update_comet_to_support_more_collaterals', }, ]; - const description = 'DESCRIPTION'; + const description = '# Update USDC and USDT Comets on Polygon to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 2 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDT and USDC markets on Polygon. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cUSDTv3 and cUSDCv3.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) diff --git a/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts b/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts index 36788dd99..0c990652e 100644 --- a/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts +++ b/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts @@ -105,7 +105,7 @@ export default migration('1735299855_update_comet_to_support_more_collaterals', }, ]; - const description = 'DESCRIPTION'; + const description = '# Update USDC Comet on Scroll to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update Scroll cUSDCv3 Comet to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDC markets on Scroll. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) diff --git a/plugins/scenario/utils/hreForBase.ts b/plugins/scenario/utils/hreForBase.ts index 7855d8b77..51251f10a 100644 --- a/plugins/scenario/utils/hreForBase.ts +++ b/plugins/scenario/utils/hreForBase.ts @@ -77,7 +77,7 @@ export async function forkedHreForBase(base: ForkSpec): Promise Date: Mon, 6 Jan 2025 20:06:17 +0200 Subject: [PATCH 33/45] fix --- scenario/AddMaticxCollateralScenario.ts | 2 +- scenario/WithdrawReservesScenario.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scenario/AddMaticxCollateralScenario.ts b/scenario/AddMaticxCollateralScenario.ts index 894aed5e9..1619bd8e1 100644 --- a/scenario/AddMaticxCollateralScenario.ts +++ b/scenario/AddMaticxCollateralScenario.ts @@ -110,6 +110,6 @@ scenario( expect(await albert.getCometCollateralBalance(maticx.address)).to.be.equal( supplyAmount ); - expect(await albert.getCometBaseBalance()).to.be.equal(-borrowAmount); + expect(await albert.getCometBaseBalance()).to.be.closeTo(-borrowAmount, 1n); } ); diff --git a/scenario/WithdrawReservesScenario.ts b/scenario/WithdrawReservesScenario.ts index 5517bb788..6e81fc910 100644 --- a/scenario/WithdrawReservesScenario.ts +++ b/scenario/WithdrawReservesScenario.ts @@ -59,7 +59,7 @@ scenario( await context.setNextBaseFeeToZero(); await expectRevertCustom( - admin.withdrawReserves(albert.address, 101n * scale, { gasPrice: 0 }), + admin.withdrawReserves(albert.address, 1001n * scale, { gasPrice: 0 }), 'InsufficientReserves()' ); } From 262fb3baebf57e3f2301a030a717e0acb2d2ab72 Mon Sep 17 00:00:00 2001 From: dmitriy-woof-software Date: Mon, 13 Jan 2025 20:21:36 -0600 Subject: [PATCH 34/45] update descriptions --- .../1735299626_update_comet_to_support_more_collaterals.ts | 2 +- .../1735299703_update_comet_to_support_more_collaterals.ts | 2 +- .../1735299739_update_comet_to_support_more_collaterals.ts | 4 ++-- .../1735299778_update_comet_to_support_more_collaterals.ts | 2 +- .../1735299799_update_comet_to_support_more_collaterals.ts | 4 ++-- .../1735299827_update_comet_to_support_more_collaterals.ts | 4 ++-- .../1735299855_update_comet_to_support_more_collaterals.ts | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts b/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts index f439de569..01514180e 100644 --- a/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts +++ b/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts @@ -192,7 +192,7 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', }, ]; - const description = '# Update USDC, USDT, WETH and USDC.e Comets on Arbitrum to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 4 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDT, USDC, WETH and USDC.e markets on Arbitrum. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cUSDTv3, cUSDCv3, cWETHv3 and cUSDCev3.'; + const description = '# Update USDC, USDT, WETH and USDC.e Comets on Arbitrum to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 4 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDT, USDC, WETH and USDC.e markets on Arbitrum. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cUSDTv3, cUSDCv3, cWETHv3 and cUSDCev3.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) diff --git a/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts b/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts index 7422f9500..a3371890a 100644 --- a/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts +++ b/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts @@ -168,7 +168,7 @@ export default migration('1735299703_update_comet_to_support_more_collaterals', }, ]; - const description = '# Update AERO, USDC, WETH and USDbC Comets on Base to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 4 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update a Compound III AERO, USDC, WETH and USDbC markets 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cAEROv3, cUSDCv3, cWETHv3 and cUSDbCv3.'; + const description = '# Update AERO, USDC, WETH and USDbC Comets on Base to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 4 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update a Compound III AERO, USDC, WETH and USDbC markets 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cAEROv3, cUSDCv3, cWETHv3 and cUSDbCv3.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) diff --git a/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts index b40c9bf6d..12c037d1f 100644 --- a/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts +++ b/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts @@ -67,7 +67,7 @@ export default migration('1735299739_update_comet_to_support_more_collaterals', cometAdmin, configurator, } = await deploymentManager.getContracts(); - + newCometExtAddress = newCometExt; const mainnetActions = [ @@ -134,7 +134,7 @@ export default migration('1735299739_update_comet_to_support_more_collaterals', params: [timelock.address], }); - const description = '# Update USDC, USDT and USDS Comets on Mainnet to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 3 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update a Compound III USDC, USDT and USDS markets on Ethereum. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory for cUSDCv3 to the newly deployed factory.\n\nThe second action sets the extension delegate for cUSDCv3 to the newly deployed contract.\n\nThe third action deploys and upgrades cUSDCv3 to a new version.\n\nThe fourth action sets the factory for cUSDTv3 to the newly deployed factory.\n\nThe fifth action sets the extension delegate for cUSDTv3 to the newly deployed contract.\n\nThe sixth action deploys and upgrades cUSDTv3 to a new version.\n\nThe seventh action sets the factory for cUSDSv3 to the newly deployed factory.\n\nThe eighth action sets the extension delegate for cUSDSv3 to the newly deployed contract.\n\nThe ninth action deploys and upgrades cUSDSv3 to a new version.'; + const description = '# Update USDC, USDT and USDS Comets on Mainnet to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 3 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update a Compound III USDC, USDT and USDS markets on Ethereum. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory for cUSDCv3 to the newly deployed factory.\n\nThe second action sets the extension delegate for cUSDCv3 to the newly deployed contract.\n\nThe third action deploys and upgrades cUSDCv3 to a new version.\n\nThe fourth action sets the factory for cUSDTv3 to the newly deployed factory.\n\nThe fifth action sets the extension delegate for cUSDTv3 to the newly deployed contract.\n\nThe sixth action deploys and upgrades cUSDTv3 to a new version.\n\nThe seventh action sets the factory for cUSDSv3 to the newly deployed factory.\n\nThe eighth action sets the extension delegate for cUSDSv3 to the newly deployed contract.\n\nThe ninth action deploys and upgrades cUSDSv3 to a new version.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) diff --git a/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts b/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts index af0123e6d..f87f16df8 100644 --- a/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts +++ b/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts @@ -109,7 +109,7 @@ export default migration('1735299778_update_comet_to_support_more_collaterals', }, ]; - const description = '# Update USDe Comet on Mantle to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update Mantle cUSDeV3 Comet to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDe markets on Mantle. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version.'; + const description = '# Update USDe Comet on Mantle to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update Mantle cUSDeV3 Comet to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDe markets on Mantle. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) diff --git a/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts b/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts index 5f4082a5a..441d954e0 100644 --- a/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts +++ b/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts @@ -103,7 +103,7 @@ export default migration('1735299799_update_comet_to_support_more_collaterals', const deployAndUpgradeToCalldataWETH = utils.defaultAbiCoder.encode( ['address', 'address'], [configurator.address, WETH_COMET] - ); + ); const l2ProposalData = utils.defaultAbiCoder.encode( ['address[]', 'uint256[]', 'string[]', 'bytes[]'], @@ -146,7 +146,7 @@ export default migration('1735299799_update_comet_to_support_more_collaterals', }, ]; - const description = '# Update USDC, USDT and WETH Comets on Optimism to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 4 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDT, USDC and WETH markets 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cUSDTv3, cUSDCv3 and cWETHv3.'; + const description = '# Update USDC, USDT and WETH Comets on Optimism to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 4 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDT, USDC and WETH markets 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cUSDTv3, cUSDCv3 and cWETHv3.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) diff --git a/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts b/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts index 03cfc3ab0..5248476ef 100644 --- a/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts +++ b/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts @@ -82,7 +82,7 @@ export default migration('1735299827_update_comet_to_support_more_collaterals', [configurator.address, comet.address] ); - + const setFactoryCalldataUSDT = await calldata( configurator.populateTransaction.setFactory(USDT_COMET, cometFactoryExtendedAssetList) ); @@ -129,7 +129,7 @@ export default migration('1735299827_update_comet_to_support_more_collaterals', }, ]; - const description = '# Update USDC and USDT Comets on Polygon to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 2 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDT and USDC markets on Polygon. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cUSDTv3 and cUSDCv3.'; + const description = '# Update USDC and USDT Comets on Polygon to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update 2 Comets to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDT and USDC markets on Polygon. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version for all 4 comets: cUSDTv3 and cUSDCv3.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) diff --git a/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts b/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts index 0c990652e..f86064978 100644 --- a/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts +++ b/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts @@ -105,7 +105,7 @@ export default migration('1735299855_update_comet_to_support_more_collaterals', }, ]; - const description = '# Update USDC Comet on Scroll to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update Scroll cUSDCv3 Comet to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDC markets on Scroll. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version.'; + const description = '# Update USDC Comet on Scroll to support more collaterals\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes to update Scroll cUSDCv3 Comet to a new version, which supports up to 24 collaterals. This proposal takes the governance steps recommended and necessary to update Compound III USDC markets on Scroll. 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).\n\nDetailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/904) and [forum discussion](https://www.comp.xyz/t/increase-amount-of-collaterals-in-comet/5465).\n\n\n## Proposal Actions\n\nThe first action sets the factory to the newly deployed factory, extension delegate to the newly deployed contract and deploys and upgrades Comet to a new version.'; const txn = await deploymentManager.retry(async () => trace( await governor.propose(...(await proposal(mainnetActions, description))) From 1b4307b47807299bce6df55e0798f66d9920f129 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Tue, 14 Jan 2025 13:35:03 +0200 Subject: [PATCH 35/45] fix --- plugins/scenario/utils/hreForBase.ts | 12 +++++++++- scenario/TransferScenario.ts | 31 +++++++++++++++++--------- scenario/utils/relayOptimismMessage.ts | 21 +++++++++++------ scenario/utils/scenarioHelper.ts | 3 +++ 4 files changed, 49 insertions(+), 18 deletions(-) diff --git a/plugins/scenario/utils/hreForBase.ts b/plugins/scenario/utils/hreForBase.ts index 51251f10a..b608ac925 100644 --- a/plugins/scenario/utils/hreForBase.ts +++ b/plugins/scenario/utils/hreForBase.ts @@ -61,6 +61,16 @@ export async function nonForkedHreForBase(base: ForkSpec): Promise { const ctx: HardhatContext = HardhatContext.getHardhatContext(); @@ -77,8 +87,8 @@ export async function forkedHreForBase(base: ForkSpec): Promise partial withdraw / borrow base to partial repay / supply', { - cometBalances: { - albert: { $base: 1000, $asset0: 5000 }, // in units of asset, not wei - betty: { $base: -1000 }, - charles: { $base: 1000 }, // to give the protocol enough base for others to borrow from - }, + cometBalances: async (ctx) => ( + { + albert: { $base: getConfigForScenario(ctx).transferBase, $asset0: getConfigForScenario(ctx).transferAsset1 }, // in units of asset, not wei + betty: { $base: -getConfigForScenario(ctx).transferBase }, + charles: { $base: getConfigForScenario(ctx).transferBase }, // to give the protocol enough base for others to borrow from + } + ), }, async ({ comet, actors }, context) => { const { albert, betty } = actors; @@ -149,16 +151,25 @@ scenario( const borrowRate = (await comet.getBorrowRate(utilization)).toBigInt(); // XXX 100 seconds?! - expectApproximately(await albert.getCometBaseBalance(), 1000n * scale, getInterest(1000n * scale, borrowRate, 100n) + 2n); - expectApproximately(await betty.getCometBaseBalance(), -1000n * scale, getInterest(1000n * scale, borrowRate, 100n) + 2n); + expectApproximately( + await albert.getCometBaseBalance(), + BigInt(getConfigForScenario(context).transferBase) * scale, + getInterest(BigInt(getConfigForScenario(context).transferBase) * scale, borrowRate, 100n) + 2n + ); + + expectApproximately( + await betty.getCometBaseBalance(), + -BigInt(getConfigForScenario(context).transferBase) * scale, + getInterest(BigInt(getConfigForScenario(context).transferBase) * scale, borrowRate, 100n) + 2n + ); // Albert with positive balance transfers to Betty with negative balance - const toTransfer = 2500n * scale; + const toTransfer = BigInt(getConfigForScenario(context).transferBase) * 25n / 10n * scale; const txn = await albert.transferAsset({ dst: betty.address, asset: baseAsset.address, amount: toTransfer }); // Albert ends with negative balance and Betty with positive balance - expectApproximately(await albert.getCometBaseBalance(), -1500n * scale, getInterest(1500n * scale, borrowRate, 100n) + 4n); - expectApproximately(await betty.getCometBaseBalance(), 1500n * scale, getInterest(1500n * scale, borrowRate, 100n) + 4n); + expectApproximately(await albert.getCometBaseBalance(), -BigInt(getConfigForScenario(context).transferBase) * 15n / 10n * scale, getInterest(BigInt(getConfigForScenario(context).transferBase) * 15n / 10n * scale, borrowRate, 100n) + 4n); + expectApproximately(await betty.getCometBaseBalance(), BigInt(getConfigForScenario(context).transferBase) * 15n / 10n * scale, getInterest(BigInt(getConfigForScenario(context).transferBase) * 15n / 10n * scale, borrowRate, 100n) + 4n); return txn; // return txn to measure gas } diff --git a/scenario/utils/relayOptimismMessage.ts b/scenario/utils/relayOptimismMessage.ts index bd3c81d74..9261f09ca 100644 --- a/scenario/utils/relayOptimismMessage.ts +++ b/scenario/utils/relayOptimismMessage.ts @@ -61,7 +61,7 @@ export default async function relayOptimismMessage( const messageWithoutSigHash = '0x' + messageWithoutPrefix.slice(8); try { // 1a. Bridging ERC20 token - const { l1Token, _l2Token, _from, to, amount, _data } = ethers.utils.defaultAbiCoder.decode( + const [ l1Token, _l2Token, _from, to, amount, _data ] = ethers.utils.defaultAbiCoder.decode( ['address l1Token', 'address l2Token', 'address from', 'address to', 'uint256 amount', 'bytes data'], messageWithoutSigHash ); @@ -71,7 +71,7 @@ export default async function relayOptimismMessage( ); } catch (e) { // 1a. Bridging ETH - const { _from, to, amount, _data } = ethers.utils.defaultAbiCoder.decode( + const [ _from, to, amount, _data ] = ethers.utils.defaultAbiCoder.decode( ['address from', 'address to', 'uint256 amount', 'bytes data'], messageWithoutSigHash ); @@ -90,11 +90,18 @@ export default async function relayOptimismMessage( } } else if (target === bridgeReceiver.address) { // Cross-chain message passing - const proposalCreatedEvent = relayMessageTxn.events.find(event => event.address === bridgeReceiver.address); - const { args: { id, eta } } = bridgeReceiver.interface.parseLog(proposalCreatedEvent); - - // Add the proposal to the list of open bridged proposals to be executed after all the messages have been relayed - openBridgedProposals.push({ id, eta }); + try { + const proposalCreatedEvent = relayMessageTxn.events.find(event => event.address === bridgeReceiver.address); + const { args: { id, eta } } = bridgeReceiver.interface.parseLog(proposalCreatedEvent); + // Add the proposal to the list of open bridged proposals to be executed after all the messages have been relayed + openBridgedProposals.push({ id, eta }); + } catch (e) { + if(relayMessageTxn.events[0].event === 'FailedRelayedMessage'){ + console.log('Failed to relay message'); + continue; + } + throw e; + } } else { throw new Error(`[${governanceDeploymentManager.network} -> ${bridgeDeploymentManager.network}] Unrecognized target for cross-chain message`); } diff --git a/scenario/utils/scenarioHelper.ts b/scenario/utils/scenarioHelper.ts index 9d2ddbc76..30b430b34 100644 --- a/scenario/utils/scenarioHelper.ts +++ b/scenario/utils/scenarioHelper.ts @@ -16,6 +16,7 @@ const config = { rewardsBase: 1000, transferBase: 1000, transferAsset: 5000, + transferAsset1: 5000, interestSeconds: 110, withdrawBase: 1000, withdrawAsset: 3000, @@ -73,6 +74,8 @@ export function getConfigForScenario(ctx: CometContext) { if (ctx.world.base.network === 'polygon' && ctx.world.base.deployment === 'usdt') { config.withdrawAsset = 10000; + config.transferAsset = 500000; + config.transferBase = 100; } if (ctx.world.base.network === 'scroll' && ctx.world.base.deployment === 'usdc') { From 23818306add6af2b41fa3e210162c7b413844aa9 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Tue, 14 Jan 2025 15:48:25 +0200 Subject: [PATCH 36/45] fix: review fix --- contracts/AssetList.sol | 9 ++++++++- contracts/IAssetListFactoryHolder.sol | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/contracts/AssetList.sol b/contracts/AssetList.sol index 6ca5c74da..0165efcb2 100644 --- a/contracts/AssetList.sol +++ b/contracts/AssetList.sol @@ -103,7 +103,14 @@ contract AssetList { } /** - * @dev Checks and gets the packed asset info for storage + * @dev Checks and gets the packed asset info for storage in 2 variables + * - in first variable, the asset address is stored in the lower 160 bits (address can be interpreted as uint160), + * the borrow collateral factor in the next 16 bits, + * the liquidate collateral factor in the next 16 bits, + * and the liquidation factor in the next 16 bits + * - in the second variable, the price feed address is stored in the lower 160 bits, + * the asset decimals in the next 8 bits, + * and the supply cap in the next 64 bits * @param assetConfigs The asset configurations * @param i The index of the asset info to get * @return The packed asset info diff --git a/contracts/IAssetListFactoryHolder.sol b/contracts/IAssetListFactoryHolder.sol index 8ba2ab551..266bf3352 100644 --- a/contracts/IAssetListFactoryHolder.sol +++ b/contracts/IAssetListFactoryHolder.sol @@ -8,7 +8,7 @@ pragma solidity 0.8.15; interface IAssetListFactoryHolder { /** * @notice Get the asset list factory - * @return assetListFactory The asset list factory + * @return assetListFactory The asset list factory address */ function assetListFactory() external view returns (address); } \ No newline at end of file From 40e0370d94042e97567148e83fff0b1593c0a105 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Tue, 14 Jan 2025 16:37:26 +0200 Subject: [PATCH 37/45] fix: naming fix --- test/absorb-test.ts | 2 +- test/asset-info-test-asset-list-comet.ts | 6 +++--- test/bulker-test.ts | 4 ++-- test/helpers.ts | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/absorb-test.ts b/test/absorb-test.ts index 8b0fe708b..2ab6c1e80 100644 --- a/test/absorb-test.ts +++ b/test/absorb-test.ts @@ -580,7 +580,7 @@ describe('absorb', function () { }, reward: 'COMP', }); - const { cometExtendedAssetList : comet, tokens: { + const { cometWithExtendedAssetList : comet, tokens: { COMP, WETH, }, users: [absorber, underwater] } = protocol; diff --git a/test/asset-info-test-asset-list-comet.ts b/test/asset-info-test-asset-list-comet.ts index 14f511b31..5650f0203 100644 --- a/test/asset-info-test-asset-list-comet.ts +++ b/test/asset-info-test-asset-list-comet.ts @@ -2,7 +2,7 @@ import { expect, exp, makeConfigurator, ONE, makeProtocol } from './helpers'; describe('asset info', function () { it('initializes protocol', async () => { - const { cometExtendedAssetList: comet, tokens } = await makeConfigurator({ + const { cometWithExtendedAssetList: comet, tokens } = await makeConfigurator({ assets: { USDC: {}, ASSET1: {}, @@ -68,8 +68,8 @@ describe('asset info', function () { }); it('reverts if index is greater than numAssets', async () => { - const { cometExtendedAssetList } = await makeConfigurator(); - await expect(cometExtendedAssetList.getAssetInfo(3)).to.be.revertedWith("custom error 'BadAsset()'"); + const { cometWithExtendedAssetList } = await makeConfigurator(); + await expect(cometWithExtendedAssetList.getAssetInfo(3)).to.be.revertedWith("custom error 'BadAsset()'"); }); it('reverts if collateral factors are out of range', async () => { diff --git a/test/bulker-test.ts b/test/bulker-test.ts index ca5c380de..cfd5a9318 100644 --- a/test/bulker-test.ts +++ b/test/bulker-test.ts @@ -77,7 +77,7 @@ describe('bulker', function () { }, reward: 'COMP', }); - const { cometExtendedAssetList : comet, tokens: { + const { cometWithExtendedAssetList : comet, tokens: { COMP, WETH, USDC, @@ -392,7 +392,7 @@ describe('bulker', function () { }, reward: 'COMP', }); - const { cometExtendedAssetList : comet, tokens: { + const { cometWithExtendedAssetList : comet, tokens: { COMP, WETH, }, users: [alice] } = protocol; diff --git a/test/helpers.ts b/test/helpers.ts index 535b4e178..a6bfcd19f 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -351,13 +351,13 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { config.extensionDelegate = extensionDelegateAssetList.address; const CometFactoryExtendedAssetList = (await ethers.getContractFactory('CometHarnessExtendedAssetList')) as CometHarnessExtendedAssetList__factory; - const cometExtendedAssetList = await CometFactoryExtendedAssetList.deploy(config); - await cometExtendedAssetList.deployed(); + const cometWithExtendedAssetList = await CometFactoryExtendedAssetList.deploy(config); + await cometWithExtendedAssetList.deployed(); if (opts.start) await ethers.provider.send('evm_setNextBlockTimestamp', [opts.start]); await comet.initializeStorage(); - await cometExtendedAssetList.initializeStorage(); + await cometWithExtendedAssetList.initializeStorage(); const baseTokenBalance = opts.baseTokenBalance; if (baseTokenBalance) { @@ -374,7 +374,7 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { base, reward, comet: await ethers.getContractAt('CometHarnessInterface', comet.address) as Comet, - cometWithExtendedAssetList: await ethers.getContractAt('CometHarnessInterfaceExtendedAssetList', cometExtendedAssetList.address) as CometWithExtendedAssetList, + cometWithExtendedAssetList: await ethers.getContractAt('CometHarnessInterfaceExtendedAssetList', cometWithExtendedAssetList.address) as CometWithExtendedAssetList, assetListFactory: assetListFactory, tokens, unsupportedToken, From fb9f9b5ca53f8cd88639ac93a3d4b58c05d73a55 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Tue, 14 Jan 2025 17:05:11 +0200 Subject: [PATCH 38/45] fix: optimizer --- .github/workflows/run-forge-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-forge-tests.yaml b/.github/workflows/run-forge-tests.yaml index 6a10f7523..9a6d2b5b6 100644 --- a/.github/workflows/run-forge-tests.yaml +++ b/.github/workflows/run-forge-tests.yaml @@ -21,7 +21,7 @@ jobs: run: forge install - name: Run tests - run: forge test -vvv --via-ir + run: forge test -vvv --via-ir --optimizer-runs 1 env: ETHERSCAN_KEY: ${{ secrets.ETHERSCAN_KEY }} SNOWTRACE_KEY: ${{ secrets.SNOWTRACE_KEY }} From f4860cf4c03b3618d1eba7efccd74daa76afcd13 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Tue, 14 Jan 2025 17:09:21 +0200 Subject: [PATCH 39/45] fix: second optimizer fix --- .github/workflows/run-forge-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-forge-tests.yaml b/.github/workflows/run-forge-tests.yaml index 9a6d2b5b6..126091154 100644 --- a/.github/workflows/run-forge-tests.yaml +++ b/.github/workflows/run-forge-tests.yaml @@ -33,4 +33,4 @@ jobs: - name: Build Comet with older solc versions run: | - forge build --contracts contracts/Comet.sol --use solc:0.8.15 --via-ir + forge build --contracts contracts/Comet.sol --use solc:0.8.15 --via-ir --optimizer-runs 1 From 94131adc6547647ab267250931a38316f46b3851 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Wed, 15 Jan 2025 13:34:48 +0200 Subject: [PATCH 40/45] fix: optimization --- .github/workflows/run-forge-tests.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-forge-tests.yaml b/.github/workflows/run-forge-tests.yaml index 700518839..1c343ea1b 100644 --- a/.github/workflows/run-forge-tests.yaml +++ b/.github/workflows/run-forge-tests.yaml @@ -21,7 +21,7 @@ jobs: run: forge install - name: Run tests - run: forge test -vvv --via-ir + run: forge test -vvv --via-ir --optimizer-runs 1 env: ETHERSCAN_KEY: ${{ secrets.ETHERSCAN_KEY }} SNOWTRACE_KEY: ${{ secrets.SNOWTRACE_KEY }} @@ -35,4 +35,4 @@ jobs: - name: Build Comet with older solc versions run: | - forge build --contracts contracts/Comet.sol --use solc:0.8.15 --via-ir + forge build --contracts contracts/Comet.sol --use solc:0.8.15 --via-ir --optimizer-runs 1 From 5fe26a2516b1a24a588862e0d090aa737c20a20b Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Fri, 17 Jan 2025 19:10:27 +0200 Subject: [PATCH 41/45] fix: merge fix --- ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 18 +++++++++--------- ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 18 +++++++++--------- ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 16 ++++++++-------- ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 14 +++++++------- ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 16 ++++++++-------- ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 14 +++++++------- ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ ...update_comet_to_support_more_collaterals.ts | 12 ++++++------ test/helpers.ts | 4 ++-- 21 files changed, 134 insertions(+), 134 deletions(-) diff --git a/deployments/arbitrum/usdc.e/migrations/1735299634_update_comet_to_support_more_collaterals.ts b/deployments/arbitrum/usdc.e/migrations/1735299634_update_comet_to_support_more_collaterals.ts index 762cdcf21..0bde436a5 100644 --- a/deployments/arbitrum/usdc.e/migrations/1735299634_update_comet_to_support_more_collaterals.ts +++ b/deployments/arbitrum/usdc.e/migrations/1735299634_update_comet_to_support_more_collaterals.ts @@ -17,9 +17,9 @@ export default migration('1735299634_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -49,13 +49,13 @@ export default migration('1735299634_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -77,7 +77,7 @@ export default migration('1735299634_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts b/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts index 01514180e..83d231ea1 100644 --- a/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts +++ b/deployments/arbitrum/usdc/migrations/1735299626_update_comet_to_support_more_collaterals.ts @@ -21,9 +21,9 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -53,13 +53,13 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -81,7 +81,7 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) @@ -92,7 +92,7 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', ); const setFactoryCalldataUSDCE = await calldata( - configurator.populateTransaction.setFactory(USDCE_COMET, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(USDCE_COMET, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldataUSDCE = await calldata( configurator.populateTransaction.setExtensionDelegate(USDCE_COMET, newCometExt) @@ -103,7 +103,7 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', ); const setFactoryCalldataUSDT = await calldata( - configurator.populateTransaction.setFactory(USDT_COMET, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(USDT_COMET, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldataUSDT = await calldata( configurator.populateTransaction.setExtensionDelegate(USDT_COMET, newCometExt) @@ -114,7 +114,7 @@ export default migration('1735299626_update_comet_to_support_more_collaterals', ); const setFactoryCalldataWETH = await calldata( - configurator.populateTransaction.setFactory(WETH_COMET, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(WETH_COMET, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldataWETH = await calldata( configurator.populateTransaction.setExtensionDelegate(WETH_COMET, newCometExt) diff --git a/deployments/arbitrum/usdt/migrations/1735299656_update_comet_to_support_more_collaterals.ts b/deployments/arbitrum/usdt/migrations/1735299656_update_comet_to_support_more_collaterals.ts index 7e008e321..8e8b161ec 100644 --- a/deployments/arbitrum/usdt/migrations/1735299656_update_comet_to_support_more_collaterals.ts +++ b/deployments/arbitrum/usdt/migrations/1735299656_update_comet_to_support_more_collaterals.ts @@ -17,9 +17,9 @@ export default migration('1735299656_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -49,13 +49,13 @@ export default migration('1735299656_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -77,7 +77,7 @@ export default migration('1735299656_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/deployments/arbitrum/weth/migrations/1735299663_update_comet_to_support_more_collaterals.ts b/deployments/arbitrum/weth/migrations/1735299663_update_comet_to_support_more_collaterals.ts index 7641ccc30..ff24a7194 100644 --- a/deployments/arbitrum/weth/migrations/1735299663_update_comet_to_support_more_collaterals.ts +++ b/deployments/arbitrum/weth/migrations/1735299663_update_comet_to_support_more_collaterals.ts @@ -17,9 +17,9 @@ export default migration('1735299663_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -49,13 +49,13 @@ export default migration('1735299663_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -77,7 +77,7 @@ export default migration('1735299663_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts b/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts index a3371890a..d31dc4626 100644 --- a/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts +++ b/deployments/base/aero/migrations/1735299703_update_comet_to_support_more_collaterals.ts @@ -20,9 +20,9 @@ export default migration('1735299703_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -52,13 +52,13 @@ export default migration('1735299703_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -78,7 +78,7 @@ export default migration('1735299703_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) @@ -89,7 +89,7 @@ export default migration('1735299703_update_comet_to_support_more_collaterals', ); const setFactoryCalldataUSDC = await calldata( - configurator.populateTransaction.setFactory(USDC_COMET, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(USDC_COMET, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldataUSDC = await calldata( configurator.populateTransaction.setExtensionDelegate(USDC_COMET, newCometExt) @@ -100,7 +100,7 @@ export default migration('1735299703_update_comet_to_support_more_collaterals', ); const setFactoryCalldataWETH = await calldata( - configurator.populateTransaction.setFactory(WETH_COMET, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(WETH_COMET, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldataWETH = await calldata( configurator.populateTransaction.setExtensionDelegate(WETH_COMET, newCometExt) @@ -111,7 +111,7 @@ export default migration('1735299703_update_comet_to_support_more_collaterals', ); const setFactoryCalldataUSDBC = await calldata( - configurator.populateTransaction.setFactory(USDBC_COMET, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(USDBC_COMET, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldataUSDBC = await calldata( configurator.populateTransaction.setExtensionDelegate(USDBC_COMET, newCometExt) diff --git a/deployments/base/usdbc/migrations/1735299714_update_comet_to_support_more_collaterals.ts b/deployments/base/usdbc/migrations/1735299714_update_comet_to_support_more_collaterals.ts index a78ef3c7d..fc2c4edac 100644 --- a/deployments/base/usdbc/migrations/1735299714_update_comet_to_support_more_collaterals.ts +++ b/deployments/base/usdbc/migrations/1735299714_update_comet_to_support_more_collaterals.ts @@ -16,9 +16,9 @@ export default migration('1735299714_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -48,13 +48,13 @@ export default migration('1735299714_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -74,7 +74,7 @@ export default migration('1735299714_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/deployments/base/usdc/migrations/1735299718_update_comet_to_support_more_collaterals.ts b/deployments/base/usdc/migrations/1735299718_update_comet_to_support_more_collaterals.ts index 5d1501a3d..ba201f579 100644 --- a/deployments/base/usdc/migrations/1735299718_update_comet_to_support_more_collaterals.ts +++ b/deployments/base/usdc/migrations/1735299718_update_comet_to_support_more_collaterals.ts @@ -16,9 +16,9 @@ export default migration('1735299718_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -48,13 +48,13 @@ export default migration('1735299718_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -74,7 +74,7 @@ export default migration('1735299718_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/deployments/base/weth/migrations/1735299723_update_comet_to_support_more_collaterals.ts b/deployments/base/weth/migrations/1735299723_update_comet_to_support_more_collaterals.ts index a9be12cdd..f48be7a14 100644 --- a/deployments/base/weth/migrations/1735299723_update_comet_to_support_more_collaterals.ts +++ b/deployments/base/weth/migrations/1735299723_update_comet_to_support_more_collaterals.ts @@ -16,9 +16,9 @@ export default migration('1735299723_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -48,13 +48,13 @@ export default migration('1735299723_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -74,7 +74,7 @@ export default migration('1735299723_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts index 12c037d1f..62e73bdf1 100644 --- a/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts +++ b/deployments/mainnet/usdc/migrations/1735299739_update_comet_to_support_more_collaterals.ts @@ -18,9 +18,9 @@ export default migration('1735299739_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -50,13 +50,13 @@ export default migration('1735299739_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, _, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -75,19 +75,19 @@ export default migration('1735299739_update_comet_to_support_more_collaterals', { contract: configurator, signature: 'setFactory(address,address)', - args: [comet.address, cometFactoryExtendedAssetList], + args: [comet.address, cometFactoryWithExtendedAssetList], }, // 2. Set the factory in the Configurator for the USDS comet { contract: configurator, signature: 'setFactory(address,address)', - args: [USDS_COMET, cometFactoryExtendedAssetList], + args: [USDS_COMET, cometFactoryWithExtendedAssetList], }, // 3. Set the factory in the Configurator for the USDT comet { contract: configurator, signature: 'setFactory(address,address)', - args: [USDT_COMET, cometFactoryExtendedAssetList], + args: [USDT_COMET, cometFactoryWithExtendedAssetList], }, // 4. Set new CometExt as the extension delegate for the USDC comet { diff --git a/deployments/mainnet/usds/migrations/1735299744_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/usds/migrations/1735299744_update_comet_to_support_more_collaterals.ts index ed41f83a3..7b60bf9fe 100644 --- a/deployments/mainnet/usds/migrations/1735299744_update_comet_to_support_more_collaterals.ts +++ b/deployments/mainnet/usds/migrations/1735299744_update_comet_to_support_more_collaterals.ts @@ -15,9 +15,9 @@ export default migration('1735299744_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -47,13 +47,13 @@ export default migration('1735299744_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, _, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -72,7 +72,7 @@ export default migration('1735299744_update_comet_to_support_more_collaterals', { contract: configurator, signature: 'setFactory(address,address)', - args: [comet.address, cometFactoryExtendedAssetList], + args: [comet.address, cometFactoryWithExtendedAssetList], }, // 2. Set new CometExt as the extension delegate { diff --git a/deployments/mainnet/usdt/migrations/1735299748_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/usdt/migrations/1735299748_update_comet_to_support_more_collaterals.ts index defc79f86..73251359d 100644 --- a/deployments/mainnet/usdt/migrations/1735299748_update_comet_to_support_more_collaterals.ts +++ b/deployments/mainnet/usdt/migrations/1735299748_update_comet_to_support_more_collaterals.ts @@ -15,9 +15,9 @@ export default migration('1735299748_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -47,13 +47,13 @@ export default migration('1735299748_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, _, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -72,7 +72,7 @@ export default migration('1735299748_update_comet_to_support_more_collaterals', { contract: configurator, signature: 'setFactory(address,address)', - args: [comet.address, cometFactoryExtendedAssetList], + args: [comet.address, cometFactoryWithExtendedAssetList], }, // 2. Set new CometExt as the extension delegate { diff --git a/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts index f6544a716..2ccbd08c1 100644 --- a/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts +++ b/deployments/mainnet/weth/migrations/1735299752_update_comet_to_support_more_collaterals.ts @@ -16,9 +16,9 @@ export default migration('1735299752_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -48,13 +48,13 @@ export default migration('1735299752_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, _, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -73,13 +73,13 @@ export default migration('1735299752_update_comet_to_support_more_collaterals', { contract: configurator, signature: 'setFactory(address,address)', - args: [comet.address, cometFactoryExtendedAssetList], + args: [comet.address, cometFactoryWithExtendedAssetList], }, // 2. Set the factory in the Configurator { contract: configurator, signature: 'setFactory(address,address)', - args: [WSTETH_COMET, cometFactoryExtendedAssetList], + args: [WSTETH_COMET, cometFactoryWithExtendedAssetList], }, // 3. Set new CometExt as the extension delegate { diff --git a/deployments/mainnet/wsteth/migrations/1735299760_update_comet_to_support_more_collaterals.ts b/deployments/mainnet/wsteth/migrations/1735299760_update_comet_to_support_more_collaterals.ts index 4ee265202..f7d3db3b3 100644 --- a/deployments/mainnet/wsteth/migrations/1735299760_update_comet_to_support_more_collaterals.ts +++ b/deployments/mainnet/wsteth/migrations/1735299760_update_comet_to_support_more_collaterals.ts @@ -15,9 +15,9 @@ export default migration('1735299760_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -47,13 +47,13 @@ export default migration('1735299760_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, _, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -72,7 +72,7 @@ export default migration('1735299760_update_comet_to_support_more_collaterals', { contract: configurator, signature: 'setFactory(address,address)', - args: [comet.address, cometFactoryExtendedAssetList], + args: [comet.address, cometFactoryWithExtendedAssetList], }, // 2. Set new CometExt as the extension delegate { diff --git a/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts b/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts index f87f16df8..bc2d5dffd 100644 --- a/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts +++ b/deployments/mantle/usde/migrations/1735299778_update_comet_to_support_more_collaterals.ts @@ -16,9 +16,9 @@ export default migration('1735299778_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -48,13 +48,13 @@ export default migration('1735299778_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -74,7 +74,7 @@ export default migration('1735299778_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts b/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts index 441d954e0..22862e83e 100644 --- a/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts +++ b/deployments/optimism/usdc/migrations/1735299799_update_comet_to_support_more_collaterals.ts @@ -19,9 +19,9 @@ export default migration('1735299799_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -51,13 +51,13 @@ export default migration('1735299799_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -73,7 +73,7 @@ export default migration('1735299799_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) @@ -84,7 +84,7 @@ export default migration('1735299799_update_comet_to_support_more_collaterals', ); const setFactoryCalldataUSDT = await calldata( - configurator.populateTransaction.setFactory(USDT_COMET, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(USDT_COMET, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldataUSDT = await calldata( configurator.populateTransaction.setExtensionDelegate(USDT_COMET, newCometExt) @@ -95,7 +95,7 @@ export default migration('1735299799_update_comet_to_support_more_collaterals', ); const setFactoryCalldataWETH = await calldata( - configurator.populateTransaction.setFactory(WETH_COMET, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(WETH_COMET, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldataWETH = await calldata( configurator.populateTransaction.setExtensionDelegate(WETH_COMET, newCometExt) diff --git a/deployments/optimism/usdt/migrations/1735299805_update_comet_to_support_more_collaterals.ts b/deployments/optimism/usdt/migrations/1735299805_update_comet_to_support_more_collaterals.ts index aaeaf80ad..c2185ef55 100644 --- a/deployments/optimism/usdt/migrations/1735299805_update_comet_to_support_more_collaterals.ts +++ b/deployments/optimism/usdt/migrations/1735299805_update_comet_to_support_more_collaterals.ts @@ -16,9 +16,9 @@ export default migration('1735299805_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -48,13 +48,13 @@ export default migration('1735299805_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -70,7 +70,7 @@ export default migration('1735299805_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/deployments/optimism/weth/migrations/1735299811_update_comet_to_support_more_collaterals.ts b/deployments/optimism/weth/migrations/1735299811_update_comet_to_support_more_collaterals.ts index 9ffa7939a..42de8972d 100644 --- a/deployments/optimism/weth/migrations/1735299811_update_comet_to_support_more_collaterals.ts +++ b/deployments/optimism/weth/migrations/1735299811_update_comet_to_support_more_collaterals.ts @@ -16,9 +16,9 @@ export default migration('1735299811_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -48,13 +48,13 @@ export default migration('1735299811_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -70,7 +70,7 @@ export default migration('1735299811_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts b/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts index 5248476ef..51d310b37 100644 --- a/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts +++ b/deployments/polygon/usdc/migrations/1735299827_update_comet_to_support_more_collaterals.ts @@ -18,9 +18,9 @@ export default migration('1735299827_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -50,13 +50,13 @@ export default migration('1735299827_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -72,7 +72,7 @@ export default migration('1735299827_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( configurator.populateTransaction.setExtensionDelegate(comet.address, newCometExt) @@ -84,7 +84,7 @@ export default migration('1735299827_update_comet_to_support_more_collaterals', const setFactoryCalldataUSDT = await calldata( - configurator.populateTransaction.setFactory(USDT_COMET, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(USDT_COMET, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldataUSDT = await calldata( configurator.populateTransaction.setExtensionDelegate(USDT_COMET, newCometExt) diff --git a/deployments/polygon/usdt/migrations/1735299832_update_comet_to_support_more_collaterals.ts b/deployments/polygon/usdt/migrations/1735299832_update_comet_to_support_more_collaterals.ts index 55e772a1c..bc36f53d9 100644 --- a/deployments/polygon/usdt/migrations/1735299832_update_comet_to_support_more_collaterals.ts +++ b/deployments/polygon/usdt/migrations/1735299832_update_comet_to_support_more_collaterals.ts @@ -16,9 +16,9 @@ export default migration('1735299832_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -48,13 +48,13 @@ export default migration('1735299832_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -70,7 +70,7 @@ export default migration('1735299832_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts b/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts index f86064978..2c754cd7d 100644 --- a/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts +++ b/deployments/scroll/usdc/migrations/1735299855_update_comet_to_support_more_collaterals.ts @@ -16,9 +16,9 @@ export default migration('1735299855_update_comet_to_support_more_collaterals', [] ); - const cometFactoryExtendedAssetList = await deploymentManager.deploy( - 'cometFactoryExtendedAssetList', - 'CometFactoryExtendedAssetList.sol', + const cometFactoryWithExtendedAssetList = await deploymentManager.deploy( + 'cometFactoryWithExtendedAssetList', + 'CometFactoryWithExtendedAssetList.sol', [] ); const { @@ -48,13 +48,13 @@ export default migration('1735299855_update_comet_to_support_more_collaterals', ] ); return { - cometFactoryExtendedAssetList: cometFactoryExtendedAssetList.address, + cometFactoryWithExtendedAssetList: cometFactoryWithExtendedAssetList.address, newCometExt: _newCometExt.address }; }, async enact(deploymentManager: DeploymentManager, govDeploymentManager, { - cometFactoryExtendedAssetList, + cometFactoryWithExtendedAssetList, newCometExt, }) { @@ -70,7 +70,7 @@ export default migration('1735299855_update_comet_to_support_more_collaterals', newCometExtAddress = newCometExt; const setFactoryCalldata = await calldata( - configurator.populateTransaction.setFactory(comet.address, cometFactoryExtendedAssetList) + configurator.populateTransaction.setFactory(comet.address, cometFactoryWithExtendedAssetList) ); const setExtensionDelegateCalldata = await calldata( diff --git a/test/helpers.ts b/test/helpers.ts index a6bfcd19f..710b5adb9 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -349,9 +349,9 @@ export async function makeProtocol(opts: ProtocolOpts = {}): Promise { await extensionDelegateAssetList.deployed(); } config.extensionDelegate = extensionDelegateAssetList.address; - const CometFactoryExtendedAssetList = (await ethers.getContractFactory('CometHarnessExtendedAssetList')) as CometHarnessExtendedAssetList__factory; + const CometFactoryWithExtendedAssetList = (await ethers.getContractFactory('CometHarnessExtendedAssetList')) as CometHarnessExtendedAssetList__factory; - const cometWithExtendedAssetList = await CometFactoryExtendedAssetList.deploy(config); + const cometWithExtendedAssetList = await CometFactoryWithExtendedAssetList.deploy(config); await cometWithExtendedAssetList.deployed(); if (opts.start) await ethers.provider.send('evm_setNextBlockTimestamp', [opts.start]); From bccbcaaf1502bd7b7cc3c9fa8c23f498a027f813 Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Tue, 21 Jan 2025 12:42:19 +0200 Subject: [PATCH 42/45] feat: wbtc market --- .github/workflows/run-scenarios.yaml | 2 +- deployments/mainnet/wbtc/configuration.json | 56 ++++ deployments/mainnet/wbtc/deploy.ts | 51 ++++ .../1737396251_configurate_and_ens.ts | 264 ++++++++++++++++++ deployments/mainnet/wbtc/relations.ts | 41 +++ deployments/mainnet/wbtc/roots.json | 2 + hardhat.config.ts | 7 + scenario/LiquidationBotScenario.ts | 2 +- scenario/RewardsScenario.ts | 15 +- scenario/SupplyScenario.ts | 2 + scenario/utils/scenarioHelper.ts | 3 + .../liquidateUnderwaterBorrowers.ts | 15 +- src/deploy/index.ts | 3 + 13 files changed, 454 insertions(+), 9 deletions(-) create mode 100644 deployments/mainnet/wbtc/configuration.json create mode 100644 deployments/mainnet/wbtc/deploy.ts create mode 100644 deployments/mainnet/wbtc/migrations/1737396251_configurate_and_ens.ts create mode 100644 deployments/mainnet/wbtc/relations.ts create mode 100644 deployments/mainnet/wbtc/roots.json diff --git a/.github/workflows/run-scenarios.yaml b/.github/workflows/run-scenarios.yaml index 49d63b2a1..cc4e6f0c9 100644 --- a/.github/workflows/run-scenarios.yaml +++ b/.github/workflows/run-scenarios.yaml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - bases: [ development, mainnet, mainnet-weth, mainnet-usdt, mainnet-wsteth, mainnet-usds, sepolia-usdc, sepolia-weth, fuji, polygon, polygon-usdt, arbitrum-usdc.e, arbitrum-usdc, arbitrum-weth, arbitrum-usdt, base-usdbc, base-weth, base-usdc, base-aero, optimism-usdc, optimism-usdt, optimism-weth, mantle-usde, scroll-usdc] + bases: [ development, mainnet, mainnet-weth, mainnet-wbtc, mainnet-usdt, mainnet-wsteth, mainnet-usds, sepolia-usdc, sepolia-weth, fuji, polygon, polygon-usdt, arbitrum-usdc.e, arbitrum-usdc, arbitrum-weth, arbitrum-usdt, base-usdbc, base-weth, base-usdc, base-aero, optimism-usdc, optimism-usdt, optimism-weth, mantle-usde, scroll-usdc] name: Run scenarios env: ETHERSCAN_KEY: ${{ secrets.ETHERSCAN_KEY }} diff --git a/deployments/mainnet/wbtc/configuration.json b/deployments/mainnet/wbtc/configuration.json new file mode 100644 index 000000000..696cc283f --- /dev/null +++ b/deployments/mainnet/wbtc/configuration.json @@ -0,0 +1,56 @@ +{ + "name": "Compound WBTC", + "symbol": "cWBTCv3", + "baseToken": "WBTC", + "baseTokenAddress": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", + "baseTokenPriceFeed": "0xfdFD9C85aD200c506Cf9e21F1FD8dd01932FBB23", + "borrowMin": "0.001e8", + "governor": "0x6d903f6003cca6255d85cca4d3b5e5146dc33925", + "pauseGuardian": "0xbbf3f1421d886e9b2c5d716b5192ac998af2012c", + "storeFrontPriceFactor": 0.7, + "targetReserves": "250e18", + "rates": { + "borrowBase": 0.01, + "borrowSlopeLow": 0.014, + "borrowKink": 0.85, + "borrowSlopeHigh": 1.15, + "supplyBase": 0, + "supplySlopeLow": 0.012, + "supplyKink": 0.85, + "supplySlopeHigh": 1 + }, + "tracking": { + "indexScale": "1e15", + "baseSupplySpeed": "0e0", + "baseBorrowSpeed": "0e0", + "baseMinForRewards": "0.1e18" + }, + "rewardTokenAddress": "0xc00e94Cb662C3520282E6f5717214004A7f26888", + "assets": { + "SolvBTC.BBN": { + "address": "0xd9D920AA40f578ab794426F5C90F6C731D159DEf", + "decimals": "18", + "borrowCF": 0.81, + "liquidateCF": 0.84, + "liquidationFactor": 0.9, + "supplyCap": "0e18" + }, + "LBTC": { + "address": "0x8236a87084f8B84306f72007F36F2618A5634494", + "priceFeed": "0x5c29868C58b6e15e2b962943278969Ab6a7D3212", + "decimals": "8", + "borrowCF": 0.73, + "liquidateCF": 0.75, + "liquidationFactor": 0.95, + "supplyCap": "0e18" + }, + "pumpBTC": { + "address": "0xF469fBD2abcd6B9de8E169d128226C0Fc90a012e", + "decimals": "8", + "borrowCF": 0.75, + "liquidateCF": 0.78, + "liquidationFactor": 0.9, + "supplyCap": "0e8" + } + } +} \ No newline at end of file diff --git a/deployments/mainnet/wbtc/deploy.ts b/deployments/mainnet/wbtc/deploy.ts new file mode 100644 index 000000000..f976ea9b0 --- /dev/null +++ b/deployments/mainnet/wbtc/deploy.ts @@ -0,0 +1,51 @@ +import { Deployed, DeploymentManager } from '../../../plugins/deployment_manager'; +import { DeploySpec, deployComet, exp } from '../../../src/deploy'; + +export default async function deploy(deploymentManager: DeploymentManager, deploySpec: DeploySpec): Promise { + const WBTC = await deploymentManager.existing('WBTC', '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599'); + const solvBTC_BBN = await deploymentManager.existing('SolvBTC.BBN', '0xd9D920AA40f578ab794426F5C90F6C731D159DEf'); + const LBTC = await deploymentManager.existing('LBTC', '0x8236a87084f8B84306f72007F36F2618A5634494'); + const pumpBTC = await deploymentManager.existing('pumpBTC', '0xF469fBD2abcd6B9de8E169d128226C0Fc90a012e'); + const COMP = await deploymentManager.existing('COMP', '0xc00e94Cb662C3520282E6f5717214004A7f26888'); + + const solvBTC_BBNPriceFeed = await deploymentManager.deploy( + 'SolvBTC.BBN:priceFeed', + 'pricefeeds/MultiplicativePriceFeed.sol', + [ + '0x1f34794A16D644b9810477EbF3f0b3870141E2e3', // SolvBTC.BBN / SolvBTC price feed + '0x936B31C428C29713343E05D631e69304f5cF5f49', // SolvBTC / BTC price feed + 8, // decimals + 'solvBTC.BBN / BTC price feed' // description + ], + true + ); + + // Deploy scaling price feed for pumpBTC + const pumpBTCScalingPriceFeed = await deploymentManager.deploy( + 'pumpBTC:priceFeed', + 'pricefeeds/ScalingPriceFeed.sol', + [ + '0x6CE4Ef3689F26edD40ed3ccbE3Cc29dab62C915f', // pumpBTC / BTC price feed + 8 // decimals + ], + true + ); + + // Import shared contracts from cUSDCv3 + const cometAdmin = await deploymentManager.fromDep('cometAdmin', 'mainnet', 'usdc'); + const cometFactory = await deploymentManager.fromDep('cometFactory', 'mainnet', 'usdc'); + const $configuratorImpl = await deploymentManager.fromDep('configurator:implementation', 'mainnet', 'usdc'); + const configurator = await deploymentManager.fromDep('configurator', 'mainnet', 'usdc'); + const rewards = await deploymentManager.fromDep('rewards', 'mainnet', 'usdc'); + const bulker = await deploymentManager.fromDep('bulker', 'mainnet', 'weth'); + + // Deploy Comet + const deployed = await deployComet(deploymentManager, deploySpec); + + return { + ...deployed, + bulker, + rewards, + COMP + }; +} \ No newline at end of file diff --git a/deployments/mainnet/wbtc/migrations/1737396251_configurate_and_ens.ts b/deployments/mainnet/wbtc/migrations/1737396251_configurate_and_ens.ts new file mode 100644 index 000000000..644fdcc6a --- /dev/null +++ b/deployments/mainnet/wbtc/migrations/1737396251_configurate_and_ens.ts @@ -0,0 +1,264 @@ +import { ethers, utils } from 'ethers'; +import { DeploymentManager } from '../../../../plugins/deployment_manager/DeploymentManager'; +import { migration } from '../../../../plugins/deployment_manager/Migration'; +import { exp, getConfigurationStruct, proposal } from '../../../../src/deploy'; +import { expect } from 'chai'; + +const ENSName = 'compound-community-licenses.eth'; +const ENSResolverAddress = '0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41'; +const ENSRegistryAddress = '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'; +const ENSSubdomainLabel = 'v3-additional-grants'; +const ENSSubdomain = `${ENSSubdomainLabel}.${ENSName}`; +const ENSTextRecordKey = 'v3-official-markets'; + +const cWBTCAddress = '0xC11b1268C1A384e55C48c2391d8d480264A3A7F4'; +const WBTCAmount = ethers.BigNumber.from(exp(2, 8)); + +export default migration('1737396251_configurate_and_ens', { + async prepare() { + return {}; + }, + + async enact(deploymentManager: DeploymentManager) { + const trace = deploymentManager.tracer(); + + const { + comet, + cometAdmin, + configurator, + rewards, + COMP, + WBTC, + governor + } = await deploymentManager.getContracts(); + const cometFactory = await deploymentManager.fromDep('cometFactory', 'mainnet', 'usdc'); + + const configuration = await getConfigurationStruct(deploymentManager); + + const ENSResolver = await deploymentManager.existing('ENSResolver', ENSResolverAddress); + const subdomainHash = ethers.utils.namehash(ENSSubdomain); + const currentChainId = 1; + const newMarketObject = { baseSymbol: 'WBTC', cometAddress: comet.address }; + const officialMarketsJSON = JSON.parse(await ENSResolver.text(subdomainHash, ENSTextRecordKey)); + + if (officialMarketsJSON[currentChainId]) { + officialMarketsJSON[currentChainId].push(newMarketObject); + } else { + officialMarketsJSON[currentChainId] = [newMarketObject]; + } + + const _reduceReservesCalldata = utils.defaultAbiCoder.encode( + ['uint256'], + [WBTCAmount] + ); + + const actions = [ + // 1. Set the Comet factory in configuration + { + contract: configurator, + signature: 'setFactory(address,address)', + args: [comet.address, cometFactory.address], + }, + // 2. Set the Comet configuration + { + contract: configurator, + signature: 'setConfiguration(address,(address,address,address,address,address,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint104,uint104,uint104,(address,address,uint8,uint64,uint64,uint64,uint128)[]))', + args: [comet.address, configuration], + }, + // 3. Deploy Comet and upgrade it to the new implementation + { + contract: cometAdmin, + signature: 'deployAndUpgradeTo(address,address)', + args: [configurator.address, comet.address], + }, + // 4. Set the reward configuration + { + contract: rewards, + signature: 'setRewardConfig(address,address)', + args: [comet.address, COMP.address], + }, + // 5. Get WBTC reserves from cWBTC contract + { + target: cWBTCAddress, + signature: '_reduceReserves(uint256)', + calldata: _reduceReservesCalldata + }, + // 6. Transfer WBTC to the Comet contract + { + contract: WBTC, + signature: 'transfer(address,uint256)', + args: [comet.address, WBTCAmount], + }, + // 7. Update the list of official markets + { + target: ENSResolverAddress, + signature: 'setText(bytes32,string,string)', + calldata: ethers.utils.defaultAbiCoder.encode( + ['bytes32', 'string', 'string'], + [subdomainHash, ENSTextRecordKey, JSON.stringify(officialMarketsJSON)] + ) + } + ]; + + const description = 'DESCRIPTION'; + const txn = await deploymentManager.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(): Promise { + return false; + }, + + async verify(deploymentManager: DeploymentManager) { + const { + comet, + rewards, + timelock, + COMP, + pumpBTC, + 'SolvBTC.BBN': solvBTC_BBN, + LBTC + } = await deploymentManager.getContracts(); + + // 1. & 2. & 3. + const solvBTC_BBNInfo = await comet.getAssetInfoByAddress(solvBTC_BBN.address); + const lbtcInfo = await comet.getAssetInfoByAddress(LBTC.address); + const pumpBTCInfo = await comet.getAssetInfoByAddress(pumpBTC.address); + + // expect(solvBTC_BBNInfo.supplyCap).to.be.eq(exp(18, 18)); + // expect(lbtcInfo.supplyCap).to.be.eq(exp(200, 8)); + // expect(pumpBTCInfo.supplyCap).to.be.eq(exp(15, 8)); + + // expect(await comet.baseTrackingSupplySpeed()).to.be.equal(exp(1 / 86400, 15, 18)); // 11574074074 + expect(await comet.baseTrackingBorrowSpeed()).to.be.equal(exp(0)); + + + // 4 + const config = await rewards.rewardConfig(comet.address); + expect(config.token).to.be.equal(COMP.address); + expect(config.rescaleFactor).to.be.equal(exp(1, 12)); + expect(config.shouldUpscale).to.be.equal(true); + + expect((await comet.pauseGuardian()).toLowerCase()).to.be.eq('0xbbf3f1421d886e9b2c5d716b5192ac998af2012c'); + + // 5. & 6. + expect(await comet.getReserves()).to.be.equal(WBTCAmount); + + // 7. + const ENSResolver = await deploymentManager.existing('ENSResolver', ENSResolverAddress); + const ENSRegistry = await deploymentManager.existing('ENSRegistry', ENSRegistryAddress); + const subdomainHash = ethers.utils.namehash(ENSSubdomain); + const officialMarketsJSON = await ENSResolver.text(subdomainHash, ENSTextRecordKey); + const officialMarkets = JSON.parse(officialMarketsJSON); + expect(await ENSRegistry.recordExists(subdomainHash)).to.be.equal(true); + expect(await ENSRegistry.owner(subdomainHash)).to.be.equal(timelock.address); + expect(await ENSRegistry.resolver(subdomainHash)).to.be.equal(ENSResolverAddress); + expect(await ENSRegistry.ttl(subdomainHash)).to.be.equal(0); + expect(officialMarkets).to.deep.equal({ + 1: [ + { + baseSymbol: 'USDC', + cometAddress: '0xc3d688B66703497DAA19211EEdff47f25384cdc3' + }, + { + baseSymbol: 'WETH', + cometAddress: '0xA17581A9E3356d9A858b789D68B4d866e593aE94' + }, + { + baseSymbol: 'USDT', + cometAddress: '0x3Afdc9BCA9213A35503b077a6072F3D0d5AB0840' + }, + { + baseSymbol: 'wstETH', + cometAddress: '0x3D0bb1ccaB520A66e607822fC55BC921738fAFE3' + }, + { + baseSymbol: 'USDS', + cometAddress: '0x5D409e56D886231aDAf00c8775665AD0f9897b56' + }, + { + baseSymbol: 'WBTC', + cometAddress: comet.address + } + ], + 10: [ + { + baseSymbol: 'USDC', + cometAddress: '0x2e44e174f7D53F0212823acC11C01A11d58c5bCB' + }, + { + baseSymbol: 'USDT', + cometAddress: '0x995E394b8B2437aC8Ce61Ee0bC610D617962B214' + }, + { + baseSymbol: 'WETH', + cometAddress: '0xE36A30D249f7761327fd973001A32010b521b6Fd' + } + ], + 137: [ + { + baseSymbol: 'USDC', + cometAddress: '0xF25212E676D1F7F89Cd72fFEe66158f541246445' + }, + { + baseSymbol: 'USDT', + cometAddress: '0xaeB318360f27748Acb200CE616E389A6C9409a07' + } + ], + 5000: [ + { + baseSymbol: 'USDe', + cometAddress: '0x606174f62cd968d8e684c645080fa694c1D7786E' + } + ], + 8453: [ + { + baseSymbol: 'USDbC', + cometAddress: '0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf' + }, + { + baseSymbol: 'WETH', + cometAddress: '0x46e6b214b524310239732D51387075E0e70970bf' + }, + { + baseSymbol: 'USDC', + cometAddress: '0xb125E6687d4313864e53df431d5425969c15Eb2F' + }, + { + baseSymbol: 'AERO', + cometAddress: '0x784efeB622244d2348d4F2522f8860B96fbEcE89' + }, + ], + 42161: [ + { + baseSymbol: 'USDC.e', + cometAddress: '0xA5EDBDD9646f8dFF606d7448e414884C7d905dCA' + }, + { + baseSymbol: 'USDC', + cometAddress: '0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf' + }, + { + baseSymbol: 'WETH', + cometAddress: '0x6f7D514bbD4aFf3BcD1140B7344b32f063dEe486' + }, + { + baseSymbol: 'USDT', + cometAddress: '0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07' + } + ], + 534352: [ + { + baseSymbol: 'USDC', + cometAddress: '0xB2f97c1Bd3bf02f5e74d13f02E3e26F93D77CE44' + } + ] + }); + } +}); diff --git a/deployments/mainnet/wbtc/relations.ts b/deployments/mainnet/wbtc/relations.ts new file mode 100644 index 000000000..9a4018c62 --- /dev/null +++ b/deployments/mainnet/wbtc/relations.ts @@ -0,0 +1,41 @@ +import { RelationConfigMap } from '../../../plugins/deployment_manager/RelationConfig'; +import baseRelationConfig from '../../relations'; + +export default { + ...baseRelationConfig, + 'wstETH': { + artifact: 'contracts/bulkers/IWstETH.sol', + relations: { + stETH: { + field: async (wstETH) => wstETH.stETH() + } + } + }, + 'AppProxyUpgradeable': { + artifact: 'contracts/ERC20.sol:ERC20', + }, + 'ERC1967Proxy': { + artifact: 'contracts/ERC20.sol:ERC20', + delegates: { + field: { + slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' + } + } + }, + 'BeaconProxy': { + artifact: 'contracts/ERC20.sol:ERC20', + delegates: { + field: { + slot: '0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50' + } + } + }, + 'TransparentUpgradeableProxy': { + artifact: 'contracts/ERC20.sol:ERC20', + delegates: { + field: { + slot: '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' + } + } + }, +}; \ No newline at end of file diff --git a/deployments/mainnet/wbtc/roots.json b/deployments/mainnet/wbtc/roots.json new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/deployments/mainnet/wbtc/roots.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index a50fbd87a..2f615acd2 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -25,6 +25,7 @@ import mainnetWethRelationConfigMap from './deployments/mainnet/weth/relations'; import mainnetUsdtRelationConfigMap from './deployments/mainnet/usdt/relations'; import mainnetWstETHRelationConfigMap from './deployments/mainnet/wsteth/relations'; import mainnetUsdsRelationConfigMap from './deployments/mainnet/usds/relations'; +import mainnetWbtcRelationConfigMap from './deployments/mainnet/wbtc/relations'; import polygonRelationConfigMap from './deployments/polygon/usdc/relations'; import polygonUsdtRelationConfigMap from './deployments/polygon/usdt/relations'; import arbitrumBridgedUsdcRelationConfigMap from './deployments/arbitrum/usdc.e/relations'; @@ -306,6 +307,7 @@ const config: HardhatUserConfig = { usdt: mainnetUsdtRelationConfigMap, wsteth: mainnetWstETHRelationConfigMap, usds: mainnetUsdsRelationConfigMap, + wbtc: mainnetWbtcRelationConfigMap, }, polygon: { usdc: polygonRelationConfigMap, @@ -365,6 +367,11 @@ const config: HardhatUserConfig = { network: 'mainnet', deployment: 'usds' }, + { + name: 'mainnet-wbtc', + network: 'mainnet', + deployment: 'wbtc' + }, { name: 'development', network: 'hardhat', diff --git a/scenario/LiquidationBotScenario.ts b/scenario/LiquidationBotScenario.ts index e6fdae1a0..a7be9ebc5 100644 --- a/scenario/LiquidationBotScenario.ts +++ b/scenario/LiquidationBotScenario.ts @@ -789,7 +789,7 @@ scenario( upgrade: { targetReserves: exp(20_000, 18) }, - filter: async (ctx) => matchesDeployment(ctx, [{ network: 'mainnet' }]) && !matchesDeployment(ctx, [{deployment: 'wsteth'}, {deployment: 'usds'}]), + filter: async (ctx) => matchesDeployment(ctx, [{ network: 'mainnet' }]) && !matchesDeployment(ctx, [{deployment: 'wsteth'}, {deployment: 'usds'}, {deployment: 'wbtc'}]), tokenBalances: async (ctx) => ( { $comet: { diff --git a/scenario/RewardsScenario.ts b/scenario/RewardsScenario.ts index a879a2bbe..cd8a6fa86 100644 --- a/scenario/RewardsScenario.ts +++ b/scenario/RewardsScenario.ts @@ -5,6 +5,7 @@ import { isRewardSupported, matchesDeployment } from './utils'; import { Contract, ContractReceipt } from 'ethers'; import { CometRewards, ERC20__factory } from '../build/types'; import {World} from '../plugins/scenario'; +import { getConfigForScenario } from './utils/scenarioHelper'; function calculateRewardsOwed( userBalance: bigint, @@ -152,20 +153,22 @@ scenario( 'Comet#rewards > can claim borrow rewards for self', { filter: async (ctx) => await isRewardSupported(ctx), - tokenBalances: { - albert: { $asset0: ' == 10000' }, // in units of asset, not wei - $comet: { $base: ' >= 1000 ' } - }, + tokenBalances: async (ctx) => ( + { + albert: { $asset0: ` == ${getConfigForScenario(ctx).rewardsAsset}` }, // in units of asset, not wei + $comet: { $base: ` >= ${getConfigForScenario(ctx).rewardsBase} ` } + } + ) }, async ({ comet, rewards, actors }, context, world) => { const { albert } = actors; const { asset: collateralAssetAddress, scale: scaleBN } = await comet.getAssetInfo(0); const collateralAsset = context.getAssetByAddress(collateralAssetAddress); const scale = scaleBN.toBigInt(); - const toSupply = 10_000n * scale; + const toSupply = BigInt(getConfigForScenario(context).rewardsAsset) * scale; const baseAssetAddress = await comet.baseToken(); const baseScale = (await comet.baseScale()).toBigInt(); - const toBorrow = 1_000n * baseScale; + const toBorrow = BigInt(getConfigForScenario(context).rewardsBase) * baseScale; const { rescaleFactor } = await context.getRewardConfig(); const rewardToken = await context.getRewardToken(); diff --git a/scenario/SupplyScenario.ts b/scenario/SupplyScenario.ts index e12d04a31..1c862bfd4 100644 --- a/scenario/SupplyScenario.ts +++ b/scenario/SupplyScenario.ts @@ -508,6 +508,7 @@ scenario( /Dai\/insufficient-allowance/, symbol === 'WETH' ? /Transaction reverted without a reason string/ : /.^/, symbol === 'wstETH' ? /0xc2139725/ : /.^/, + symbol === 'SolvBTC.BBN' ? /0xfb8f41b2/ : /.^/, symbol === 'WMATIC' ? /Transaction reverted without a reason string/ : /.^/, symbol === 'WPOL' ? /Transaction reverted without a reason string/ : /.^/, ] @@ -595,6 +596,7 @@ scenario( /Dai\/insufficient-balance/, symbol === 'WETH' ? /Transaction reverted without a reason string/ : /.^/, symbol === 'wstETH' ? /0x00b284f2/ : /.^/, + symbol === 'SolvBTC.BBN' ? /0xe450d38c/ : /.^/, symbol === 'WMATIC' ? /Transaction reverted without a reason string/ : /.^/, symbol === 'WPOL' ? /Transaction reverted without a reason string/ : /.^/, ] diff --git a/scenario/utils/scenarioHelper.ts b/scenario/utils/scenarioHelper.ts index 30b430b34..bd9e17110 100644 --- a/scenario/utils/scenarioHelper.ts +++ b/scenario/utils/scenarioHelper.ts @@ -29,6 +29,8 @@ export function getConfigForScenario(ctx: CometContext) { config.bulkerAsset1 = 200; config.bulkerComet = 200; config.bulkerBorrowBase = 100; + config.withdrawBase = 100; + config.withdrawAsset = 200; config.bulkerBorrowAsset = 50; config.liquidationBase = 1000; config.liquidationBase1 = 500; @@ -37,6 +39,7 @@ export function getConfigForScenario(ctx: CometContext) { config.rewardsBase = 100; config.transferBase = 100; config.transferAsset = 500; + config.transferAsset1 = 500; config.interestSeconds = 70; } diff --git a/scripts/liquidation_bot/liquidateUnderwaterBorrowers.ts b/scripts/liquidation_bot/liquidateUnderwaterBorrowers.ts index 1c42437c0..b5b2dc1c3 100644 --- a/scripts/liquidation_bot/liquidateUnderwaterBorrowers.ts +++ b/scripts/liquidation_bot/liquidateUnderwaterBorrowers.ts @@ -39,6 +39,7 @@ const addresses = { WETH9: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', CB_ETH: '0xBe9895146f7AF43049ca1c1AE358B0541Ea49704', WST_ETH: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0', + SOLVBTC_BBN: '0xd9D920AA40f578ab794426F5C90F6C731D159DEf', RS_ETH: '0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7', USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7' }, @@ -97,7 +98,11 @@ export const flashLoanPools = { usds: { tokenAddress: addresses.mainnet.DAI, poolFee: 3000, - } + }, + wbtc: { + tokenAddress: addresses.mainnet.WETH9, + poolFee: 500 + }, }, polygon: { usdc: { @@ -200,6 +205,14 @@ export function getPoolConfig(tokenAddress: string) { balancerPoolId: '0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080' } }, + [addresses.mainnet.SOLVBTC_BBN.toLowerCase()]: { + ...defaultPoolConfig, + ...{ + exchange: Exchange.Uniswap, + swapViaWeth: false, + uniswapPoolFee: 500 + } + }, [addresses.polygon.WMATIC.toLowerCase()]: { ...defaultPoolConfig, ...{ diff --git a/src/deploy/index.ts b/src/deploy/index.ts index febb0ab9b..94dea29f3 100644 --- a/src/deploy/index.ts +++ b/src/deploy/index.ts @@ -94,6 +94,9 @@ export const WHALES = { '0x43594da5d6A03b2137a04DF5685805C676dEf7cB', // rsETH whale '0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b', '0x0B925eD163218f6662a35e0f0371Ac234f9E9371', // wstETH whale + '0x3b3501f6778Bfc56526cF2aC33b78b2fDBE4bc73', // solvBTC.BBN whale + '0x8bc93498b861fd98277c3b51d240e7E56E48F23c', // solvBTC.BBN whale + '0xD5cf704dC17403343965b4F9cd4D7B5e9b20CC52', // solvBTC.BBN whale ], polygon: [ '0x2093b4281990a568c9d588b8bce3bfd7a1557ebd', // WETH whale From 5dcf2d7e16ee961f1531618870c1786d3abb3bfd Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Wed, 22 Jan 2025 15:58:34 +0200 Subject: [PATCH 43/45] feat: description --- .../mainnet/wbtc/migrations/1737396251_configurate_and_ens.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployments/mainnet/wbtc/migrations/1737396251_configurate_and_ens.ts b/deployments/mainnet/wbtc/migrations/1737396251_configurate_and_ens.ts index 644fdcc6a..3b67220cf 100644 --- a/deployments/mainnet/wbtc/migrations/1737396251_configurate_and_ens.ts +++ b/deployments/mainnet/wbtc/migrations/1737396251_configurate_and_ens.ts @@ -100,7 +100,7 @@ export default migration('1737396251_configurate_and_ens', { } ]; - const description = 'DESCRIPTION'; + const description = '# Initialize cWBTCv3 on Ethereum Mainnet\n\n## Proposal summary\n\nCompound Growth Program [AlphaGrowth] proposes the deployment of Compound III to the Mainnet network. This proposal takes the governance steps recommended and necessary to initialize a Compound III WBTC market on Mainnet; upon execution, cWBTCv3 will be ready for use. 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-market-wbtc-on-mainnet/5644/9).\n\nFurther detailed information can be found on the corresponding [proposal pull request](https://github.com/compound-finance/comet/pull/954), [deploy market GitHub action run](<>) and [forum discussion](https://www.comp.xyz/t/add-market-wbtc-on-mainnet/5644).\n\n\n## Proposal Actions\n\nThe first proposal action sets the CometFactory for the new Comet instance in the existing Configurator.\n\nThe second action configures the Comet instance in the Configurator.\n\nThe third action deploys an instance of the newly configured factory and upgrades the Comet instance to use that implementation.\n\nThe fourth action configures the existing rewards contract for the newly deployed Comet instance.\n\nThe fifth action reduces Compound’s [cWBTC](https://etherscan.io/address/0xC11b1268C1A384e55C48c2391d8d480264A3A7F4) reserves and transfers it to Timelock, in order to seed the market reserves for the cWBTCv3 Comet.\n\nThe sixth action transfers reserves from Timelock to the cWBTCv3 Comet.\n\nThe seventh action updates the ENS TXT record `v3-official-markets` on `v3-additional-grants.compound-community-licenses.eth`, updating the official markets JSON to include the new Ethereum Mainnet cWBTCv3 market.'; const txn = await deploymentManager.retry( async () => trace((await governor.propose(...await proposal(actions, description)))) ); From 26d14c3e9cc5b3901f045258043c9f9cf3fd462e Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Wed, 22 Jan 2025 16:01:48 +0200 Subject: [PATCH 44/45] fix: small decimals fix --- deployments/mainnet/wbtc/configuration.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployments/mainnet/wbtc/configuration.json b/deployments/mainnet/wbtc/configuration.json index 696cc283f..41d2fbe10 100644 --- a/deployments/mainnet/wbtc/configuration.json +++ b/deployments/mainnet/wbtc/configuration.json @@ -42,7 +42,7 @@ "borrowCF": 0.73, "liquidateCF": 0.75, "liquidationFactor": 0.95, - "supplyCap": "0e18" + "supplyCap": "0e8" }, "pumpBTC": { "address": "0xF469fBD2abcd6B9de8E169d128226C0Fc90a012e", From 70bb11feab2b7f4af1ee33d79b9db5a671c1a44f Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Thu, 23 Jan 2025 13:42:01 +0200 Subject: [PATCH 45/45] fix: fixes after review --- deployments/mainnet/wbtc/configuration.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deployments/mainnet/wbtc/configuration.json b/deployments/mainnet/wbtc/configuration.json index 41d2fbe10..02091b899 100644 --- a/deployments/mainnet/wbtc/configuration.json +++ b/deployments/mainnet/wbtc/configuration.json @@ -8,7 +8,7 @@ "governor": "0x6d903f6003cca6255d85cca4d3b5e5146dc33925", "pauseGuardian": "0xbbf3f1421d886e9b2c5d716b5192ac998af2012c", "storeFrontPriceFactor": 0.7, - "targetReserves": "250e18", + "targetReserves": "250e8", "rates": { "borrowBase": 0.01, "borrowSlopeLow": 0.014, @@ -23,7 +23,7 @@ "indexScale": "1e15", "baseSupplySpeed": "0e0", "baseBorrowSpeed": "0e0", - "baseMinForRewards": "0.1e18" + "baseMinForRewards": "1e8" }, "rewardTokenAddress": "0xc00e94Cb662C3520282E6f5717214004A7f26888", "assets": {