Skip to content

Commit

Permalink
✨ weird APYs: adds check and reports on fixed pools (#606)
Browse files Browse the repository at this point in the history
  • Loading branch information
itofarina authored Oct 11, 2022
1 parent c9bf887 commit c1305fd
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 20 deletions.
10 changes: 5 additions & 5 deletions components/MarketsList/Item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ function Item({ market, type, fixedMarketData }: Props) {
}

try {
const fixedMarket = fixedMarketData?.find((element) => element.market == market.market);
const fixedMarket = fixedMarketData?.find((element) => element.market === market.market);

if (type == 'borrow') {
const pool = fixedMarket?.borrows.find((pool) => pool.maturity.toString() == date?.value);
if (type === 'borrow') {
const pool = fixedMarket?.borrows.find((pool) => pool.maturity.toString() === date?.value);
if (!fixedMarket || !pool) return;

const initialAssets = fixedMarket.assets;
Expand All @@ -114,8 +114,8 @@ function Item({ market, type, fixedMarketData }: Props) {
} else {
setRate(`${borrowFixedAPY.toFixed(2)}%`);
}
} else if (type == 'deposit') {
const pool = fixedMarket?.deposits.find((pool) => pool.maturity.toString() == date?.value);
} else if (type === 'deposit') {
const pool = fixedMarket?.deposits.find((pool) => pool.maturity.toString() === date?.value);
if (!fixedMarket || !pool) return;

const initialAssets = fixedMarket.assets;
Expand Down
62 changes: 58 additions & 4 deletions components/MarketsList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useContext, useEffect, useState } from 'react';
import { parseFixed } from '@ethersproject/bignumber';
import { formatFixed, parseFixed } from '@ethersproject/bignumber';
import dynamic from 'next/dynamic';
import { captureMessage } from '@sentry/nextjs';

const Item = dynamic(() => import('components/MarketsList/Item'));
import Tooltip from 'components/Tooltip';
Expand All @@ -22,6 +23,7 @@ import keys from './translations.json';
import formatMarkets from 'utils/formatMarkets';

import numbers from 'config/numbers.json';
const { usdAmount, maxAPYValue, minAPYValue } = numbers;

function MarketsList() {
const previewerData = useContext(PreviewerContext);
Expand Down Expand Up @@ -53,6 +55,57 @@ function MarketsList() {
}
}

const checkWeirdAPY = (marketsData: any) => {
if (!markets.length) return; // not ready to do the check yet

const findings = [];
// iterate through every market asset
for (let index = 0; index < marketsData.length; index++) {
const marketData = marketsData[index];
const {
borrows: borrowPools,
deposits: depositPools,
assets: initialAssets,
market: marketAddress
} = marketData;
const { name: marketName } = markets.find(
({ market }) => market.toLowerCase() === marketAddress.toLowerCase()
)!;
// iterate through every borrow & deposit pools - parallel arrays
for (let j = 0; j < borrowPools.length; j++) {
const { assets: borrowFinalAssets, maturity: timestampEnd } = borrowPools[j];
const { assets: depositFinalAssets } = depositPools[j];

const timestampNow = new Date().getTime() / 1_000;

// 31_536_000 = seconds in 1 year
const timePerYear = 31_536_000 / (timestampEnd - timestampNow);

const borrowRate = borrowFinalAssets.mul(parseFixed('1', 18)).div(initialAssets);
const borrowFixedAPY = (Number(formatFixed(borrowRate, 18)) ** timePerYear - 1) * 100;

const depositRate = depositFinalAssets.mul(parseFixed('1', 18)).div(initialAssets);
const depositFixedAPY = (Number(formatFixed(depositRate, 18)) ** timePerYear - 1) * 100;

if (depositFixedAPY > borrowFixedAPY) {
findings.push(`Market: ${marketName} -> deposit APY > borrow APY.`);
}

if (depositFixedAPY > maxAPYValue || borrowFixedAPY > maxAPYValue) {
findings.push(`Market: ${marketName} -> APY > ${maxAPYValue}%`);
}

if (depositFixedAPY < minAPYValue || borrowFixedAPY < minAPYValue) {
findings.push(`Market: ${marketName} -> APY < ${minAPYValue}%`);
}
}
}

if (findings.length) {
captureMessage(`Weird Fixed APYs | ${findings.join(' | ')}`);
}
};

async function getPreviewFixed() {
try {
const previewerContract = getInstance(
Expand All @@ -61,11 +114,12 @@ function MarketsList() {
'previewer'
);

const data = await previewerContract?.previewFixed(
parseFixed(numbers.usdAmount.toString(), 18)
const marketData = await previewerContract?.previewFixed(
parseFixed(usdAmount.toString(), 18)
);

setFixedMarketData(data);
checkWeirdAPY(marketData);
setFixedMarketData(marketData);
} catch (e) {
console.log(e);
}
Expand Down
20 changes: 10 additions & 10 deletions components/SmartPoolList/Item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function Item({ market, type }: Props) {
async function getFixedLenderContract() {
if (!market) return;

const filteredFixedLender = fixedLenderData.find((fl) => fl.address == market.market);
const filteredFixedLender = fixedLenderData.find((fl) => fl.address === market.market);

setEMarketAddress(filteredFixedLender?.address);
}
Expand Down Expand Up @@ -90,20 +90,20 @@ function Item({ market, type }: Props) {

if (!eMarketAddress) return;

if (type == 'deposit') {
if (type === 'deposit') {
const maxFuturePools = accountData[market?.symbol.toUpperCase()].maxFuturePools;
const data = await queryRate(subgraphUrl, eMarketAddress, 'deposit', { maxFuturePools });

interestRate = data[0].rate.toFixed(2);
}

if (type == 'borrow') {
if (type === 'borrow') {
const data = await queryRate(subgraphUrl, eMarketAddress, 'borrow');

interestRate = data[0].rate.toFixed(2);
}

if (interestRate && rate && `${interestRate}%` == rate) {
if (interestRate && rate && `${interestRate}%` === rate) {
return;
}

Expand Down Expand Up @@ -163,10 +163,10 @@ function Item({ market, type }: Props) {
return (
<div
className={`${style.container} ${
type == 'borrow' ? style.secondaryContainer : style.primaryContainer
type === 'borrow' ? style.secondaryContainer : style.primaryContainer
}`}
>
<Link href={`/assets/${market?.symbol == 'WETH' ? 'eth' : market?.symbol.toLowerCase()}`}>
<Link href={`/assets/${market?.symbol === 'WETH' ? 'eth' : market?.symbol.toLowerCase()}`}>
<div className={style.symbol}>
{(market && (
<Image
Expand All @@ -185,20 +185,20 @@ function Item({ market, type }: Props) {
{(market &&
poolData &&
`$${formatNumber(
(type == 'borrow' ? poolData?.borrowed! : poolData?.supplied!) * poolData?.rate!,
(type === 'borrow' ? poolData?.borrowed! : poolData?.supplied!) * poolData?.rate!,
'USD'
)}`) || <Skeleton />}
</p>
<p className={style.value}>{(rate && rate) || <Skeleton />}</p>
<div className={style.buttonContainer}>
{(market && (
<Button
text={type == 'borrow' ? translations[lang].borrow : translations[lang].deposit}
text={type === 'borrow' ? translations[lang].borrow : translations[lang].deposit}
onClick={(e) => {
e.stopPropagation();
handleClick(type == 'borrow' ? 'borrow' : 'deposit');
handleClick(type === 'borrow' ? 'borrow' : 'deposit');
}}
className={type == 'borrow' ? 'secondary' : 'primary'}
className={type === 'borrow' ? 'secondary' : 'primary'}
/>
)) || <Skeleton height={40} />}
</div>
Expand Down
2 changes: 1 addition & 1 deletion config/numbers.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"gasLimitMultiplier": 1.25,
"debounceTime": 500,
"minAPYValue": 0,
"maxAPYValue": 100
"maxAPYValue": 30
}

0 comments on commit c1305fd

Please sign in to comment.