Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Override asset configs for multiple collaterals #186

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
Overrides:
kasperpawlowski marked this conversation as resolved.
Show resolved Hide resolved
? how is BF=0 handled in liquidations

Lending logic:
g when a token has < 18 decimal places, and a user withdraws their full EToken balance, 0 out the remaining dust so user gets a storage refund

Expand Down
1 change: 1 addition & 0 deletions addresses/euler-addresses-mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"SwapHandlerUniswapV3": "0x7527E082300fb8D189B3c07dB3BEcc990B5037E7"
},
"eulerGeneralView": "0xACC25c4d40651676FEEd43a3467F3169e3E68e42",
"eulerLensV1": "0xACC25c4d40651676FEEd43a3467F3169e3E68e42",
"eulerSimpleLens": "0x5077B7642abF198b4a5b7C4BdCE4f03016C7089C",
"euler": "0x27182842E098f60e3D576794A5bFFb0777E025d3",
"installer": "0x055DE1CCbCC9Bc5291569a0b6aFFdF8b5707aB16",
Expand Down
5 changes: 3 additions & 2 deletions contracts/BaseLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -574,12 +574,13 @@ abstract contract BaseLogic is BaseModule {
return abi.decode(result, (uint));
}

function getAccountLiquidity(address account) internal returns (uint collateralValue, uint liabilityValue) {
function getAccountLiquidity(address account) internal returns (uint collateralValue, uint liabilityValue, uint overrideCollateralValue) {
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER, abi.encodeWithSelector(IRiskManager.computeLiquidity.selector, account));
(IRiskManager.LiquidityStatus memory status) = abi.decode(result, (IRiskManager.LiquidityStatus));

collateralValue = status.collateralValue;
liabilityValue = status.liabilityValue;
overrideCollateralValue = status.overrideCollateralValue;
}

