aave-protocol-v2/test/helpers/utils/calculations.ts

1397 lines
44 KiB
TypeScript
Raw Normal View History

2020-06-30 12:09:28 +00:00
import BigNumber from 'bignumber.js';
import {
ONE_YEAR,
RAY,
MAX_UINT_AMOUNT,
OPTIMAL_UTILIZATION_RATE,
EXCESS_UTILIZATION_RATE,
2020-06-30 12:09:28 +00:00
} from '../../../helpers/constants';
2020-09-21 13:27:53 +00:00
import {IReserveParams, iAavePoolAssets, RateMode, tEthereumAddress} from '../../../helpers/types';
2020-06-30 12:09:28 +00:00
import './math';
2020-09-09 19:26:52 +00:00
import {ReserveData, UserReserveData} from './interfaces';
export const strToBN = (amount: string): BigNumber => new BigNumber(amount);
interface Configuration {
reservesParams: iAavePoolAssets<IReserveParams>;
}
export const configuration: Configuration = <Configuration>{};
export const calcExpectedUserDataAfterDeposit = (
amountDeposited: string,
reserveDataBeforeAction: ReserveData,
reserveDataAfterAction: ReserveData,
userDataBeforeAction: UserReserveData,
txTimestamp: BigNumber,
currentTimestamp: BigNumber,
txCost: BigNumber
): UserReserveData => {
const expectedUserData = <UserReserveData>{};
2020-09-14 18:04:49 +00:00
expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
2020-06-30 12:09:28 +00:00
txTimestamp
);
2020-09-14 18:04:49 +00:00
expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance(
reserveDataBeforeAction,
2020-06-30 12:09:28 +00:00
userDataBeforeAction,
txTimestamp
);
2020-09-08 11:45:24 +00:00
expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt;
2020-09-14 17:25:45 +00:00
expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt;
2020-06-30 12:09:28 +00:00
expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex;
expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate;
2020-07-03 21:20:02 +00:00
expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated;
expectedUserData.liquidityRate = reserveDataAfterAction.liquidityRate;
expectedUserData.scaledATokenBalance = calcExpectedScaledATokenBalance(
userDataBeforeAction,
reserveDataAfterAction.liquidityIndex,
new BigNumber(amountDeposited),
new BigNumber(0)
);
expectedUserData.currentATokenBalance = calcExpectedATokenBalance(
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
).plus(amountDeposited);
if (userDataBeforeAction.currentATokenBalance.eq(0)) {
expectedUserData.usageAsCollateralEnabled = true;
} else {
expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled;
}
2020-06-30 12:09:28 +00:00
expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex;
2020-09-04 08:27:32 +00:00
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(amountDeposited);
expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
2020-06-30 12:09:28 +00:00
txTimestamp
);
expectedUserData.currentVariableDebt = expectedUserData.principalStableDebt = calcExpectedVariableDebtTokenBalance(
2020-06-30 12:09:28 +00:00
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
);
return expectedUserData;
};
export const calcExpectedUserDataAfterWithdraw = (
amountWithdrawn: string,
reserveDataBeforeAction: ReserveData,
reserveDataAfterAction: ReserveData,
userDataBeforeAction: UserReserveData,
txTimestamp: BigNumber,
currentTimestamp: BigNumber,
txCost: BigNumber
): UserReserveData => {
const expectedUserData = <UserReserveData>{};
const aTokenBalance = calcExpectedATokenBalance(
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
);
if (amountWithdrawn == MAX_UINT_AMOUNT) {
amountWithdrawn = aTokenBalance.toFixed(0);
}
2020-06-30 12:09:28 +00:00
expectedUserData.scaledATokenBalance = calcExpectedScaledATokenBalance(
userDataBeforeAction,
reserveDataAfterAction.liquidityIndex,
new BigNumber(0),
new BigNumber(amountWithdrawn)
);
2020-06-30 12:09:28 +00:00
expectedUserData.currentATokenBalance = aTokenBalance.minus(amountWithdrawn);
2020-09-08 14:14:32 +00:00
expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt;
2020-09-14 17:25:45 +00:00
expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt;
2020-09-08 14:14:32 +00:00
expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
txTimestamp
);
2020-09-08 14:14:32 +00:00
expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance(
2020-06-30 12:09:28 +00:00
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
);
2020-06-30 12:09:28 +00:00
expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex;
expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate;
2020-07-03 21:20:02 +00:00
expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated;
expectedUserData.liquidityRate = reserveDataAfterAction.liquidityRate;
if (userDataBeforeAction.currentATokenBalance.eq(0)) {
expectedUserData.usageAsCollateralEnabled = true;
} else {
//if the user is withdrawing everything, usageAsCollateralEnabled must be false
if (expectedUserData.currentATokenBalance.eq(0)) {
expectedUserData.usageAsCollateralEnabled = false;
} else {
2020-06-30 12:09:28 +00:00
expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled;
}
}
2020-09-04 08:27:32 +00:00
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountWithdrawn);
return expectedUserData;
};
export const calcExpectedReserveDataAfterDeposit = (
amountDeposited: string,
reserveDataBeforeAction: ReserveData,
txTimestamp: BigNumber
): ReserveData => {
const expectedReserveData: ReserveData = <ReserveData>{};
expectedReserveData.address = reserveDataBeforeAction.address;
2020-06-30 12:09:28 +00:00
expectedReserveData.totalLiquidity = new BigNumber(reserveDataBeforeAction.totalLiquidity).plus(
amountDeposited
);
expectedReserveData.availableLiquidity = new BigNumber(
reserveDataBeforeAction.availableLiquidity
).plus(amountDeposited);
2020-06-30 12:09:28 +00:00
expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate;
2020-09-14 17:25:45 +00:00
expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex(
reserveDataBeforeAction,
txTimestamp
);
expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex(
reserveDataBeforeAction,
txTimestamp
);
expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt(
2020-09-18 15:56:33 +00:00
reserveDataBeforeAction.principalStableDebt,
reserveDataBeforeAction.averageStableBorrowRate,
2020-09-21 13:27:53 +00:00
reserveDataBeforeAction.totalStableDebtLastUpdated,
2020-09-14 17:25:45 +00:00
txTimestamp
);
expectedReserveData.totalVariableDebt = calcExpectedTotalVariableDebt(
reserveDataBeforeAction,
expectedReserveData.variableBorrowIndex
);
expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt;
expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt;
expectedReserveData.utilizationRate = calcExpectedUtilizationRate(
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.totalLiquidity
);
const rates = calcExpectedInterestRates(
reserveDataBeforeAction.symbol,
reserveDataBeforeAction.marketStableRate,
expectedReserveData.utilizationRate,
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.averageStableBorrowRate
);
expectedReserveData.liquidityRate = rates[0];
expectedReserveData.stableBorrowRate = rates[1];
expectedReserveData.variableBorrowRate = rates[2];
return expectedReserveData;
};
export const calcExpectedReserveDataAfterWithdraw = (
amountWithdrawn: string,
reserveDataBeforeAction: ReserveData,
userDataBeforeAction: UserReserveData,
txTimestamp: BigNumber
): ReserveData => {
const expectedReserveData: ReserveData = <ReserveData>{};
expectedReserveData.address = reserveDataBeforeAction.address;
if (amountWithdrawn == MAX_UINT_AMOUNT) {
amountWithdrawn = calcExpectedATokenBalance(
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
).toFixed();
}
expectedReserveData.availableLiquidity = new BigNumber(
reserveDataBeforeAction.availableLiquidity
).minus(amountWithdrawn);
2020-09-14 17:25:45 +00:00
expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt;
expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt;
expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex(
reserveDataBeforeAction,
txTimestamp
);
expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex(
reserveDataBeforeAction,
txTimestamp
);
expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt(
2020-09-18 15:56:33 +00:00
reserveDataBeforeAction.principalStableDebt,
reserveDataBeforeAction.averageStableBorrowRate,
2020-09-21 13:27:53 +00:00
reserveDataBeforeAction.totalStableDebtLastUpdated,
txTimestamp
);
2020-09-21 10:29:33 +00:00
expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul(
expectedReserveData.variableBorrowIndex
);
2020-09-14 17:25:45 +00:00
2020-06-30 12:09:28 +00:00
expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate;
2020-09-21 10:29:33 +00:00
expectedReserveData.totalLiquidity = new BigNumber(reserveDataBeforeAction.availableLiquidity)
.minus(amountWithdrawn)
.plus(expectedReserveData.totalVariableDebt)
.plus(expectedReserveData.totalStableDebt);
expectedReserveData.utilizationRate = calcExpectedUtilizationRate(
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.totalLiquidity
);
const rates = calcExpectedInterestRates(
reserveDataBeforeAction.symbol,
reserveDataBeforeAction.marketStableRate,
expectedReserveData.utilizationRate,
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.averageStableBorrowRate
);
expectedReserveData.liquidityRate = rates[0];
expectedReserveData.stableBorrowRate = rates[1];
expectedReserveData.variableBorrowRate = rates[2];
return expectedReserveData;
};
export const calcExpectedReserveDataAfterBorrow = (
amountBorrowed: string,
borrowRateMode: string,
reserveDataBeforeAction: ReserveData,
userDataBeforeAction: UserReserveData,
txTimestamp: BigNumber,
currentTimestamp: BigNumber
): ReserveData => {
const expectedReserveData = <ReserveData>{};
expectedReserveData.address = reserveDataBeforeAction.address;
const amountBorrowedBN = new BigNumber(amountBorrowed);
2020-09-14 18:04:49 +00:00
expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex(
reserveDataBeforeAction,
2020-06-30 12:09:28 +00:00
txTimestamp
);
2020-09-14 18:04:49 +00:00
expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex(
2020-06-30 12:09:28 +00:00
reserveDataBeforeAction,
txTimestamp
);
expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity.minus(
amountBorrowedBN
);
expectedReserveData.lastUpdateTimestamp = txTimestamp;
2020-06-30 12:09:28 +00:00
if (borrowRateMode == RateMode.Stable) {
expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt;
2020-09-21 10:29:33 +00:00
const expectedVariableDebtAfterTx = expectedReserveData.scaledVariableDebt.rayMul(
expectedReserveData.variableBorrowIndex
);
2020-07-03 21:20:02 +00:00
2020-09-18 15:56:33 +00:00
const expectedStableDebtUntilTx = calcExpectedTotalStableDebt(
reserveDataBeforeAction.principalStableDebt,
reserveDataBeforeAction.averageStableBorrowRate,
2020-09-21 13:27:53 +00:00
reserveDataBeforeAction.totalStableDebtLastUpdated,
2020-09-18 15:56:33 +00:00
txTimestamp
);
2020-06-30 12:09:28 +00:00
2020-09-18 15:56:33 +00:00
expectedReserveData.principalStableDebt = expectedStableDebtUntilTx.plus(amountBorrowedBN);
expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate(
2020-07-03 21:20:02 +00:00
reserveDataBeforeAction.averageStableBorrowRate,
2020-09-18 15:56:33 +00:00
expectedStableDebtUntilTx,
2020-07-07 10:07:31 +00:00
amountBorrowedBN,
reserveDataBeforeAction.stableBorrowRate
);
2020-09-18 15:56:33 +00:00
const totalLiquidityAfterTx = expectedReserveData.availableLiquidity
.plus(expectedReserveData.principalStableDebt)
.plus(expectedVariableDebtAfterTx);
const utilizationRateAfterTx = calcExpectedUtilizationRate(
expectedReserveData.principalStableDebt, //the expected principal debt is the total debt immediately after the tx
expectedVariableDebtAfterTx,
totalLiquidityAfterTx
);
const ratesAfterTx = calcExpectedInterestRates(
reserveDataBeforeAction.symbol,
reserveDataBeforeAction.marketStableRate,
utilizationRateAfterTx,
expectedReserveData.principalStableDebt,
expectedVariableDebtAfterTx,
expectedReserveData.averageStableBorrowRate
2020-09-17 17:05:22 +00:00
);
2020-09-18 15:56:33 +00:00
expectedReserveData.liquidityRate = ratesAfterTx[0];
expectedReserveData.stableBorrowRate = ratesAfterTx[1];
expectedReserveData.variableBorrowRate = ratesAfterTx[2];
expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt(
2020-09-18 15:56:33 +00:00
expectedReserveData.principalStableDebt,
expectedReserveData.averageStableBorrowRate,
txTimestamp,
currentTimestamp
);
2020-09-18 15:56:33 +00:00
expectedReserveData.totalVariableDebt = reserveDataBeforeAction.scaledVariableDebt.rayMul(
calcExpectedReserveNormalizedDebt(
expectedReserveData.variableBorrowRate,
expectedReserveData.variableBorrowIndex,
txTimestamp,
currentTimestamp
)
);
expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity
.plus(expectedReserveData.totalVariableDebt)
.plus(expectedReserveData.totalStableDebt);
expectedReserveData.utilizationRate = calcExpectedUtilizationRate(
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.totalLiquidity
);
} else {
expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt;
2020-09-21 10:29:33 +00:00
const totalStableDebtAfterTx = calcExpectedStableDebtTokenBalance(
reserveDataBeforeAction.principalStableDebt,
reserveDataBeforeAction.averageStableBorrowRate,
2020-09-21 13:52:53 +00:00
reserveDataBeforeAction.totalStableDebtLastUpdated,
2020-09-21 10:29:33 +00:00
txTimestamp
);
expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt(
reserveDataBeforeAction.principalStableDebt,
reserveDataBeforeAction.averageStableBorrowRate,
2020-09-21 13:27:53 +00:00
reserveDataBeforeAction.totalStableDebtLastUpdated,
currentTimestamp
);
2020-09-21 10:29:33 +00:00
2020-06-30 12:09:28 +00:00
expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate;
expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus(
amountBorrowedBN.rayDiv(expectedReserveData.variableBorrowIndex)
);
2020-06-30 12:09:28 +00:00
const totalVariableDebtAfterTx = expectedReserveData.scaledVariableDebt.rayMul(
expectedReserveData.variableBorrowIndex
2020-09-14 13:09:16 +00:00
);
2020-09-17 17:05:22 +00:00
const utilizationRateAfterTx = calcExpectedUtilizationRate(
2020-09-21 10:29:33 +00:00
totalStableDebtAfterTx,
totalVariableDebtAfterTx,
expectedReserveData.availableLiquidity
2020-09-21 10:29:33 +00:00
.plus(totalStableDebtAfterTx)
.plus(totalVariableDebtAfterTx)
);
const rates = calcExpectedInterestRates(
reserveDataBeforeAction.symbol,
reserveDataBeforeAction.marketStableRate,
2020-09-17 17:05:22 +00:00
utilizationRateAfterTx,
2020-09-21 10:29:33 +00:00
totalStableDebtAfterTx,
totalVariableDebtAfterTx,
expectedReserveData.averageStableBorrowRate
);
expectedReserveData.liquidityRate = rates[0];
expectedReserveData.stableBorrowRate = rates[1];
expectedReserveData.variableBorrowRate = rates[2];
expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul(
2020-09-18 15:56:33 +00:00
calcExpectedReserveNormalizedDebt(
expectedReserveData.variableBorrowRate,
expectedReserveData.variableBorrowIndex,
txTimestamp,
currentTimestamp
)
);
2020-09-17 17:05:22 +00:00
expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity
.plus(expectedReserveData.totalStableDebt)
.plus(expectedReserveData.totalVariableDebt);
expectedReserveData.utilizationRate = calcExpectedUtilizationRate(
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.totalLiquidity
);
}
2020-06-30 12:09:28 +00:00
return expectedReserveData;
};
export const calcExpectedReserveDataAfterRepay = (
amountRepaid: string,
2020-06-30 12:09:28 +00:00
borrowRateMode: RateMode,
reserveDataBeforeAction: ReserveData,
userDataBeforeAction: UserReserveData,
txTimestamp: BigNumber,
currentTimestamp: BigNumber
): ReserveData => {
const expectedReserveData: ReserveData = <ReserveData>{};
expectedReserveData.address = reserveDataBeforeAction.address;
let amountRepaidBN = new BigNumber(amountRepaid);
const userStableDebt = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
txTimestamp
);
2020-09-14 13:09:16 +00:00
const userVariableDebt = calcExpectedVariableDebtTokenBalance(
2020-06-30 12:09:28 +00:00
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
);
2020-09-17 17:05:22 +00:00
//if amount repaid == MAX_UINT_AMOUNT, user is repaying everything
if (amountRepaidBN.abs().eq(MAX_UINT_AMOUNT)) {
2020-06-30 12:09:28 +00:00
if (borrowRateMode == RateMode.Stable) {
2020-09-14 13:09:16 +00:00
amountRepaidBN = userStableDebt;
2020-06-30 12:09:28 +00:00
} else {
2020-09-14 13:09:16 +00:00
amountRepaidBN = userVariableDebt;
2020-06-30 12:09:28 +00:00
}
}
2020-09-17 17:05:22 +00:00
expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex(
reserveDataBeforeAction,
txTimestamp
);
expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex(
reserveDataBeforeAction,
txTimestamp
);
2020-06-30 12:09:28 +00:00
if (borrowRateMode == RateMode.Stable) {
2020-09-18 15:56:33 +00:00
const expectedDebt = calcExpectedTotalStableDebt(
reserveDataBeforeAction.principalStableDebt,
reserveDataBeforeAction.averageStableBorrowRate,
2020-09-21 13:27:53 +00:00
reserveDataBeforeAction.totalStableDebtLastUpdated,
2020-09-18 15:56:33 +00:00
txTimestamp
2020-09-17 17:05:22 +00:00
);
2020-09-18 15:56:33 +00:00
expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedDebt.minus(
amountRepaidBN
);
2020-09-18 15:56:33 +00:00
//due to accumulation errors, the total stable debt might be smaller than the last user debt.
//in this case we simply set the total supply and avg stable rate to 0.
if (expectedReserveData.principalStableDebt.lt(0)) {
expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = new BigNumber(
0
);
expectedReserveData.averageStableBorrowRate = new BigNumber(0);
} else {
expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate(
reserveDataBeforeAction.averageStableBorrowRate,
expectedDebt,
amountRepaidBN.negated(),
userDataBeforeAction.stableBorrowRate
);
}
2020-09-17 17:05:22 +00:00
expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt;
2020-09-21 10:29:33 +00:00
expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul(
expectedReserveData.variableBorrowIndex
);
} else {
2020-09-17 17:05:22 +00:00
expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.minus(
amountRepaidBN.rayDiv(expectedReserveData.variableBorrowIndex)
2020-09-14 13:09:16 +00:00
);
2020-06-30 12:09:28 +00:00
2020-09-17 17:05:22 +00:00
expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul(
expectedReserveData.variableBorrowIndex
);
2020-06-30 12:09:28 +00:00
2020-09-17 17:05:22 +00:00
expectedReserveData.principalStableDebt = reserveDataBeforeAction.principalStableDebt;
expectedReserveData.totalStableDebt = reserveDataBeforeAction.totalStableDebt;
2020-07-03 21:20:02 +00:00
2020-06-30 12:09:28 +00:00
expectedReserveData.averageStableBorrowRate = reserveDataBeforeAction.averageStableBorrowRate;
}
2020-06-30 12:09:28 +00:00
expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity.plus(
amountRepaidBN
);
2020-09-17 17:05:22 +00:00
expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity
.plus(expectedReserveData.totalStableDebt)
.plus(expectedReserveData.totalVariableDebt);
2020-06-30 12:09:28 +00:00
expectedReserveData.utilizationRate = calcExpectedUtilizationRate(
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.totalLiquidity
);
const rates = calcExpectedInterestRates(
reserveDataBeforeAction.symbol,
reserveDataBeforeAction.marketStableRate,
expectedReserveData.utilizationRate,
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.averageStableBorrowRate
);
expectedReserveData.liquidityRate = rates[0];
expectedReserveData.stableBorrowRate = rates[1];
expectedReserveData.variableBorrowRate = rates[2];
2020-06-30 12:09:28 +00:00
expectedReserveData.lastUpdateTimestamp = txTimestamp;
return expectedReserveData;
};
export const calcExpectedUserDataAfterBorrow = (
amountBorrowed: string,
interestRateMode: string,
reserveDataBeforeAction: ReserveData,
expectedDataAfterAction: ReserveData,
userDataBeforeAction: UserReserveData,
txTimestamp: BigNumber,
2020-09-21 13:35:22 +00:00
currentTimestamp: BigNumber
): UserReserveData => {
const expectedUserData = <UserReserveData>{};
const amountBorrowedBN = new BigNumber(amountBorrowed);
2020-07-03 21:20:02 +00:00
if (interestRateMode == RateMode.Stable) {
const stableDebtUntilTx = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
txTimestamp
);
expectedUserData.principalStableDebt = stableDebtUntilTx.plus(amountBorrowed);
expectedUserData.stableRateLastUpdated = txTimestamp;
2020-07-07 10:07:31 +00:00
expectedUserData.stableBorrowRate = calcExpectedUserStableRate(
stableDebtUntilTx,
2020-07-07 10:07:31 +00:00
userDataBeforeAction.stableBorrowRate,
amountBorrowedBN,
2020-07-07 10:07:31 +00:00
reserveDataBeforeAction.stableBorrowRate
);
expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance(
expectedUserData.principalStableDebt,
expectedUserData.stableBorrowRate,
txTimestamp,
currentTimestamp
);
expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt;
2020-07-03 21:20:02 +00:00
} else {
expectedUserData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus(
amountBorrowedBN.rayDiv(expectedDataAfterAction.variableBorrowIndex)
);
2020-07-13 08:54:08 +00:00
expectedUserData.principalStableDebt = userDataBeforeAction.principalStableDebt;
2020-07-07 10:07:31 +00:00
expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate;
2020-06-30 12:09:28 +00:00
2020-07-03 21:20:02 +00:00
expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated;
2020-06-30 12:09:28 +00:00
2020-09-17 17:05:22 +00:00
expectedUserData.currentStableDebt = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
currentTimestamp
);
2020-07-03 21:20:02 +00:00
}
expectedUserData.currentVariableDebt = calcExpectedVariableDebtTokenBalance(
2020-07-03 21:20:02 +00:00
expectedDataAfterAction,
2020-09-17 17:05:22 +00:00
expectedUserData,
2020-07-03 21:20:02 +00:00
currentTimestamp
);
2020-06-30 12:09:28 +00:00
expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate;
2020-06-30 12:09:28 +00:00
expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled;
expectedUserData.currentATokenBalance = calcExpectedATokenBalance(
expectedDataAfterAction,
userDataBeforeAction,
currentTimestamp
);
2020-09-09 08:44:34 +00:00
expectedUserData.scaledATokenBalance = userDataBeforeAction.scaledATokenBalance;
2020-09-15 08:57:04 +00:00
2020-09-04 08:27:32 +00:00
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountBorrowed);
return expectedUserData;
};
export const calcExpectedUserDataAfterRepay = (
totalRepaid: string,
2020-06-30 12:09:28 +00:00
rateMode: RateMode,
reserveDataBeforeAction: ReserveData,
expectedDataAfterAction: ReserveData,
userDataBeforeAction: UserReserveData,
user: string,
onBehalfOf: string,
txTimestamp: BigNumber,
2020-09-21 13:35:22 +00:00
currentTimestamp: BigNumber
): UserReserveData => {
const expectedUserData = <UserReserveData>{};
2020-09-17 17:05:22 +00:00
const variableDebt = calcExpectedVariableDebtTokenBalance(
reserveDataBeforeAction,
2020-06-30 12:09:28 +00:00
userDataBeforeAction,
currentTimestamp
);
2020-09-17 17:05:22 +00:00
const stableDebt = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
2020-06-30 12:09:28 +00:00
currentTimestamp
);
2020-09-17 17:05:22 +00:00
let totalRepaidBN = new BigNumber(totalRepaid);
if (totalRepaidBN.abs().eq(MAX_UINT_AMOUNT)) {
2020-09-18 15:56:33 +00:00
totalRepaidBN = rateMode == RateMode.Stable ? stableDebt : variableDebt;
2020-07-03 21:20:02 +00:00
}
2020-07-03 21:20:02 +00:00
if (rateMode == RateMode.Stable) {
2020-09-17 17:05:22 +00:00
expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt;
2020-09-21 10:29:33 +00:00
expectedUserData.currentVariableDebt = variableDebt;
2020-09-17 17:05:22 +00:00
expectedUserData.principalStableDebt = expectedUserData.currentStableDebt = stableDebt.minus(
2020-09-18 15:56:33 +00:00
totalRepaidBN
2020-07-03 21:20:02 +00:00
);
if (expectedUserData.currentStableDebt.eq('0')) {
2020-07-03 21:20:02 +00:00
//user repaid everything
2020-07-07 10:07:31 +00:00
expectedUserData.stableBorrowRate = expectedUserData.stableRateLastUpdated = new BigNumber(
'0'
);
2020-09-04 08:27:32 +00:00
} else {
2020-08-20 15:09:23 +00:00
expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate;
expectedUserData.stableRateLastUpdated = txTimestamp;
}
2020-07-03 21:20:02 +00:00
} else {
2020-09-17 17:05:22 +00:00
expectedUserData.currentStableDebt = userDataBeforeAction.principalStableDebt;
expectedUserData.principalStableDebt = stableDebt;
2020-07-03 21:20:02 +00:00
expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate;
expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated;
2020-09-18 15:56:33 +00:00
expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt.minus(
totalRepaidBN.rayDiv(expectedDataAfterAction.variableBorrowIndex)
);
expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt.rayMul(
expectedDataAfterAction.variableBorrowIndex
2020-07-03 21:20:02 +00:00
);
}
expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate;
2020-06-30 12:09:28 +00:00
expectedUserData.usageAsCollateralEnabled = userDataBeforeAction.usageAsCollateralEnabled;
expectedUserData.currentATokenBalance = calcExpectedATokenBalance(
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
);
expectedUserData.scaledATokenBalance = userDataBeforeAction.scaledATokenBalance;
2020-09-15 08:57:04 +00:00
if (user === onBehalfOf) {
2020-09-17 17:05:22 +00:00
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(totalRepaidBN);
} else {
//wallet balance didn't change
expectedUserData.walletBalance = userDataBeforeAction.walletBalance;
}
return expectedUserData;
};
export const calcExpectedUserDataAfterSetUseAsCollateral = (
useAsCollateral: boolean,
reserveDataBeforeAction: ReserveData,
userDataBeforeAction: UserReserveData,
txCost: BigNumber
): UserReserveData => {
2020-09-09 19:26:52 +00:00
const expectedUserData = {...userDataBeforeAction};
expectedUserData.usageAsCollateralEnabled = useAsCollateral;
return expectedUserData;
};
export const calcExpectedReserveDataAfterSwapRateMode = (
reserveDataBeforeAction: ReserveData,
userDataBeforeAction: UserReserveData,
2020-07-07 10:07:31 +00:00
rateMode: string,
txTimestamp: BigNumber
): ReserveData => {
const expectedReserveData: ReserveData = <ReserveData>{};
expectedReserveData.address = reserveDataBeforeAction.address;
2020-09-14 13:09:16 +00:00
const variableDebt = calcExpectedVariableDebtTokenBalance(
reserveDataBeforeAction,
2020-06-30 12:09:28 +00:00
userDataBeforeAction,
txTimestamp
);
const stableDebt = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
txTimestamp
);
2020-09-21 12:29:59 +00:00
expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex(
reserveDataBeforeAction,
txTimestamp
);
expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex(
reserveDataBeforeAction,
txTimestamp
);
2020-06-30 12:09:28 +00:00
expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity;
2020-09-21 12:29:59 +00:00
const totalStableDebtUntilTx = calcExpectedTotalStableDebt(
reserveDataBeforeAction.principalStableDebt,
reserveDataBeforeAction.averageStableBorrowRate,
2020-09-21 13:27:53 +00:00
reserveDataBeforeAction.totalStableDebtLastUpdated,
2020-09-21 12:29:59 +00:00
txTimestamp
);
2020-07-07 10:07:31 +00:00
if (rateMode === RateMode.Stable) {
//swap user stable debt to variable
2020-09-21 12:29:59 +00:00
expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.plus(
stableDebt.rayDiv(expectedReserveData.variableBorrowIndex)
);
2020-06-30 12:09:28 +00:00
2020-09-21 12:29:59 +00:00
expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul(
expectedReserveData.variableBorrowIndex
);
2020-06-30 12:09:28 +00:00
2020-09-21 13:27:53 +00:00
expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = totalStableDebtUntilTx.minus(
stableDebt
);
expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate(
reserveDataBeforeAction.averageStableBorrowRate,
2020-09-21 12:29:59 +00:00
expectedReserveData.principalStableDebt.plus(stableDebt),
2020-09-14 13:09:16 +00:00
stableDebt.negated(),
2020-06-30 12:09:28 +00:00
userDataBeforeAction.stableBorrowRate
);
2020-09-21 12:29:59 +00:00
} else {
//swap variable to stable
2020-07-07 10:07:31 +00:00
2020-09-21 12:29:59 +00:00
expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = totalStableDebtUntilTx.plus(
variableDebt
);
2020-07-07 10:07:31 +00:00
2020-09-21 12:29:59 +00:00
expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt.minus(
variableDebt.rayDiv(expectedReserveData.variableBorrowIndex)
2020-06-30 12:09:28 +00:00
);
2020-09-21 12:29:59 +00:00
expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul(
expectedReserveData.variableBorrowIndex
2020-07-07 10:07:31 +00:00
);
2020-06-30 12:09:28 +00:00
expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate(
reserveDataBeforeAction.averageStableBorrowRate,
reserveDataBeforeAction.totalStableDebt,
2020-09-14 13:09:16 +00:00
variableDebt,
reserveDataBeforeAction.stableBorrowRate
);
}
2020-09-21 12:29:59 +00:00
expectedReserveData.totalLiquidity = reserveDataBeforeAction.availableLiquidity
.plus(expectedReserveData.totalStableDebt)
.plus(expectedReserveData.totalVariableDebt);
expectedReserveData.utilizationRate = calcExpectedUtilizationRate(
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.totalLiquidity
);
const rates = calcExpectedInterestRates(
reserveDataBeforeAction.symbol,
reserveDataBeforeAction.marketStableRate,
expectedReserveData.utilizationRate,
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.averageStableBorrowRate
);
expectedReserveData.liquidityRate = rates[0];
expectedReserveData.stableBorrowRate = rates[1];
expectedReserveData.variableBorrowRate = rates[2];
return expectedReserveData;
};
export const calcExpectedUserDataAfterSwapRateMode = (
reserveDataBeforeAction: ReserveData,
expectedDataAfterAction: ReserveData,
userDataBeforeAction: UserReserveData,
2020-07-07 10:07:31 +00:00
rateMode: string,
txCost: BigNumber,
txTimestamp: BigNumber
): UserReserveData => {
2020-09-09 19:26:52 +00:00
const expectedUserData = {...userDataBeforeAction};
2020-09-21 12:29:59 +00:00
const stableDebtBalance = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
txTimestamp
);
2020-09-21 12:29:59 +00:00
const variableDebtBalance = calcExpectedVariableDebtTokenBalance(
2020-06-30 12:09:28 +00:00
reserveDataBeforeAction,
userDataBeforeAction,
2020-06-30 12:09:28 +00:00
txTimestamp
);
expectedUserData.currentATokenBalance = calcExpectedATokenBalance(
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
);
2020-07-07 10:07:31 +00:00
if (rateMode === RateMode.Stable) {
2020-07-13 08:54:08 +00:00
// swap to variable
expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = new BigNumber(0);
2020-07-07 10:07:31 +00:00
2020-06-30 12:09:28 +00:00
expectedUserData.stableBorrowRate = new BigNumber(0);
2020-07-13 08:54:08 +00:00
2020-09-21 12:29:59 +00:00
expectedUserData.scaledVariableDebt = userDataBeforeAction.scaledVariableDebt.plus(
stableDebtBalance.rayDiv(expectedDataAfterAction.variableBorrowIndex)
);
expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt.rayMul(
expectedDataAfterAction.variableBorrowIndex
2020-06-30 12:09:28 +00:00
);
2020-09-21 12:29:59 +00:00
2020-07-07 10:07:31 +00:00
expectedUserData.stableRateLastUpdated = new BigNumber(0);
} else {
expectedUserData.principalStableDebt = expectedUserData.currentStableDebt = userDataBeforeAction.currentStableDebt.plus(
2020-09-21 12:29:59 +00:00
variableDebtBalance
2020-06-30 12:09:28 +00:00
);
//weighted average of the previous and the current
2020-07-07 10:07:31 +00:00
expectedUserData.stableBorrowRate = calcExpectedUserStableRate(
2020-09-21 12:29:59 +00:00
stableDebtBalance,
2020-07-07 10:07:31 +00:00
userDataBeforeAction.stableBorrowRate,
2020-09-21 12:29:59 +00:00
variableDebtBalance,
2020-07-07 10:07:31 +00:00
reserveDataBeforeAction.stableBorrowRate
);
2020-06-30 12:09:28 +00:00
2020-07-07 10:07:31 +00:00
expectedUserData.stableRateLastUpdated = txTimestamp;
2020-09-21 12:29:59 +00:00
expectedUserData.currentVariableDebt = expectedUserData.scaledVariableDebt = new BigNumber(0);
}
expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate;
return expectedUserData;
};
export const calcExpectedReserveDataAfterStableRateRebalance = (
reserveDataBeforeAction: ReserveData,
userDataBeforeAction: UserReserveData,
txTimestamp: BigNumber
): ReserveData => {
const expectedReserveData: ReserveData = <ReserveData>{};
expectedReserveData.address = reserveDataBeforeAction.address;
2020-09-21 13:27:53 +00:00
const userStableDebt = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
txTimestamp
);
2020-09-21 13:27:53 +00:00
expectedReserveData.liquidityIndex = calcExpectedLiquidityIndex(
reserveDataBeforeAction,
txTimestamp
);
expectedReserveData.variableBorrowIndex = calcExpectedVariableBorrowIndex(
reserveDataBeforeAction,
txTimestamp
);
2020-09-21 13:27:53 +00:00
expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt;
expectedReserveData.totalVariableDebt = expectedReserveData.scaledVariableDebt.rayMul(
expectedReserveData.variableBorrowIndex
);
2020-09-21 13:27:53 +00:00
expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = calcExpectedTotalStableDebt(
reserveDataBeforeAction.principalStableDebt,
reserveDataBeforeAction.averageStableBorrowRate,
reserveDataBeforeAction.totalStableDebtLastUpdated,
txTimestamp
);
2020-06-30 12:09:28 +00:00
expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity;
2020-09-21 13:27:53 +00:00
expectedReserveData.totalLiquidity = expectedReserveData.availableLiquidity
.plus(expectedReserveData.totalStableDebt)
.plus(expectedReserveData.totalVariableDebt);
2020-07-07 11:57:08 +00:00
//removing the stable liquidity at the old rate
const avgRateBefore = calcExpectedAverageStableBorrowRate(
reserveDataBeforeAction.averageStableBorrowRate,
2020-09-21 13:27:53 +00:00
expectedReserveData.totalStableDebt,
userStableDebt.negated(),
2020-06-30 12:09:28 +00:00
userDataBeforeAction.stableBorrowRate
);
2020-07-07 11:57:08 +00:00
// adding it again at the new rate
expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate(
avgRateBefore,
2020-09-21 13:27:53 +00:00
expectedReserveData.totalStableDebt.minus(userStableDebt),
userStableDebt,
2020-07-07 11:57:08 +00:00
reserveDataBeforeAction.stableBorrowRate
);
expectedReserveData.utilizationRate = calcExpectedUtilizationRate(
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.totalLiquidity
);
const rates = calcExpectedInterestRates(
reserveDataBeforeAction.symbol,
reserveDataBeforeAction.marketStableRate,
expectedReserveData.utilizationRate,
expectedReserveData.totalStableDebt,
expectedReserveData.totalVariableDebt,
expectedReserveData.averageStableBorrowRate
);
expectedReserveData.liquidityRate = rates[0];
expectedReserveData.stableBorrowRate = rates[1];
expectedReserveData.variableBorrowRate = rates[2];
return expectedReserveData;
};
export const calcExpectedUserDataAfterStableRateRebalance = (
reserveDataBeforeAction: ReserveData,
expectedDataAfterAction: ReserveData,
userDataBeforeAction: UserReserveData,
txCost: BigNumber,
txTimestamp: BigNumber
): UserReserveData => {
2020-09-09 19:26:52 +00:00
const expectedUserData = {...userDataBeforeAction};
expectedUserData.principalVariableDebt = calcExpectedVariableDebtTokenBalance(
2020-06-30 12:09:28 +00:00
reserveDataBeforeAction,
userDataBeforeAction,
2020-06-30 12:09:28 +00:00
txTimestamp
);
expectedUserData.currentStableDebt = expectedUserData.principalStableDebt = calcExpectedStableDebtTokenBalance(
userDataBeforeAction.principalStableDebt,
userDataBeforeAction.stableBorrowRate,
userDataBeforeAction.stableRateLastUpdated,
txTimestamp
);
2020-07-07 11:57:08 +00:00
expectedUserData.stableRateLastUpdated = txTimestamp;
2020-07-13 08:54:08 +00:00
expectedUserData.principalVariableDebt = userDataBeforeAction.principalVariableDebt;
2020-06-30 12:09:28 +00:00
expectedUserData.stableBorrowRate = reserveDataBeforeAction.stableBorrowRate;
expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate;
expectedUserData.currentATokenBalance = calcExpectedATokenBalance(
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
);
return expectedUserData;
};
2020-09-08 11:45:24 +00:00
const calcExpectedScaledATokenBalance = (
userDataBeforeAction: UserReserveData,
index: BigNumber,
2020-09-08 11:45:24 +00:00
amountAdded: BigNumber,
amountTaken: BigNumber
) => {
return userDataBeforeAction.scaledATokenBalance
.plus(amountAdded.rayDiv(index))
.minus(amountTaken.rayDiv(index));
};
2020-09-08 10:08:16 +00:00
export const calcExpectedATokenBalance = (
reserveData: ReserveData,
userData: UserReserveData,
currentTimestamp: BigNumber
) => {
const index = calcExpectedReserveNormalizedIncome(reserveData, currentTimestamp);
const {scaledATokenBalance: scaledBalanceBeforeAction} = userData;
return scaledBalanceBeforeAction.rayMul(index);
};
const calcExpectedAverageStableBorrowRate = (
avgStableRateBefore: BigNumber,
totalStableDebtBefore: BigNumber,
amountChanged: string | BigNumber,
rate: BigNumber
) => {
const weightedTotalBorrows = avgStableRateBefore.multipliedBy(totalStableDebtBefore);
const weightedAmountBorrowed = rate.multipliedBy(amountChanged);
const totalBorrowedStable = totalStableDebtBefore.plus(new BigNumber(amountChanged));
2020-06-30 12:09:28 +00:00
if (totalBorrowedStable.eq(0)) return new BigNumber('0');
return weightedTotalBorrows
.plus(weightedAmountBorrowed)
.div(totalBorrowedStable)
.decimalPlaces(0, BigNumber.ROUND_DOWN);
};
2020-07-08 15:26:50 +00:00
export const calcExpectedVariableDebtTokenBalance = (
reserveData: ReserveData,
userData: UserReserveData,
2020-06-30 12:09:28 +00:00
currentTimestamp: BigNumber
) => {
2020-09-18 15:56:33 +00:00
const normalizedDebt = calcExpectedReserveNormalizedDebt(
reserveData.variableBorrowRate,
reserveData.variableBorrowIndex,
reserveData.lastUpdateTimestamp,
currentTimestamp
);
2020-06-30 12:09:28 +00:00
const {scaledVariableDebt} = userData;
return scaledVariableDebt.rayMul(normalizedDebt);
2020-06-30 12:09:28 +00:00
};
2020-07-08 15:26:50 +00:00
export const calcExpectedStableDebtTokenBalance = (
principalStableDebt: BigNumber,
stableBorrowRate: BigNumber,
stableRateLastUpdated: BigNumber,
2020-06-30 12:09:28 +00:00
currentTimestamp: BigNumber
) => {
2020-07-07 10:07:31 +00:00
if (
stableBorrowRate.eq(0) ||
currentTimestamp.eq(stableRateLastUpdated) ||
stableRateLastUpdated.eq(0)
) {
return principalStableDebt;
}
2020-06-30 12:09:28 +00:00
const cumulatedInterest = calcCompoundedInterest(
stableBorrowRate,
currentTimestamp,
2020-07-03 21:20:02 +00:00
stableRateLastUpdated
2020-06-30 12:09:28 +00:00
);
return principalStableDebt.rayMul(cumulatedInterest);
};
const calcLinearInterest = (
rate: BigNumber,
currentTimestamp: BigNumber,
lastUpdateTimestamp: BigNumber
) => {
const timeDifference = currentTimestamp.minus(lastUpdateTimestamp).wadToRay();
const timeDelta = timeDifference.rayDiv(new BigNumber(ONE_YEAR).wadToRay());
const cumulatedInterest = rate.rayMul(timeDelta).plus(RAY);
return cumulatedInterest;
};
const calcCompoundedInterest = (
rate: BigNumber,
currentTimestamp: BigNumber,
lastUpdateTimestamp: BigNumber
) => {
const timeDifference = currentTimestamp.minus(lastUpdateTimestamp);
if (timeDifference.eq(0)) {
return new BigNumber(RAY);
}
2020-08-11 07:36:46 +00:00
const expMinusOne = timeDifference.minus(1);
const expMinusTwo = timeDifference.gt(2) ? timeDifference.minus(2) : 0;
2020-08-11 07:36:46 +00:00
const ratePerSecond = rate.div(ONE_YEAR);
2020-08-11 07:36:46 +00:00
const basePowerTwo = ratePerSecond.rayMul(ratePerSecond);
const basePowerThree = basePowerTwo.rayMul(ratePerSecond);
const secondTerm = timeDifference.times(expMinusOne).times(basePowerTwo).div(2);
const thirdTerm = timeDifference
.times(expMinusOne)
.times(expMinusTwo)
.times(basePowerThree)
.div(6);
return new BigNumber(RAY)
.plus(ratePerSecond.times(timeDifference))
.plus(secondTerm)
.plus(thirdTerm);
};
const calcExpectedInterestRates = (
reserveSymbol: string,
marketStableRate: BigNumber,
utilizationRate: BigNumber,
totalStableDebt: BigNumber,
totalVariableDebt: BigNumber,
averageStableBorrowRate: BigNumber
): BigNumber[] => {
2020-09-09 19:26:52 +00:00
const {reservesParams} = configuration;
2020-06-30 12:09:28 +00:00
const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol);
const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[
reserveIndex
];
let stableBorrowRate: BigNumber = marketStableRate;
2020-06-30 12:09:28 +00:00
let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.baseVariableBorrowRate);
if (utilizationRate.gt(OPTIMAL_UTILIZATION_RATE)) {
const excessUtilizationRateRatio = utilizationRate
.minus(OPTIMAL_UTILIZATION_RATE)
.rayDiv(EXCESS_UTILIZATION_RATE);
stableBorrowRate = stableBorrowRate
.plus(reserveConfiguration.stableRateSlope1)
.plus(
2020-06-30 12:09:28 +00:00
new BigNumber(reserveConfiguration.stableRateSlope2).rayMul(excessUtilizationRateRatio)
);
variableBorrowRate = variableBorrowRate
.plus(reserveConfiguration.variableRateSlope1)
.plus(
2020-06-30 12:09:28 +00:00
new BigNumber(reserveConfiguration.variableRateSlope2).rayMul(excessUtilizationRateRatio)
);
} else {
stableBorrowRate = stableBorrowRate.plus(
new BigNumber(reserveConfiguration.stableRateSlope1).rayMul(
utilizationRate.rayDiv(new BigNumber(OPTIMAL_UTILIZATION_RATE))
)
);
variableBorrowRate = variableBorrowRate.plus(
utilizationRate
.rayDiv(OPTIMAL_UTILIZATION_RATE)
.rayMul(new BigNumber(reserveConfiguration.variableRateSlope1))
);
}
const expectedOverallRate = calcExpectedOverallBorrowRate(
totalStableDebt,
totalVariableDebt,
variableBorrowRate,
averageStableBorrowRate
);
const liquidityRate = expectedOverallRate.rayMul(utilizationRate);
return [liquidityRate, stableBorrowRate, variableBorrowRate];
};
const calcExpectedOverallBorrowRate = (
totalStableDebt: BigNumber,
totalVariableDebt: BigNumber,
currentVariableBorrowRate: BigNumber,
currentAverageStableBorrowRate: BigNumber
): BigNumber => {
const totalBorrows = totalStableDebt.plus(totalVariableDebt);
2020-06-30 12:09:28 +00:00
if (totalBorrows.eq(0)) return strToBN('0');
const weightedVariableRate = totalVariableDebt.wadToRay().rayMul(currentVariableBorrowRate);
const weightedStableRate = totalStableDebt.wadToRay().rayMul(currentAverageStableBorrowRate);
const overallBorrowRate = weightedVariableRate
.plus(weightedStableRate)
.rayDiv(totalBorrows.wadToRay());
return overallBorrowRate;
};
const calcExpectedUtilizationRate = (
totalStableDebt: BigNumber,
totalVariableDebt: BigNumber,
totalLiquidity: BigNumber
): BigNumber => {
if (totalStableDebt.eq('0') && totalVariableDebt.eq('0')) {
2020-06-30 12:09:28 +00:00
return strToBN('0');
}
const utilization = totalStableDebt.plus(totalVariableDebt).rayDiv(totalLiquidity);
return utilization;
};
const calcExpectedReserveNormalizedIncome = (
reserveData: ReserveData,
currentTimestamp: BigNumber
) => {
2020-09-09 19:26:52 +00:00
const {liquidityRate, liquidityIndex, lastUpdateTimestamp} = reserveData;
//if utilization rate is 0, nothing to compound
2020-06-30 12:09:28 +00:00
if (liquidityRate.eq('0')) {
return liquidityIndex;
}
const cumulatedInterest = calcLinearInterest(
liquidityRate,
currentTimestamp,
lastUpdateTimestamp
);
const income = cumulatedInterest.rayMul(liquidityIndex);
return income;
};
2020-06-30 12:09:28 +00:00
const calcExpectedReserveNormalizedDebt = (
2020-09-18 15:56:33 +00:00
variableBorrowRate: BigNumber,
variableBorrowIndex: BigNumber,
lastUpdateTimestamp: BigNumber,
2020-06-30 12:09:28 +00:00
currentTimestamp: BigNumber
) => {
2020-06-30 12:09:28 +00:00
//if utilization rate is 0, nothing to compound
if (variableBorrowRate.eq('0')) {
return variableBorrowIndex;
}
const cumulatedInterest = calcCompoundedInterest(
variableBorrowRate,
currentTimestamp,
lastUpdateTimestamp
);
const debt = cumulatedInterest.rayMul(variableBorrowIndex);
return debt;
};
2020-07-07 10:07:31 +00:00
const calcExpectedUserStableRate = (
balanceBefore: BigNumber,
rateBefore: BigNumber,
amount: BigNumber,
rateNew: BigNumber
) => {
return balanceBefore
.times(rateBefore)
.plus(amount.times(rateNew))
.div(balanceBefore.plus(amount));
};
2020-06-30 12:09:28 +00:00
const calcExpectedLiquidityIndex = (reserveData: ReserveData, timestamp: BigNumber) => {
//if utilization rate is 0, nothing to compound
2020-06-30 12:09:28 +00:00
if (reserveData.utilizationRate.eq('0')) {
return reserveData.liquidityIndex;
}
const cumulatedInterest = calcLinearInterest(
reserveData.liquidityRate,
timestamp,
reserveData.lastUpdateTimestamp
);
return cumulatedInterest.rayMul(reserveData.liquidityIndex);
};
2020-06-30 12:09:28 +00:00
const calcExpectedVariableBorrowIndex = (reserveData: ReserveData, timestamp: BigNumber) => {
//if totalVariableDebt is 0, nothing to compound
if (reserveData.totalVariableDebt.eq('0')) {
return reserveData.variableBorrowIndex;
}
const cumulatedInterest = calcCompoundedInterest(
reserveData.variableBorrowRate,
timestamp,
reserveData.lastUpdateTimestamp
);
return cumulatedInterest.rayMul(reserveData.variableBorrowIndex);
};
2020-09-14 17:25:45 +00:00
2020-09-18 15:56:33 +00:00
const calcExpectedTotalStableDebt = (
principalStableDebt: BigNumber,
averageStableBorrowRate: BigNumber,
lastUpdateTimestamp: BigNumber,
currentTimestamp: BigNumber
) => {
2020-09-14 17:25:45 +00:00
const cumulatedInterest = calcCompoundedInterest(
2020-09-18 15:56:33 +00:00
averageStableBorrowRate,
currentTimestamp,
lastUpdateTimestamp
2020-09-14 17:25:45 +00:00
);
2020-09-18 15:56:33 +00:00
return cumulatedInterest.rayMul(principalStableDebt);
};
2020-09-14 17:25:45 +00:00
const calcExpectedTotalVariableDebt = (
reserveData: ReserveData,
expectedVariableDebtIndex: BigNumber
) => {
2020-09-14 17:25:45 +00:00
return reserveData.scaledVariableDebt.rayMul(expectedVariableDebtIndex);
};