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

feat: gho repay with collateral #1871

Merged
merged 5 commits into from
Dec 5, 2023
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
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
Loading