Skip to content

Commit

Permalink
fix: gho borrow cap and facilitator level checks [skip cypress] (#1769)
Browse files Browse the repository at this point in the history
* fix: factor in borrow cap for amount of gho available

* fix: console logs, percentage math
  • Loading branch information
grothem authored Sep 1, 2023
1 parent 057f9a7 commit c42d747
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export const GhoBorrowModalContent = ({
const discountAvailable = ghoUserQualifiesForDiscount(amount);

// amount calculations
let maxAmountToBorrow = getMaxGhoMintAmount(user);
let maxAmountToBorrow = getMaxGhoMintAmount(user, poolReserve);
maxAmountToBorrow = Math.min(
Number(maxAmountToBorrow),
ghoReserveData.aaveFacilitatorRemainingCapacity
Expand Down
47 changes: 27 additions & 20 deletions src/hooks/app-data-provider/useAppDataProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import React, { useContext } from 'react';
import { EmodeCategory } from 'src/helpers/types';
import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
import { useRootStore } from 'src/store/root';
import { GHO_SUPPORTED_MARKETS, weightedAverageAPY } from 'src/utils/ghoUtilities';
import { GHO_SUPPORTED_MARKETS, GHO_SYMBOL, weightedAverageAPY } from 'src/utils/ghoUtilities';

import {
reserveSortFn,
Expand Down Expand Up @@ -121,23 +121,33 @@ export const AppDataProvider: React.FC = ({ children }) => {
currentTimestamp,
});

let ghoBorrowCap = '0';
let aaveFacilitatorRemainingCapacity = Math.max(
formattedGhoReserveData.aaveFacilitatorRemainingCapacity - 0.000001,
0
);
let user = userSummary;
// Factor discounted GHO interest into cumulative user fields
if (
GHO_SUPPORTED_MARKETS.includes(currentMarket) &&
formattedGhoUserData.userDiscountedGhoInterest > 0
) {
const userSummaryWithDiscount = formatUserSummaryWithDiscount({
userGhoDiscountedInterest: formattedGhoUserData.userDiscountedGhoInterest,
user,
marketReferenceCurrencyPriceUSD: Number(
formatUnits(baseCurrencyData.marketReferenceCurrencyPriceInUsd, USD_DECIMALS)
),
});
user = {
...user,
...userSummaryWithDiscount,
};
if (GHO_SUPPORTED_MARKETS.includes(currentMarket)) {
ghoBorrowCap = reserves.find((r) => r.symbol === GHO_SYMBOL)?.borrowCap || '0';

if (ghoBorrowCap && ghoBorrowCap !== '0') {
aaveFacilitatorRemainingCapacity = Number(ghoBorrowCap);
}

if (formattedGhoUserData.userDiscountedGhoInterest > 0) {
const userSummaryWithDiscount = formatUserSummaryWithDiscount({
userGhoDiscountedInterest: formattedGhoUserData.userDiscountedGhoInterest,
user,
marketReferenceCurrencyPriceUSD: Number(
formatUnits(baseCurrencyData.marketReferenceCurrencyPriceInUsd, USD_DECIMALS)
),
});
user = {
...user,
...userSummaryWithDiscount,
};
}
}

const proportions = user.userReservesData.reduce(
Expand Down Expand Up @@ -259,10 +269,7 @@ export const AppDataProvider: React.FC = ({ children }) => {
// ghoLoadingData for now is just propagated through to reduce changes to other components.
ghoReserveData: {
...formattedGhoReserveData,
aaveFacilitatorRemainingCapacity: Math.max(
formattedGhoReserveData.aaveFacilitatorRemainingCapacity - 0.000001,
0
),
aaveFacilitatorRemainingCapacity,
},
ghoUserData: formattedGhoUserData,
ghoLoadingData: !ghoReserveDataFetched,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const GhoBorrowAssetsListItem = ({
name,
underlyingAsset,
isFreezed,
reserve,
}: GhoBorrowAssetsItem) => {
const { openBorrow } = useModalContext();
const { user } = useAppDataContext();
Expand All @@ -38,8 +39,8 @@ export const GhoBorrowAssetsListItem = ({
const { ghoUserDataFetched } = useRootStore();
const theme = useTheme();
const downToXSM = useMediaQuery(theme.breakpoints.down('xsm'));
// Available borrows is min of user available borrows and remaining facilitator capacity
const maxAmountUserCanMint = Number(getMaxGhoMintAmount(user));

const maxAmountUserCanMint = Number(getMaxGhoMintAmount(user, reserve));
const availableBorrows = Math.min(
maxAmountUserCanMint,
ghoReserveData.aaveFacilitatorRemainingCapacity
Expand Down
2 changes: 2 additions & 0 deletions src/modules/dashboard/lists/BorrowAssetsList/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ReserveIncentiveResponse } from '@aave/math-utils/dist/esm/formatters/incentive/calculate-reserve-incentives';
import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider';

export type BorrowAssetsItem = {
id: string;
Expand Down Expand Up @@ -33,4 +34,5 @@ export type GhoBorrowAssetsItem = {
isFreezed?: boolean;
aIncentivesData?: ReserveIncentiveResponse[];
vIncentivesData?: ReserveIncentiveResponse[];
reserve: ComputedReserveData;
};
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const GhoBorrowedPositionsListItem = ({
const hasDiscount = ghoUserQualifiesForDiscount();

const { isActive, isFrozen, isPaused, borrowingEnabled } = reserve;
const maxAmountUserCanMint = Number(getMaxGhoMintAmount(user));
const maxAmountUserCanMint = Number(getMaxGhoMintAmount(user, reserve));
const availableBorrows = Math.min(
maxAmountUserCanMint,
ghoReserveData.aaveFacilitatorRemainingCapacity
Expand Down
16 changes: 12 additions & 4 deletions src/modules/reserve-overview/Gho/GhoBorrowInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ const GhoBorrowInfoDesktop = ({ reserve, ghoReserveData }: GhoBorrowInfoProps) =
return (
<Stack direction="row">
<CapsCircularStatus
value={ghoReserveData.aaveFacilitatorMintedPercent * 100}
value={
(ghoReserveData.aaveFacilitatorBucketLevel /
ghoReserveData.aaveFacilitatorRemainingCapacity) *
100
}
onClick={(open) => {
if (open) {
trackEvent(GENERAL.TOOL_TIP, {
Expand Down Expand Up @@ -86,7 +90,7 @@ const GhoBorrowInfoDesktop = ({ reserve, ghoReserveData }: GhoBorrowInfoProps) =
<Trans>of</Trans>
</Typography>
<FormattedNumber
value={ghoReserveData.aaveFacilitatorBucketMaxCapacity}
value={ghoReserveData.aaveFacilitatorRemainingCapacity}
variant="main16"
/>
</Box>
Expand Down Expand Up @@ -154,7 +158,7 @@ const GhoBorrowInfoMobile = ({ reserve, ghoReserveData }: GhoBorrowInfoProps) =>
>
<Trans>of</Trans>
</Typography>
<ReserveSubheader value={ghoReserveData.aaveFacilitatorBucketMaxCapacity.toString()} />
<ReserveSubheader value={ghoReserveData.aaveFacilitatorRemainingCapacity.toString()} />
</Box>
</PanelItem>
<Box mt={{ xs: 6, sm: 0 }}>
Expand All @@ -165,7 +169,11 @@ const GhoBorrowInfoMobile = ({ reserve, ghoReserveData }: GhoBorrowInfoProps) =>
</Stack>
<Box>
<CapsCircularStatus
value={ghoReserveData.aaveFacilitatorMintedPercent * 100}
value={
(ghoReserveData.aaveFacilitatorBucketLevel /
ghoReserveData.aaveFacilitatorRemainingCapacity) *
100
}
onClick={(open) => {
if (open) {
trackEvent(GENERAL.TOOL_TIP, {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/reserve-overview/ReserveActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const ReserveActions = ({ reserve }: ReserveActionsProps) => {
const isGho = displayGho({ symbol: reserve.symbol, currentMarket });

if (isGho) {
const maxMintAmount = getMaxGhoMintAmount(user);
const maxMintAmount = getMaxGhoMintAmount(user, reserve);
maxAmountToBorrow = BigNumber.min(
maxMintAmount,
valueToBigNumber(ghoReserveData.aaveFacilitatorRemainingCapacity)
Expand Down
26 changes: 22 additions & 4 deletions src/utils/getMaxAmountAvailableToBorrow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,33 @@ export function getMaxAmountAvailableToBorrow(
* Calculates the maximum amount of GHO a user can mint
* @param user
*/
export function getMaxGhoMintAmount(user: FormatUserSummaryAndIncentivesResponse) {
const maxUserAmountToMint = valueToBigNumber(user?.availableBorrowsMarketReferenceCurrency || 0);
export function getMaxGhoMintAmount(
user: FormatUserSummaryAndIncentivesResponse,
poolReserve: PoolReserveBorrowSubset
) {
const userAvailableBorrows = valueToBigNumber(user?.availableBorrowsMarketReferenceCurrency || 0);

const availableBorrowCap =
poolReserve.borrowCap === '0'
? valueToBigNumber(ethers.constants.MaxUint256.toString())
: valueToBigNumber(Number(poolReserve.borrowCap)).minus(
valueToBigNumber(poolReserve.totalDebt)
);

const maxAmountUserCanMint = BigNumber.min(userAvailableBorrows, availableBorrowCap);

const shouldAddMargin =
/**
* When a user has borrows we assume the debt is increasing faster then the supply.
* That's a simplification that might not be true, but doesn't matter in most cases.
*/
user.totalBorrowsMarketReferenceCurrency !== '0' ||
/**
* When borrow cap could be reached and debt accumulates the debt would be surpassed.
*/
(poolReserve.borrowCapUSD &&
poolReserve.totalDebt !== '0' &&
maxAmountUserCanMint.gte(availableBorrowCap)) ||
/**
* When the user would be able to borrow all the remaining ceiling we need to add a margin as existing debt.
*/
Expand All @@ -128,8 +146,8 @@ export function getMaxGhoMintAmount(user: FormatUserSummaryAndIncentivesResponse
.lt(user.availableBorrowsUSD));

const amountWithMargin = shouldAddMargin
? maxUserAmountToMint.multipliedBy('0.99')
: maxUserAmountToMint;
? maxAmountUserCanMint.multipliedBy('0.99')
: maxAmountUserCanMint;
return roundToTokenDecimals(amountWithMargin.toString(10), 18);
}

Expand Down

2 comments on commit c42d747

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit was deployed on ipfs

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit was deployed on ipfs

Please sign in to comment.