Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Сomet with extended asset list #904

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
bba7d99
feat: create comet with extended asset list
MishaShWoof Aug 9, 2024
fc16ae0
feat: move new cometExt to its own contract
MishaShWoof Aug 12, 2024
6b62ee6
fix: clean up
MishaShWoof Aug 12, 2024
d06a3f6
fix: gas optimization
MishaShWoof Aug 12, 2024
d2873ad
fix: more gas optimization
MishaShWoof Aug 12, 2024
5e867a0
fix: linter fix
MishaShWoof Aug 12, 2024
8ab1786
fix: natspec
MishaShWoof Aug 12, 2024
171eb7a
fix: more natspec
MishaShWoof Aug 12, 2024
53f1513
Update index.ts
MishaShWoof Aug 23, 2024
8df38e6
fix: remove unused iterface
MishaShWoof Aug 26, 2024
70e8a73
feat: add prepare and enact for simulation
MishaShWoof Aug 26, 2024
4c0a8f4
fix: fix to workflow
MishaShWoof Aug 26, 2024
c29f4b9
Update enact-migration.yaml
MishaShWoof Aug 26, 2024
cf08c19
fix: reverse
MishaShWoof Aug 26, 2024
71fee7b
feat: add prepare and enact workflow
MishaShWoof Aug 26, 2024
57d04f7
feat: update enact migration script
dmitriy-woof-software Aug 26, 2024
f0c33a1
feat: update enact migration script
dmitriy-woof-software Aug 26, 2024
df2d152
feat: update enact migration script
dmitriy-woof-software Aug 26, 2024
92937aa
feat: update enact migration script
dmitriy-woof-software Aug 26, 2024
b72092c
fix: remove verification from simulatative migration
MishaShWoof Aug 27, 2024
ea15450
Merge branch 'main' of github.com:woof-software/comet into woof-softw…
MishaShWoof Sep 17, 2024
dfe98c9
feat: fixes after audit
MishaShWoof Sep 19, 2024
4f2ba04
fix: working tests
MishaShWoof Sep 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions .github/workflows/enact-migration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand All @@ -129,7 +129,18 @@ 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 }}
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: |
Expand Down
131 changes: 131 additions & 0 deletions contracts/AssetList.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;

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) {
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;
}

/**
* @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
});
}
}
17 changes: 17 additions & 0 deletions contracts/AssetListFactory.sol
Original file line number Diff line number Diff line change
@@ -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);
}
}
2 changes: 1 addition & 1 deletion contracts/CometExt.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 23 additions & 0 deletions contracts/CometExtAssetList.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;

import "./CometExt.sol";

contract CometExtAssetList is CometExt {

/// @notice The address of the asset list factory
address immutable public assetListFactory;

/**
* @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;
}

uint8 internal constant MAX_ASSETS_FOR_ASSET_LIST = 24;

function maxAssets() override external pure returns (uint8) { return MAX_ASSETS_FOR_ASSET_LIST; }
}
Loading