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

Take borrow cap into account in validateBorrow and getBorrowMaxValue #5

Merged
merged 4 commits into from
Apr 25, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ describe(getBorrowMaxValue.name, () => {
getBorrowMaxValue({
asset: {
availableLiquidity: NormalizedUnitNumber(Infinity),
totalDebt: NormalizedUnitNumber(0),
},
user: {
maxBorrowBasedOnCollateral: NormalizedUnitNumber(0),
Expand All @@ -21,13 +22,29 @@ describe(getBorrowMaxValue.name, () => {
getBorrowMaxValue({
asset: {
availableLiquidity: NormalizedUnitNumber(Infinity),
totalDebt: NormalizedUnitNumber(0),
},
user: {
maxBorrowBasedOnCollateral: NormalizedUnitNumber(100),
},
}),
).toEqual(NormalizedUnitNumber(100))
})

it('returns borrow cap based borrow limit', () => {
expect(
getBorrowMaxValue({
asset: {
availableLiquidity: NormalizedUnitNumber(Infinity),
totalDebt: NormalizedUnitNumber(50),
borrowCap: NormalizedUnitNumber(100),
},
user: {
maxBorrowBasedOnCollateral: NormalizedUnitNumber(Infinity),
},
}),
).toEqual(NormalizedUnitNumber(50))
})
})

describe('limited liquidity', () => {
Expand All @@ -36,6 +53,7 @@ describe(getBorrowMaxValue.name, () => {
getBorrowMaxValue({
asset: {
availableLiquidity: NormalizedUnitNumber(10),
totalDebt: NormalizedUnitNumber(0),
},
user: {
maxBorrowBasedOnCollateral: NormalizedUnitNumber(0),
Expand All @@ -44,11 +62,12 @@ describe(getBorrowMaxValue.name, () => {
).toEqual(NormalizedUnitNumber(0))
})

it('returns available liquidity value when smaller than borrow limit', () => {
it('returns available liquidity based value when smaller than borrow limit', () => {
expect(
getBorrowMaxValue({
asset: {
availableLiquidity: NormalizedUnitNumber(10),
totalDebt: NormalizedUnitNumber(5),
},
user: {
maxBorrowBasedOnCollateral: NormalizedUnitNumber(100),
Expand All @@ -70,6 +89,7 @@ describe(getBorrowMaxValue.name, () => {
},
asset: {
availableLiquidity: NormalizedUnitNumber(Infinity),
totalDebt: NormalizedUnitNumber(0),
},
}),
).toEqual(NormalizedUnitNumber(0))
Expand All @@ -86,6 +106,7 @@ describe(getBorrowMaxValue.name, () => {
},
asset: {
availableLiquidity: NormalizedUnitNumber(Infinity),
totalDebt: NormalizedUnitNumber(0),
},
}),
).toEqual(NormalizedUnitNumber(100))
Expand All @@ -103,6 +124,7 @@ describe(getBorrowMaxValue.name, () => {

asset: {
availableLiquidity: NormalizedUnitNumber(Infinity),
totalDebt: NormalizedUnitNumber(0),
},
}),
).toEqual(NormalizedUnitNumber(50))
Expand All @@ -116,6 +138,7 @@ describe(getBorrowMaxValue.name, () => {
},
asset: {
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { NormalizedUnitNumber } from '../types/NumericValues'
interface GetBorrowMaxValueParams {
asset: {
availableLiquidity: NormalizedUnitNumber
totalDebt: NormalizedUnitNumber
borrowCap?: NormalizedUnitNumber
}
user: {
maxBorrowBasedOnCollateral: NormalizedUnitNumber
Expand All @@ -26,13 +28,17 @@ export function getBorrowMaxValue({ asset, user, validationIssue }: GetBorrowMax
) {
return NormalizedUnitNumber(0)
}

const ceilings = [asset.availableLiquidity, user.maxBorrowBasedOnCollateral]

if (asset.borrowCap) {
ceilings.push(NormalizedUnitNumber(asset.borrowCap.minus(asset.totalDebt)))
}

const { inIsolationMode, isolationModeCollateralTotalDebt, isolationModeCollateralDebtCeiling } = user

if (inIsolationMode && isolationModeCollateralTotalDebt && isolationModeCollateralDebtCeiling) {
ceilings.push(NormalizedUnitNumber(isolationModeCollateralDebtCeiling.minus(isolationModeCollateralTotalDebt)))
}

return NormalizedUnitNumber(BigNumber.min(...ceilings))
return NormalizedUnitNumber(BigNumber.max(BigNumber.min(...ceilings), 0))
}
64 changes: 64 additions & 0 deletions packages/app/src/domain/market-validators/validateBorrow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: false,
eModeCategory: 0,
Expand All @@ -37,6 +38,7 @@ describe(validateBorrow.name, () => {
status: 'frozen',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: false,
eModeCategory: 0,
Expand All @@ -61,6 +63,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: false,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: false,
eModeCategory: 0,
Expand All @@ -85,6 +88,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: false,
eModeCategory: 0,
Expand All @@ -100,6 +104,58 @@ describe(validateBorrow.name, () => {
).toStrictEqual('exceeds-liquidity')
})

it('validates borrow cap', () => {
expect(
validateBorrow({
value: NormalizedUnitNumber(101),
asset: {
address: testAddresses.token,
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(102),
borrowCap: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: false,
eModeCategory: 0,
},
user: {
maxBorrowBasedOnCollateral: NormalizedUnitNumber(200),
totalBorrowedUSD: NormalizedUnitNumber(0),
isInSiloMode: false,
inIsolationMode: false,
eModeCategory: 0,
},
}),
).toStrictEqual('borrow-cap-reached')
})

it('takes into account total debt when validating borrow cap', () => {
expect(
validateBorrow({
value: NormalizedUnitNumber(96),
asset: {
address: testAddresses.token,
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(102),
borrowCap: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(5),
isSiloed: false,
borrowableInIsolation: false,
eModeCategory: 0,
},
user: {
maxBorrowBasedOnCollateral: NormalizedUnitNumber(200),
totalBorrowedUSD: NormalizedUnitNumber(0),
isInSiloMode: false,
inIsolationMode: false,
eModeCategory: 0,
},
}),
).toStrictEqual('borrow-cap-reached')
})

it('validates collateralization', () => {
expect(
validateBorrow({
Expand All @@ -109,6 +165,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(101),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: false,
eModeCategory: 0,
Expand All @@ -133,6 +190,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: true,
borrowableInIsolation: false,
eModeCategory: 0,
Expand All @@ -157,6 +215,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: true,
borrowableInIsolation: false,
eModeCategory: 0,
Expand All @@ -183,6 +242,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: false,
eModeCategory: 0,
Expand Down Expand Up @@ -210,6 +270,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: true,
eModeCategory: 0,
Expand All @@ -236,6 +297,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: true,
eModeCategory: 0,
Expand Down Expand Up @@ -264,6 +326,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: true,
eModeCategory: 1,
Expand All @@ -290,6 +353,7 @@ describe(validateBorrow.name, () => {
status: 'active',
borrowingEnabled: true,
availableLiquidity: NormalizedUnitNumber(100),
totalDebt: NormalizedUnitNumber(0),
isSiloed: false,
borrowableInIsolation: true,
eModeCategory: 2,
Expand Down
12 changes: 12 additions & 0 deletions packages/app/src/domain/market-validators/validateBorrow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export interface ValidateBorrowParams {
status: ReserveStatus
borrowingEnabled: boolean
availableLiquidity: NormalizedUnitNumber
totalDebt: NormalizedUnitNumber
borrowCap?: NormalizedUnitNumber
isSiloed: boolean
borrowableInIsolation: boolean
eModeCategory: number
Expand All @@ -36,6 +38,7 @@ export type BorrowValidationIssue =
| 'reserve-not-active'
| 'reserve-borrowing-disabled'
| 'exceeds-liquidity'
| 'borrow-cap-reached'
| 'insufficient-collateral'
| 'siloed-mode-cannot-enable'
| 'siloed-mode-enabled'
Expand All @@ -50,6 +53,8 @@ export function validateBorrow({
status,
borrowingEnabled,
availableLiquidity,
totalDebt,
borrowCap,
isSiloed,
borrowableInIsolation,
eModeCategory: assetEModeCategory,
Expand Down Expand Up @@ -83,6 +88,10 @@ export function validateBorrow({
return 'exceeds-liquidity'
}

if (borrowCap?.lt(totalDebt.plus(value))) {
return 'borrow-cap-reached'
}

if (value.gt(maxBorrowBasedOnCollateral)) {
return 'insufficient-collateral'
}
Expand Down Expand Up @@ -122,6 +131,7 @@ export function validateBorrow({
export const borrowValidationIssueToMessage: Record<BorrowValidationIssue, string> = {
'value-not-positive': 'Borrow value should be positive',
'exceeds-liquidity': 'Borrow value exceeds liquidity',
'borrow-cap-reached': 'Borrow cap reached',
'insufficient-collateral': 'Not enough collateral to borrow this amount',
'siloed-mode-enabled': 'Siloed borrowing enabled. Borrowing other assets is not allowed.',
'siloed-mode-cannot-enable':
Expand All @@ -148,6 +158,8 @@ export function getValidateBorrowArgs(
status: reserve.status,
borrowingEnabled: reserve.borrowEligibilityStatus !== 'no',
availableLiquidity: reserve.availableLiquidity,
totalDebt: reserve.totalDebt,
borrowCap: reserve.borrowCap,
isSiloed: reserve.isSiloedBorrowing,
borrowableInIsolation: reserve.isBorrowableInIsolation,
eModeCategory: reserve.eModeCategory?.id ?? 0,
Expand Down
Loading