Skip to content

Commit

Permalink
Bugfix/fee slippage values (#765)
Browse files Browse the repository at this point in the history
* fix: initial change

* fix: deposit and withdraw summaries

* fix: simplify liquidation risk

* fix: leveraged vault fees

* fix: deleverage withdraw summary

* fix: roll debt convert asset

* fix: realized calculations

* fix: roll vault position

* fix: max vault withdraw

* fix: vault risk bug
  • Loading branch information
jeffywu authored Apr 19, 2024
1 parent e3293f1 commit 4984998
Show file tree
Hide file tree
Showing 15 changed files with 436 additions and 342 deletions.
2 changes: 1 addition & 1 deletion packages/core-entities/src/exchanges/default-pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const defaultPools: Record<Network, PoolDefinition[]> = {
},
{
address: '0x383E6b4437b59fff47B619CBA855CA29342A8559',
PoolClass: 'Curve2TokenPoolV1_SelfLPToken',
PoolClass: 'Curve2TokenPoolV1_SelfLPTokenNoAdmin',
registerTokens: [
{
id: '0x383E6b4437b59fff47B619CBA855CA29342A8559',
Expand Down
10 changes: 6 additions & 4 deletions packages/features/portfolio/src/side-drawers/convert-asset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ export const ConvertAsset = () => {
state: { collateral },
updateState,
} = context;
const [hasUserTouched, setHasUserTouched] = useState<boolean>(false)
const [hasUserTouched, setHasUserTouched] = useState<boolean>(false);

const onBalanceChange = (
inputAmount: TokenBalance | undefined,
_: TokenBalance | undefined,
maxBalance: TokenBalance | undefined
) => {
if (inputAmount) setHasUserTouched(true)
// Fixes a race condition where the screen flashes
if (inputAmount === undefined && hasUserTouched === false) return;
if (inputAmount) setHasUserTouched(true);
updateState({
debtBalance: inputAmount,
maxWithdraw: maxBalance && inputAmount?.neg().eq(maxBalance),
Expand All @@ -35,7 +37,7 @@ export const ConvertAsset = () => {
return (
<Box>
<Box sx={{ display: collateral === undefined ? 'block' : 'none' }}>
<SelectConvertAsset context={context} hasUserTouched={hasUserTouched}/>
<SelectConvertAsset context={context} hasUserTouched={hasUserTouched} />
</Box>
{collateral && (
<PortfolioSideDrawer context={context}>
Expand All @@ -47,7 +49,7 @@ export const ConvertAsset = () => {
background: theme.palette.background.paper,
}}
titleText={defineMessage({ defaultMessage: 'Back' })}
></SideBarSubHeader>
/>
<AssetInput
ref={currencyInputRef}
debtOrCollateral="Debt"
Expand Down
2 changes: 2 additions & 0 deletions packages/features/portfolio/src/side-drawers/roll-debt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const RollDebt = () => {
_: TokenBalance | undefined,
maxBalance: TokenBalance | undefined
) => {
// Fixes a race condition where the screen flashes
if (inputAmount === undefined && hasUserTouched === false) return;
if (inputAmount) setHasUserTouched(true);
updateState({
collateralBalance: inputAmount,
Expand Down
11 changes: 4 additions & 7 deletions packages/features/vault/src/components/vault-side-drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ToggleSwitchProps } from '@notional-finance/mui';
import { TransactionSidebar } from '@notional-finance/trade';
import { useHistory } from 'react-router';
import { messages } from '../messages';
import { VaultDetailsTable } from './vault-details-table';
import {
VaultContext,
useVaultProperties,
Expand Down Expand Up @@ -43,14 +42,12 @@ export const VaultSideDrawer = ({
showDrawer={false}
heading={messages[tradeType].heading}
advancedToggle={advancedToggle}
onCancelRouteCallback={() => history.push(`/vaults/${selectedNetwork}/${vaultAddress}`)}
onCancelRouteCallback={() =>
history.push(`/vaults/${selectedNetwork}/${vaultAddress}`)
}
hideTextOnMobile={false}
riskComponent={
tradeType === 'CreateVaultPosition' ? (
<CreateVaultLiquidationRisk key={'vault-risk-table'} state={state} />
) : (
<VaultDetailsTable key={'vault-risk-table'} />
)
<CreateVaultLiquidationRisk key={'vault-risk-table'} state={state} />
}
helptext={{
...messages[tradeType].helptext,
Expand Down
11 changes: 8 additions & 3 deletions packages/features/vault/src/hooks/use-vault-details-table.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { useContext } from 'react';
import { formatMaturity } from '@notional-finance/util';
import { VaultActionContext } from '../vault';
import { useVaultLiquidationRisk } from '@notional-finance/notionable-hooks';
import { useVaultDetails } from '@notional-finance/notionable-hooks';

export function useVaultDetailsTable() {
const { state } = useContext(VaultActionContext);
const { priorVaultBalances, collateralBalance } = state;
const { tableData, priorAccountNoRisk, postAccountNoRisk, tooRisky, onlyCurrent } =
useVaultLiquidationRisk(state);
const {
tableData,
priorAccountNoRisk,
postAccountNoRisk,
tooRisky,
onlyCurrent,
} = useVaultDetails(state);

const maturity =
collateralBalance?.maturity ||
Expand Down
20 changes: 16 additions & 4 deletions packages/features/vault/src/side-drawers/withdraw-vault.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,19 @@ export const WithdrawVault = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [updateState, inputAmount?.hashKey]);

const maxWithdrawUnderlying = useMemo(() => {
return profile?.maxWithdraw().toUnderlying();
const maxWithdrawValues = useMemo(() => {
return profile?.maxWithdraw();
}, [profile]);

const onMaxValue = useCallback(() => {
if (profile && maxWithdrawUnderlying) {
if (profile && maxWithdrawValues) {
const {
maxWithdrawUnderlying,
netRealizedCollateralBalance,
netRealizedDebtBalance,
debtFee,
collateralFee,
} = maxWithdrawValues;
setCurrencyInput(maxWithdrawUnderlying.toExactString(), false);

updateState({
Expand All @@ -66,9 +73,14 @@ export const WithdrawVault = () => {
calculateError: undefined,
collateralBalance: profile.vaultShares.neg(),
debtBalance: profile.vaultDebt.neg(),
netRealizedCollateralBalance,
netRealizedDebtBalance,
debtFee,
collateralFee,
});
}
}, [profile, setCurrencyInput, maxWithdrawUnderlying, updateState]);
}, [profile, setCurrencyInput, updateState, maxWithdrawValues]);
const maxWithdrawUnderlying = maxWithdrawValues?.maxWithdrawUnderlying;

if (!deposit || !primaryBorrowSymbol) return <PageLoading />;

Expand Down
2 changes: 1 addition & 1 deletion packages/risk-engine/src/account-risk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ export class AccountRiskProfile extends BaseRiskProfile {
};
}

override maxWithdraw(token: TokenDefinition): TokenBalance {
maxWithdraw(token: TokenDefinition): TokenBalance {
const balance = this.collateral.find((t) => t.token.id === token.id);
if (!balance) return TokenBalance.zero(token);

Expand Down
2 changes: 0 additions & 2 deletions packages/risk-engine/src/base-risk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -641,8 +641,6 @@ export abstract class BaseRiskProfile implements RiskFactors {
return undefined;
}

abstract maxWithdraw(token: TokenDefinition): TokenBalance;

/** Abstract Risk Factor Implementations **/
abstract freeCollateral(): TokenBalance;
abstract collateralRatio(): number | null;
Expand Down
22 changes: 17 additions & 5 deletions packages/risk-engine/src/vault-account-risk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,21 +363,21 @@ export class VaultAccountRiskProfile extends BaseRiskProfile {
};
}

override maxWithdraw(
_token: TokenDefinition = this.vaultShares.token
): TokenBalance {
maxWithdraw(_token: TokenDefinition = this.vaultShares.token) {
let costToRepay: TokenBalance | undefined;
let debtFee: TokenBalance | undefined;
if (this.vaultDebt.maturity !== PRIME_CASH_VAULT_MATURITY) {
const fCash = Registry.getExchangeRegistry().getfCashMarket(
this.network,
this.vaultDebt.currencyId
);

try {
const { tokensOut } = fCash.calculateTokenTrade(
const { tokensOut, feesPaid } = fCash.calculateTokenTrade(
this.vaultDebt.unwrapVaultToken(),
0
);
debtFee = feesPaid[0];

costToRepay = tokensOut
.add(this.vaultCash.unwrapVaultToken())
Expand Down Expand Up @@ -405,10 +405,22 @@ export class VaultAccountRiskProfile extends BaseRiskProfile {
costToRepay, // this is a negative number
this.vaultShares.token
);
const { netUnderlyingForVaultShares, feesPaid } =
this.vaultAdapter.getNetVaultSharesCost(this.vaultShares.neg());

// Return this in vault shares terms
return this.vaultShares.gt(netVaultSharesForUnderlying)
const maxWithdraw = this.vaultShares.gt(netVaultSharesForUnderlying)
? this.vaultShares.sub(netVaultSharesForUnderlying)
: this.vaultShares.copy(0);

return {
maxWithdrawUnderlying: maxWithdraw.toUnderlying(),
netRealizedCollateralBalance: netUnderlyingForVaultShares.add(feesPaid),
collateralFee: feesPaid,
debtFee,
netRealizedDebtBalance: costToRepay.add(
debtFee?.toUnderlying() || costToRepay.copy(0)
),
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,17 @@ export function usePortfolioLiquidationRisk(state: TradeState) {
}

export function useVaultLiquidationRisk(state: VaultTradeState) {
const { liquidationPrices, tooRisky, postAccountNoRisk } =
useVaultDetails(state);

return {
tooRisky,
postAccountNoRisk,
tableData: liquidationPrices,
};
}

export function useVaultDetails(state: VaultTradeState) {
const {
postAccountRisk,
netWorth,
Expand Down Expand Up @@ -195,5 +206,6 @@ export function useVaultLiquidationRisk(state: VaultTradeState) {
postAccountNoRisk:
postAccountRisk === undefined || postAccountRisk?.leverageRatio === null,
tableData: [...factors, ...liquidationPrices],
liquidationPrices,
};
}
Loading

0 comments on commit 4984998

Please sign in to comment.