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

Commit 8e29948

Browse files
committed
allow override of self-collateral factor
1 parent ffed13f commit 8e29948

File tree

4 files changed

+147
-12
lines changed

4 files changed

+147
-12
lines changed

contracts/modules/Liquidation.sol

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,12 @@ contract Liquidation is BaseLogic {
133133

134134
// If override is active for the liquidated pair, assume the resulting liability will be fully covered by override collateral, and adjust inputs
135135
if (liqLocs.overrideCollateralValue > 0) {
136-
if (liqLocs.underlying == liqLocs.collateral) { // liquidating self-collateral
137-
collateralFactor = SELF_COLLATERAL_FACTOR;
136+
overrideConfig = overrideLookup[liqLocs.underlying][liqLocs.collateral];
137+
if (overrideConfig.enabled || liqLocs.underlying == liqLocs.collateral) { // the liquidated collateral has active override with liability
138+
collateralFactor = overrideConfig.enabled ? overrideConfig.collateralFactor : SELF_COLLATERAL_FACTOR;
138139
borrowFactor = CONFIG_FACTOR_SCALE;
139140
// adjust the whole liability for override BF = 1
140141
liqLocs.liabilityValue = liqLocs.currentOwed * liqLocs.underlyingPrice / 1e18;
141-
} else {
142-
overrideConfig = overrideLookup[liqLocs.underlying][liqLocs.collateral];
143-
144-
if (overrideConfig.enabled) { // the liquidated collateral has active override with liability
145-
collateralFactor = overrideConfig.collateralFactor;
146-
borrowFactor = CONFIG_FACTOR_SCALE;
147-
// adjust the whole liability for override BF = 1
148-
liqLocs.liabilityValue = liqLocs.currentOwed * liqLocs.underlyingPrice / 1e18;
149-
}
150142
}
151143
}
152144

contracts/modules/RiskManager.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,9 @@ contract RiskManager is IRiskManager, BaseLogic {
329329

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

334336
// self-collateralization is an implicit override
335337
status.overrideCollateralValue += assetCollateral;

test/liquidationWithOverrides.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,4 +1137,94 @@ et.testSet({
11371137
],
11381138
})
11391139

1140+
1141+
1142+
1143+
.test({
1144+
desc: "XV Liquidate self-collateral with override on self-collateral factor",
1145+
dev: 1,
1146+
actions: ctx => [
1147+
{ action: 'setAssetConfig', tok: 'TST3', config: { collateralFactor: .5}, },
1148+
{ send: 'tokens.TST3.mint', args: [ctx.wallet2.address, et.eth(200)], },
1149+
{ from: ctx.wallet2, send: 'tokens.TST3.approve', args: [ctx.contracts.euler.address, et.MaxUint256,], },
1150+
{ from: ctx.wallet2, send: 'eTokens.eTST3.deposit', args: [0, et.eth(30)], },
1151+
{ from: ctx.wallet2, send: 'markets.enterMarket', args: [0, ctx.contracts.tokens.TST3.address], },
1152+
1153+
1154+
{ send: 'tokens.TST6.mint', args: [ctx.wallet2.address, et.eth(100)], },
1155+
{ from: ctx.wallet2, send: 'tokens.TST6.approve', args: [ctx.contracts.euler.address, et.MaxUint256,], },
1156+
{ from: ctx.wallet2, send: 'eTokens.eTST6.deposit', args: [0, et.eth(10)], },
1157+
{ from: ctx.wallet2, send: 'markets.enterMarket', args: [0, ctx.contracts.tokens.TST6.address], },
1158+
1159+
{ send: 'governance.setOverride', args: [
1160+
ctx.contracts.tokens.TST.address,
1161+
ctx.contracts.tokens.TST6.address,
1162+
{
1163+
enabled: true,
1164+
collateralFactor: Math.floor(0.6 * 4e9),
1165+
},
1166+
], },
1167+
1168+
{ from: ctx.wallet2, send: 'eTokens.eTST.mint', args: [0, et.eth(45)], },
1169+
1170+
{ send: 'governance.setOverride', args: [
1171+
ctx.contracts.tokens.TST.address,
1172+
ctx.contracts.tokens.TST2.address,
1173+
{
1174+
enabled: true,
1175+
collateralFactor: Math.floor(0.9 * 4e9),
1176+
},
1177+
], },
1178+
1179+
1180+
{ action: 'updateUniswapPrice', pair: 'TST/WETH', price: '7.4', },
1181+
1182+
{ send: 'governance.setOverride', args: [
1183+
ctx.contracts.tokens.TST.address,
1184+
ctx.contracts.tokens.TST.address,
1185+
{
1186+
enabled: true,
1187+
collateralFactor: Math.floor(0.8 * 4e9),
1188+
},
1189+
], },
1190+
1191+
{ call: 'exec.liquidity', args: [ctx.wallet2.address], onResult: r => {
1192+
et.equals(r.collateralValue / r.liabilityValue, 0.914, 0.001);
1193+
}, },
1194+
testDetailedLiability(ctx, 0.914),
1195+
1196+
{ callStatic: 'liquidation.checkLiquidation', args: [ctx.wallet.address, ctx.wallet2.address, ctx.contracts.tokens.TST.address, ctx.contracts.tokens.TST.address],
1197+
onResult: r => {
1198+
et.equals(r.healthScore, 0.914, 0.001);
1199+
ctx.stash.repay = r.repay;
1200+
ctx.stash.yield = r.yield;
1201+
},
1202+
},
1203+
1204+
// Successful liquidation
1205+
1206+
{ call: 'eTokens.eTST.reserveBalanceUnderlying', args: [], equals: [0, '0.000000000001'] },
1207+
{ call: 'dTokens.dTST.balanceOf', args: [ctx.wallet2.address], equals: et.eth('45'), },
1208+
1209+
{ send: 'liquidation.liquidate', args: [ctx.wallet2.address, ctx.contracts.tokens.TST.address, ctx.contracts.tokens.TST.address, () => ctx.stash.repay, 0], },
1210+
1211+
// liquidator:
1212+
{ call: 'dTokens.dTST.balanceOf', args: [ctx.wallet.address], equals: () => ctx.stash.repay, },
1213+
{ call: 'eTokens.eTST.balanceOfUnderlying', args: [ctx.wallet.address], equals: () => [ctx.stash.yield.add(et.eth(100)), '0.00001'], }, // 100 pre-existing depsit
1214+
1215+
// reserves:
1216+
{ call: 'eTokens.eTST.reserveBalanceUnderlying', onResult: (r) => ctx.stash.reserves = r, },
1217+
1218+
// violator:
1219+
{ call: 'dTokens.dTST.balanceOf', args: [ctx.wallet2.address], equals: () => [et.units(45).sub(ctx.stash.repay).add(ctx.stash.reserves), '0.000000000001'], },
1220+
{ call: 'eTokens.eTST.balanceOfUnderlying', args: [ctx.wallet2.address], equals: () => [et.units(45).sub(ctx.stash.yield), '0.000000000001'], },
1221+
1222+
{ call: 'exec.liquidity', args: [ctx.wallet2.address], onResult: async (r) => {
1223+
let targetHealth = (await ctx.contracts.liquidation.TARGET_HEALTH()) / 1e18;
1224+
et.equals(r.collateralValue / r.liabilityValue, targetHealth, 0.00000001);
1225+
}},
1226+
testDetailedLiability(ctx, 1.25),
1227+
],
1228+
})
1229+
11401230
.run();

test/override.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,56 @@ et.testSet({
118118

119119

120120

121+
.test({
122+
desc: "override self-collateral factor",
123+
actions: ctx => [
124+
// set collateral factor to 0
125+
126+
// { from: ctx.wallet2, send: 'dTokens.dTST3.borrow', args: [0, et.eth(1)], },
127+
{ from: ctx.wallet2, send: 'eTokens.eTST2.mint', args: [0, et.eth(10)], },
128+
129+
130+
{ call: 'exec.liquidity', args: [ctx.wallet2.address], onResult: r => {
131+
et.equals(r.liabilityValue, 5, .001); // 10 * 0.5 (price) * 1 (BF)
132+
et.equals(r.collateralValue, 9.5, .001); // 20 * 0.5 (price) * 0.95 (SCF)
133+
et.equals(r.overrideCollateralValue, 9.5, .001); // whole collateral is in override
134+
}, },
135+
136+
// Override is added for the self collateralisation
137+
138+
{ send: 'governance.setOverride', args: [
139+
ctx.contracts.tokens.TST2.address,
140+
ctx.contracts.tokens.TST2.address,
141+
{
142+
enabled: true,
143+
collateralFactor: Math.floor(0.8 * 4e9),
144+
},
145+
], },
146+
147+
{ call: 'exec.liquidity', args: [ctx.wallet2.address], onResult: r => {
148+
et.equals(r.liabilityValue, 5, .001); // 10 * 0.5 (price) * 1 (BF)
149+
et.equals(r.collateralValue, 8, .001); // 20 * 0.5 (price) * 0.8 (CF)
150+
et.equals(r.overrideCollateralValue, 8, .001); // whole collateral is in override
151+
}, },
152+
153+
{ send: 'governance.setOverride', args: [
154+
ctx.contracts.tokens.TST2.address,
155+
ctx.contracts.tokens.TST2.address,
156+
{
157+
enabled: false,
158+
collateralFactor:0,
159+
},
160+
], },
161+
162+
{ call: 'exec.liquidity', args: [ctx.wallet2.address], onResult: r => {
163+
et.equals(r.liabilityValue, 5, .001); // 10 * 0.5 (price) * 1 (BF)
164+
et.equals(r.collateralValue, 9.5, .001); // 20 * 0.5 (price) * 0.95 (SCF)
165+
et.equals(r.overrideCollateralValue, 9.5, .001); // whole collateral is in override
166+
}, },
167+
],
168+
})
169+
170+
171+
121172

122173
.run();

0 commit comments

Comments
 (0)