Skip to content

Commit

Permalink
feat: gho repay with collateral (#1871)
Browse files Browse the repository at this point in the history
Co-authored-by: Nikita Boakrev <right2maresko@gmail.com>
  • Loading branch information
grothem and MareskoY authored Dec 5, 2023
1 parent 29136b0 commit ba82b0a
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 42 deletions.
4 changes: 2 additions & 2 deletions cypress/e2e/4-gho-ethereum/gho-basic.ethereum-v3.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ const testData = {
],
},
};

describe(`GHO base testing and e-mode`, () => {
//while borrow limit
describe.skip(`GHO base testing and e-mode`, () => {
const skipTestState = skipState(false);
configEnvWithTenderlyAEthereumV3Fork({
v3: true,
Expand Down
70 changes: 45 additions & 25 deletions cypress/e2e/4-gho-ethereum/gho-modal.gho-v3.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,28 @@ const testData = {
},
};

describe(`GHO MODAL APY TESTING`, () => {
describe(`Verify modal without discount APY = ${gho.apy.max}%`, () => {
let minApy: number;
let maxApy: number;
//skip while borrow limit
describe.skip(`GHO MODAL APY TESTING`, () => {
configEnvWithTenderlyAEthereumV3Fork({
v3: true,
tokens: tokenSet({ aDAI: 1000 }),
});
before(() => {
cy.doSwitchToDashboardBorrowView();
cy.get('[data-cy="apy-gho-from"]')
.invoke('text')
.then((text) => {
minApy = parseFloat(text.replace('%', ''));
});
cy.get('[data-cy="apy-gho-till"]')
.invoke('text')
.then((text) => {
maxApy = parseFloat(text.replace('%', ''));
});
});
describe(`Verify modal without discount APY = maxApy`, () => {
configEnvWithTenderlyAEthereumV3Fork({
v3: true,
tokens: tokenSet({ aDAI: 1000 }),
Expand All @@ -26,25 +46,25 @@ describe(`GHO MODAL APY TESTING`, () => {
cy.doSwitchToDashboardBorrowView();
DashboardHelpers.openBorrowModal(testData.borrow.asset.shortName);
});
it(`Verify modal without discount APY=${gho.apy.max}%, no amount`, () => {
it(`Verify modal without discount APY=maxApy, no amount`, () => {
ModalHelpers.getApy().then(($val) => {
expect($val).to.be.eql(gho.apy.max);
expect($val).to.be.eql(maxApy);
});
});
it(`Verify modal without discount APY=${gho.apy.max}%, some amount`, () => {
it(`Verify modal without discount APY=maxApy, some amount`, () => {
ModalHelpers.setAmount(100);
ModalHelpers.getApy().then(($val) => {
expect($val).to.be.eql(gho.apy.max);
expect($val).to.be.eql(maxApy);
});
});
it(`Verify modal without discount APY=${gho.apy.max}%, max amount`, () => {
it(`Verify modal without discount APY=maxApy, max amount`, () => {
ModalHelpers.setAmount(1000, true);
ModalHelpers.getApy().then(($val) => {
expect($val).to.be.eql(gho.apy.max);
expect($val).to.be.eql(maxApy);
});
});
});
describe(`Verify modal with max discount APY = ${gho.apy.min}%`, () => {
describe(`Verify modal with max discount APY = minApy`, () => {
configEnvWithTenderlyAEthereumV3Fork({
v3: true,
tokens: tokenSet({ stkAave: 50, aDAI: 1000 }),
Expand All @@ -53,20 +73,20 @@ describe(`GHO MODAL APY TESTING`, () => {
cy.doSwitchToDashboardBorrowView();
DashboardHelpers.openBorrowModal(testData.borrow.asset.shortName);
});
it(`Verify modal with max discount APY=${gho.apy.min}%, some amount`, () => {
it(`Verify modal with max discount APY=minApy, some amount`, () => {
ModalHelpers.setAmount(100);
ModalHelpers.getApy().then(($val) => {
expect($val).to.be.eql(gho.apy.min);
expect($val).to.be.eql(minApy);
});
});
it(`Verify modal with max discount APY=${gho.apy.min}%, max amount`, () => {
it(`Verify modal with max discount APY=minApy, max amount`, () => {
ModalHelpers.setAmount(1000, true);
ModalHelpers.getApy().then(($val) => {
expect($val).to.be.eql(gho.apy.min);
expect($val).to.be.eql(minApy);
});
});
});
describe.skip(`Verify modal in range: min APY ${gho.apy.min}% - max APY ${gho.apy.max}%`, () => {
describe.skip(`Verify modal in range: min APY minApy - max APY maxApy`, () => {
configEnvWithTenderlyAEthereumV3Fork({
v3: true,
tokens: tokenSet({ stkAave: 1.01, aDAI: 12000 }),
Expand All @@ -76,21 +96,21 @@ describe(`GHO MODAL APY TESTING`, () => {
DashboardHelpers.openBorrowModal(testData.borrow.asset.shortName);
});

it(`Verify modal with max discount APY=${gho.apy.min}%, small amount`, () => {
it(`Verify modal with max discount APY=minApy, small amount`, () => {
ModalHelpers.setAmount(100);
ModalHelpers.getApy().then(($val) => {
expect($val).to.be.eql(gho.apy.min);
expect($val).to.be.eql(minApy);
});
});
it(`Verify modal with some discount ${gho.apy.min}<%APY<${gho.apy.max}%, medium amount`, () => {
it(`Verify modal with some discount minApy<%APY<maxApy, medium amount`, () => {
ModalHelpers.setAmount(1000);
ModalHelpers.getApy().then(($val) => {
expect($val).to.be.greaterThan(gho.apy.min);
expect($val).to.be.lessThan(gho.apy.max);
expect($val).to.be.greaterThan(minApy);
expect($val).to.be.lessThan(maxApy);
});
});
});
describe(`Verify modal in range: min APY ${gho.apy.min}% - max APY < ${gho.apy.max}%`, () => {
describe(`Verify modal in range: min APY minApy - max APY < maxApy`, () => {
let maxAPY: number;
configEnvWithTenderlyAEthereumV3Fork({
v3: true,
Expand All @@ -103,20 +123,20 @@ describe(`GHO MODAL APY TESTING`, () => {
maxAPY = $val;
});
});
it(`Verify modal with max discount APY=${gho.apy.min}%, small amount`, () => {
it(`Verify modal with max discount APY=minApy, small amount`, () => {
ModalHelpers.setAmount(1);
ModalHelpers.getApy().then(($val) => {
expect($val).to.be.eql(gho.apy.min);
expect($val).to.be.eql(minApy);
});
});
it(`Verify modal with some discount ${gho.apy.min} < %APY < ${gho.apy.max}%, medium amount`, () => {
it(`Verify modal with some discount minApy < %APY < maxApy, medium amount`, () => {
ModalHelpers.setAmount(200);
ModalHelpers.getApy().then(($val) => {
expect($val).to.be.greaterThan(gho.apy.min);
expect($val).to.be.greaterThan(minApy);
expect($val).to.be.lessThan(maxAPY);
});
});
it(`Verify modal without discount APY=${gho.apy.max}%, max amount`, () => {
it(`Verify modal without discount APY=maxApy, max amount`, () => {
ModalHelpers.setAmount(1000, true);
ModalHelpers.getApy().then(($val) => {
expect($val).to.be.eql(maxAPY);
Expand Down
6 changes: 1 addition & 5 deletions src/components/transactions/Repay/RepayModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import React, { useState } from 'react';
import { useAppDataContext } from 'src/hooks/app-data-provider/useAppDataProvider';
import { ModalContextType, ModalType, useModalContext } from 'src/hooks/useModal';
import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
import { getGhoReserve } from 'src/utils/ghoUtilities';
import { isFeatureEnabled } from 'src/utils/marketsAndNetworksConfig';

import { BasicModal } from '../../primitives/BasicModal';
Expand All @@ -24,16 +23,13 @@ export const RepayModal = () => {
const [repayType, setRepayType] = useState(RepayType.BALANCE);

const stETHAddress = reserves.find((reserve) => reserve.symbol === 'stETH')?.underlyingAsset;
const ghoReserve = getGhoReserve(reserves);

// repay with collateral is only possible:
// 1. on chains with paraswap deployed
// 2. if asset is not GHO (disabled initially until there is enough liquidity)
// 3. when you have a different supplied(not necessarily collateral) asset then the one your debt is in
// 2. when you have a different supplied(not necessarily collateral) asset then the one your debt is in
// For repaying your debt with the same assets aToken you can use repayWithAToken on aave protocol v3
const collateralRepayPossible =
isFeatureEnabled.collateralRepay(currentMarketData) &&
args.underlyingAsset !== ghoReserve?.underlyingAsset &&
userReserves.some(
(userReserve) =>
userReserve.scaledATokenBalance !== '0' &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,13 @@ export const BorrowAssetsList = () => {
const borrowReserves =
user?.totalCollateralMarketReferenceCurrency === '0' || +collateralUsagePercent >= 0.98
? tokensToBorrow
: tokensToBorrow.filter(
({ availableBorrowsInUSD, totalLiquidityUSD, symbol }) =>
availableBorrowsInUSD !== '0.00' &&
(totalLiquidityUSD !== '0' ||
displayGho({
symbol,
currentMarket,
}))
);
: tokensToBorrow.filter(({ availableBorrowsInUSD, totalLiquidityUSD, symbol }) => {
if (displayGho({ symbol, currentMarket })) {
return true;
}

return availableBorrowsInUSD !== '0.00' && totalLiquidityUSD !== '0';
});

const { value: ghoReserve, filtered: filteredReserves } = findAndFilterGhoReserve(borrowReserves);
const sortedReserves = handleSortDashboardReserves(
Expand Down
5 changes: 4 additions & 1 deletion src/utils/getMaxAmountAvailableToBorrow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@ export function getMaxGhoMintAmount(
valueToBigNumber(poolReserve.totalDebt)
);

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

const shouldAddMargin =
/**
Expand Down

2 comments on commit ba82b0a

@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.