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

Commit

Permalink
allow override of self-collateral factor
Browse files Browse the repository at this point in the history
  • Loading branch information
dglowinski committed Feb 16, 2023
1 parent ffed13f commit 8e29948
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 12 deletions.
14 changes: 3 additions & 11 deletions contracts/modules/Liquidation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -133,20 +133,12 @@ contract Liquidation is BaseLogic {

// If override is active for the liquidated pair, assume the resulting liability will be fully covered by override collateral, and adjust inputs
if (liqLocs.overrideCollateralValue > 0) {
if (liqLocs.underlying == liqLocs.collateral) { // liquidating self-collateral
collateralFactor = SELF_COLLATERAL_FACTOR;
overrideConfig = overrideLookup[liqLocs.underlying][liqLocs.collateral];
if (overrideConfig.enabled || liqLocs.underlying == liqLocs.collateral) { // the liquidated collateral has active override with liability
collateralFactor = overrideConfig.enabled ? overrideConfig.collateralFactor : SELF_COLLATERAL_FACTOR;
borrowFactor = CONFIG_FACTOR_SCALE;
// adjust the whole liability for override BF = 1
liqLocs.liabilityValue = liqLocs.currentOwed * liqLocs.underlyingPrice / 1e18;
} else {
overrideConfig = overrideLookup[liqLocs.underlying][liqLocs.collateral];

if (overrideConfig.enabled) { // the liquidated collateral has active override with liability
collateralFactor = overrideConfig.collateralFactor;
borrowFactor = CONFIG_FACTOR_SCALE;
// adjust the whole liability for override BF = 1
liqLocs.liabilityValue = liqLocs.currentOwed * liqLocs.underlyingPrice / 1e18;
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion contracts/modules/RiskManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,9 @@ contract RiskManager is IRiskManager, BaseLogic {

uint balanceInUnderlying = balanceToUnderlyingAmount(assetCache, balance);
uint assetCollateral = balanceInUnderlying * price / 1e18;
assetCollateral = assetCollateral * SELF_COLLATERAL_FACTOR / CONFIG_FACTOR_SCALE;
OverrideConfig memory overrideConfig = overrideLookup[underlying][underlying];
uint32 selfCollateralFactor = overrideConfig.enabled ? overrideConfig.collateralFactor : SELF_COLLATERAL_FACTOR;
assetCollateral = assetCollateral * selfCollateralFactor / CONFIG_FACTOR_SCALE;

// self-collateralization is an implicit override
status.overrideCollateralValue += assetCollateral;
Expand Down
90 changes: 90 additions & 0 deletions test/liquidationWithOverrides.js
Original file line number Diff line number Diff line change
Expand Up @@ -1137,4 +1137,94 @@ et.testSet({
],
})




.test({
desc: "XV Liquidate self-collateral with override on self-collateral factor",
dev: 1,
actions: ctx => [
{ action: 'setAssetConfig', tok: 'TST3', config: { collateralFactor: .5}, },
{ send: 'tokens.TST3.mint', args: [ctx.wallet2.address, et.eth(200)], },
{ from: ctx.wallet2, send: 'tokens.TST3.approve', args: [ctx.contracts.euler.address, et.MaxUint256,], },
{ from: ctx.wallet2, send: 'eTokens.eTST3.deposit', args: [0, et.eth(30)], },
{ from: ctx.wallet2, send: 'markets.enterMarket', args: [0, ctx.contracts.tokens.TST3.address], },


{ send: 'tokens.TST6.mint', args: [ctx.wallet2.address, et.eth(100)], },
{ from: ctx.wallet2, send: 'tokens.TST6.approve', args: [ctx.contracts.euler.address, et.MaxUint256,], },
{ from: ctx.wallet2, send: 'eTokens.eTST6.deposit', args: [0, et.eth(10)], },
{ from: ctx.wallet2, send: 'markets.enterMarket', args: [0, ctx.contracts.tokens.TST6.address], },

{ send: 'governance.setOverride', args: [
ctx.contracts.tokens.TST.address,
ctx.contracts.tokens.TST6.address,
{
enabled: true,
collateralFactor: Math.floor(0.6 * 4e9),
},
], },

{ from: ctx.wallet2, send: 'eTokens.eTST.mint', args: [0, et.eth(45)], },

{ send: 'governance.setOverride', args: [
ctx.contracts.tokens.TST.address,
ctx.contracts.tokens.TST2.address,
{
enabled: true,
collateralFactor: Math.floor(0.9 * 4e9),
},
], },


{ action: 'updateUniswapPrice', pair: 'TST/WETH', price: '7.4', },

{ send: 'governance.setOverride', args: [
ctx.contracts.tokens.TST.address,
ctx.contracts.tokens.TST.address,
{
enabled: true,
collateralFactor: Math.floor(0.8 * 4e9),
},
], },

{ call: 'exec.liquidity', args: [ctx.wallet2.address], onResult: r => {
et.equals(r.collateralValue / r.liabilityValue, 0.914, 0.001);
}, },
testDetailedLiability(ctx, 0.914),

{ callStatic: 'liquidation.checkLiquidation', args: [ctx.wallet.address, ctx.wallet2.address, ctx.contracts.tokens.TST.address, ctx.contracts.tokens.TST.address],
onResult: r => {
et.equals(r.healthScore, 0.914, 0.001);
ctx.stash.repay = r.repay;
ctx.stash.yield = r.yield;
},
},

// Successful liquidation

{ call: 'eTokens.eTST.reserveBalanceUnderlying', args: [], equals: [0, '0.000000000001'] },
{ call: 'dTokens.dTST.balanceOf', args: [ctx.wallet2.address], equals: et.eth('45'), },

{ send: 'liquidation.liquidate', args: [ctx.wallet2.address, ctx.contracts.tokens.TST.address, ctx.contracts.tokens.TST.address, () => ctx.stash.repay, 0], },

// liquidator:
{ call: 'dTokens.dTST.balanceOf', args: [ctx.wallet.address], equals: () => ctx.stash.repay, },
{ call: 'eTokens.eTST.balanceOfUnderlying', args: [ctx.wallet.address], equals: () => [ctx.stash.yield.add(et.eth(100)), '0.00001'], }, // 100 pre-existing depsit

// reserves:
{ call: 'eTokens.eTST.reserveBalanceUnderlying', onResult: (r) => ctx.stash.reserves = r, },

// violator:
{ call: 'dTokens.dTST.balanceOf', args: [ctx.wallet2.address], equals: () => [et.units(45).sub(ctx.stash.repay).add(ctx.stash.reserves), '0.000000000001'], },
{ call: 'eTokens.eTST.balanceOfUnderlying', args: [ctx.wallet2.address], equals: () => [et.units(45).sub(ctx.stash.yield), '0.000000000001'], },

{ call: 'exec.liquidity', args: [ctx.wallet2.address], onResult: async (r) => {
let targetHealth = (await ctx.contracts.liquidation.TARGET_HEALTH()) / 1e18;
et.equals(r.collateralValue / r.liabilityValue, targetHealth, 0.00000001);
}},
testDetailedLiability(ctx, 1.25),
],
})

.run();
51 changes: 51 additions & 0 deletions test/override.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,56 @@ et.testSet({



.test({
desc: "override self-collateral factor",
actions: ctx => [
// set collateral factor to 0

// { from: ctx.wallet2, send: 'dTokens.dTST3.borrow', args: [0, et.eth(1)], },
{ from: ctx.wallet2, send: 'eTokens.eTST2.mint', args: [0, et.eth(10)], },


{ call: 'exec.liquidity', args: [ctx.wallet2.address], onResult: r => {
et.equals(r.liabilityValue, 5, .001); // 10 * 0.5 (price) * 1 (BF)
et.equals(r.collateralValue, 9.5, .001); // 20 * 0.5 (price) * 0.95 (SCF)
et.equals(r.overrideCollateralValue, 9.5, .001); // whole collateral is in override
}, },

// Override is added for the self collateralisation

{ send: 'governance.setOverride', args: [
ctx.contracts.tokens.TST2.address,
ctx.contracts.tokens.TST2.address,
{
enabled: true,
collateralFactor: Math.floor(0.8 * 4e9),
},
], },

{ call: 'exec.liquidity', args: [ctx.wallet2.address], onResult: r => {
et.equals(r.liabilityValue, 5, .001); // 10 * 0.5 (price) * 1 (BF)
et.equals(r.collateralValue, 8, .001); // 20 * 0.5 (price) * 0.8 (CF)
et.equals(r.overrideCollateralValue, 8, .001); // whole collateral is in override
}, },

{ send: 'governance.setOverride', args: [
ctx.contracts.tokens.TST2.address,
ctx.contracts.tokens.TST2.address,
{
enabled: false,
collateralFactor:0,
},
], },

{ call: 'exec.liquidity', args: [ctx.wallet2.address], onResult: r => {
et.equals(r.liabilityValue, 5, .001); // 10 * 0.5 (price) * 1 (BF)
et.equals(r.collateralValue, 9.5, .001); // 20 * 0.5 (price) * 0.95 (SCF)
et.equals(r.overrideCollateralValue, 9.5, .001); // whole collateral is in override
}, },
],
})




.run();

0 comments on commit 8e29948

Please sign in to comment.