function checkLiquidity(address account) internal {
Expand All @@ -603,7 +604,7 @@ abstract contract BaseLogic is BaseModule {
uint currAverageLiquidity;

{
(uint collateralValue, uint liabilityValue) = getAccountLiquidity(account);
(uint collateralValue, uint liabilityValue,) = getAccountLiquidity(account);
currAverageLiquidity = collateralValue > liabilityValue ? collateralValue - liabilityValue : 0;
}

Expand Down
1 change: 1 addition & 0 deletions contracts/Events.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ abstract contract Events {
event GovSetReserveFee(address indexed underlying, uint32 newReserveFee);
event GovConvertReserves(address indexed underlying, address indexed recipient, uint amount);
event GovSetChainlinkPriceFeed(address indexed underlying, address chainlinkAggregator);
event GovSetOverride(address indexed liability, address indexed collateral, Storage.OverrideConfig newOverride);

event RequestSwap(address indexed accountIn, address indexed accountOut, address indexed underlyingIn, address underlyingOut, uint amount, uint swapType);
event RequestSwapHub(address indexed accountIn, address indexed accountOut, address indexed underlyingIn, address underlyingOut, uint amountIn, uint amountOut, uint mode, address swapHandler);
Expand Down
1 change: 1 addition & 0 deletions contracts/IRiskManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface IRiskManager {
uint liabilityValue;
uint numBorrows;
bool borrowIsolated;
uint overrideCollateralValue;
}

struct AssetLiquidity {
Expand Down
9 changes: 9 additions & 0 deletions contracts/Storage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,13 @@ abstract contract Storage is Constants {
mapping(address => address) internal pTokenLookup; // PToken => underlying
mapping(address => address) internal reversePTokenLookup; // underlying => PToken
mapping(address => address) internal chainlinkPriceFeedLookup; // underlying => chainlinkAggregator

struct OverrideConfig {
bool enabled;
dglowinski marked this conversation as resolved.
Show resolved Hide resolved
uint32 collateralFactor;
}

mapping(address => mapping(address => OverrideConfig)) internal overrideLookup; // liability => collateral => OverrideConfig
mapping(address => address[]) internal overrideCollaterals; // liability => collaterals
mapping(address => address[]) internal overrideLiabilities; // collateral => liabilities
}
8 changes: 0 additions & 8 deletions contracts/modules/EToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,6 @@ contract EToken is BaseLogic {

increaseBalance(assetStorage, assetCache, proxyAddr, account, amountInternal);

// Depositing a token to an account with pre-existing debt in that token creates a self-collateralized loan
// which may result in borrow isolation violation if other tokens are also borrowed on the account
if (assetStorage.users[account].owed != 0) checkLiquidity(account);

dglowinski marked this conversation as resolved.
Show resolved Hide resolved
logAssetStatus(assetCache);
}

Expand Down Expand Up @@ -344,10 +340,6 @@ contract EToken is BaseLogic {

checkLiquidity(from);

// Depositing a token to an account with pre-existing debt in that token creates a self-collateralized loan
// which may result in borrow isolation violation if other tokens are also borrowed on the account
if (assetStorage.users[to].owed != 0) checkLiquidity(to);

logAssetStatus(assetCache);

return true;
Expand Down
43 changes: 42 additions & 1 deletion contracts/modules/Exec.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ contract Exec is BaseLogic {
/// @notice Compute detailed liquidity for an account, broken down by asset
/// @param account User address
/// @return assets List of user's entered assets and each asset's corresponding liquidity
function detailedLiquidity(address account) public staticDelegate returns (IRiskManager.AssetLiquidity[] memory assets) {
function liquidityPerAsset(address account) public staticDelegate returns (IRiskManager.AssetLiquidity[] memory assets) {
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER,
abi.encodeWithSelector(IRiskManager.computeAssetLiquidities.selector, account));

Expand Down Expand Up @@ -321,4 +321,45 @@ contract Exec is BaseLogic {
if (status == DEFERLIQUIDITY__DIRTY) checkLiquidity(account);
}
}




// Deprecated functions for backward compatibility. May be removed in the future.

struct LegacyLiquidityStatus {
uint collateralValue;
uint liabilityValue;
uint numBorrows;
bool borrowIsolated;
}
struct LegacyAssetLiquidity {
address underlying;
LegacyLiquidityStatus status;
}

// DEPRECATED. Use liquidityPerAsset instead.
function detailedLiquidity(address account) public staticDelegate returns (LegacyAssetLiquidity[] memory) {
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER,
abi.encodeWithSelector(IRiskManager.computeAssetLiquidities.selector, account));

(IRiskManager.AssetLiquidity[] memory assetLiquidities) = abi.decode(result, (IRiskManager.AssetLiquidity[]));

LegacyAssetLiquidity[] memory assets = new LegacyAssetLiquidity[](assetLiquidities.length);

for (uint i = 0; i < assetLiquidities.length; ++i) {
IRiskManager.LiquidityStatus memory status = assetLiquidities[i].status;
assets[i] = LegacyAssetLiquidity({
underlying: assetLiquidities[i].underlying,
status: LegacyLiquidityStatus({
collateralValue: status.collateralValue,
liabilityValue: status.liabilityValue,
numBorrows: status.numBorrows,
borrowIsolated: status.borrowIsolated
})
});
}

return assets;
}
}
32 changes: 28 additions & 4 deletions contracts/modules/Governance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,6 @@ contract Governance is BaseLogic {

increaseBalance(assetStorage, assetCache, eTokenAddress, recipient, amount);

// Depositing a token to an account with pre-existing debt in that token creates a self-collateralized loan
// which may result in borrow isolation violation if other tokens are also borrowed on the account
if (assetStorage.users[recipient].owed != 0) checkLiquidity(recipient);

logAssetStatus(assetCache);

emit GovConvertReserves(underlying, recipient, balanceToUnderlyingAmount(assetCache, amount));
Expand All @@ -117,6 +113,34 @@ contract Governance is BaseLogic {
emit GovSetChainlinkPriceFeed(underlying, chainlinkAggregator);
}

function setOverride(address liability, address collateral, OverrideConfig calldata newOverride) external nonReentrant governorOnly {
overrideLookup[liability][collateral] = newOverride;

updateOverridesArray(overrideCollaterals[liability], collateral, newOverride);
updateOverridesArray(overrideLiabilities[collateral], liability, newOverride);

emit GovSetOverride(liability, collateral, newOverride);
}

function updateOverridesArray(address[] storage arr, address asset, OverrideConfig calldata newOverride) private {
uint length = arr.length;
if (newOverride.enabled) {
for (uint i = 0; i < length;) {
if (arr[i] == asset) return;
unchecked { ++i; }
}
arr.push(asset);
} else {
for (uint i = 0; i < length;) {
if (arr[i] == asset) {
arr[i] = arr[length - 1];
arr.pop();
return;
}
unchecked { ++i; }
}
}
}

// getters

Expand Down
Loading