Skip to content

Commit

Permalink
Earn position: fix deposit & coll reward values (#814)
Browse files Browse the repository at this point in the history
- The displayed deposit now comes from getCompoundedBoldDeposit() on the StabilityPool contract, rather than `deposit` on the subgraph, which corresponds to the initial deposit.
- The collateral gains now come from getDepositorCollGain on the StabilityPool contract.
  • Loading branch information
bpierre authored Feb 3, 2025
1 parent 0f83506 commit 67275e1
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 94 deletions.
21 changes: 2 additions & 19 deletions frontend/app/src/liquity-stability-pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,17 @@ const DECIMAL_PRECISION = 10n ** 18n;
const SCALE_FACTOR = 10n ** 9n;
const ONE_YEAR = 365n * 24n * 60n * 60n * 1000n;

// This is an adaptation of getDepositorCollGain() and
// _getCollGainFromSnapshots() from LiquityStabilityPool.sol
export function getCollGainFromSnapshots(
initialDeposit: bigint,
snapshotsP: bigint,
snapshotsS: bigint,
epochScaleS1: bigint, // S corresponding to the snapshot epoch + scale
epochScaleS2: bigint, // S corresponding to the snapshot epoch + scale + 1
): bigint {
if (initialDeposit === 0n) {
return 0n;
}

const firstPortion = epochScaleS1 - snapshotsS;
const secondPortion = epochScaleS2 / SCALE_FACTOR;

return (initialDeposit * (firstPortion + secondPortion)) / snapshotsP / DECIMAL_PRECISION;
}

export function useContinuousBoldGains(account: null | Address, collIndex: null | CollIndex) {
const collateral = getCollToken(collIndex);
const spYieldGainParams = useSpYieldGainParameters(collateral?.symbol ?? null);
const deposit = useStabilityPoolDeposit(collIndex, account);

const epochScale1 = useStabilityPoolEpochScale(
collIndex,
deposit.data?.snapshot.epoch ?? null,
deposit.data?.snapshot.scale ?? null,
);

const epochScale2 = useStabilityPoolEpochScale(
collIndex,
deposit.data?.snapshot.epoch ?? null,
Expand Down
127 changes: 52 additions & 75 deletions frontend/app/src/liquity-utils.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
import type { Contracts } from "@/src/contracts";
import type { StabilityPoolDepositQuery } from "@/src/graphql/graphql";
import type {
CollIndex,
Dnum,
PositionEarn,
PositionLoanCommitted,
PositionStake,
PrefixedTroveId,
TroveId,
} from "@/src/types";
import type { CollIndex, Dnum, PositionLoanCommitted, PositionStake, PrefixedTroveId, TroveId } from "@/src/types";
import type { Address, CollateralSymbol, CollateralToken } from "@liquity2/uikit";
import type { UseQueryResult } from "@tanstack/react-query";
import type { Config as WagmiConfig } from "wagmi";
Expand All @@ -17,15 +8,13 @@ import { DATA_REFRESH_INTERVAL, INTEREST_RATE_INCREMENT, INTEREST_RATE_MAX, INTE
import { getCollateralContract, getContracts, getProtocolContract } from "@/src/contracts";
import { dnum18, dnumOrNull, jsonStringifyWithDnum } from "@/src/dnum-utils";
import { CHAIN_BLOCK_EXPLORER, LIQUITY_STATS_URL } from "@/src/env";
import { getCollGainFromSnapshots, useContinuousBoldGains } from "@/src/liquity-stability-pool";
import { useContinuousBoldGains } from "@/src/liquity-stability-pool";
import {
useGovernanceStats,
useGovernanceUser,
useInterestRateBrackets,
useLoanById,
useStabilityPool,
useStabilityPoolDeposit,
useStabilityPoolEpochScale,
} from "@/src/subgraph-hooks";
import { isCollIndex, isTroveId } from "@/src/types";
import { COLLATERALS, isAddress } from "@liquity2/uikit";
Expand Down Expand Up @@ -95,9 +84,7 @@ export function useEarnPool(collIndex: null | CollIndex) {
const collateral = getCollToken(collIndex);
const pool = useStabilityPool(collIndex ?? undefined);
const stats = useLiquityStats();

const branchStats = collateral && stats.data?.branch[collateral?.symbol];

return {
...pool,
data: {
Expand All @@ -119,77 +106,67 @@ export function useEarnPosition(
return getBoldGains.data?.(Date.now()) ?? null;
};

const boldGains = useQuery({
const yieldGainsInBold = useQuery({
queryFn: () => getBoldGains_(),
queryKey: ["useEarnPosition:getBoldGains", collIndex, account],
refetchInterval: DATA_REFRESH_INTERVAL,
refetchInterval: 10_000,
enabled: getBoldGains.status === "success",
});

const spDeposit = useStabilityPoolDeposit(collIndex, account);
const spDepositSnapshot = spDeposit.data?.snapshot;
const StabilityPool = getCollateralContract(collIndex, "StabilityPool");
if (!StabilityPool) {
throw new Error(`Invalid collateral index: ${collIndex}`);
}

const epochScale1 = useStabilityPoolEpochScale(
collIndex,
spDepositSnapshot?.epoch ?? null,
spDepositSnapshot?.scale ?? null,
);
const spContractReads = useReadContracts({
contracts: [{
...StabilityPool,
functionName: "getCompoundedBoldDeposit",
args: [account ?? "0x"],
}, {
...StabilityPool,
functionName: "getDepositorCollGain",
args: [account ?? "0x"],
}],
query: {
enabled: account !== null,
},
});

const epochScale2 = useStabilityPoolEpochScale(
collIndex,
spDepositSnapshot?.epoch ?? null,
spDepositSnapshot?.scale ? spDepositSnapshot?.scale + 1n : null,
);
const spDepositCompounded = spContractReads.data?.[0];
const spCollGain = spContractReads.data?.[1];

const base = [
const useQueryResultBase = [
yieldGainsInBold,
getBoldGains,
boldGains,
spDeposit,
epochScale1,
epochScale2,
].find((r) => r.status !== "success") ?? epochScale2;

return {
...base,
data: (
!spDeposit.data
|| !boldGains.data
|| !epochScale1.data
|| !epochScale2.data
)
? null
: earnPositionFromGraph(spDeposit.data, {
bold: boldGains.data,
coll: dnum18(
getCollGainFromSnapshots(
spDeposit.data.deposit,
spDeposit.data.snapshot.P,
spDeposit.data.snapshot.S,
epochScale1.data.S,
epochScale2.data.S,
),
),
}),
};
}

function earnPositionFromGraph(
spDeposit: NonNullable<StabilityPoolDepositQuery["stabilityPoolDeposit"]>,
rewards: { bold: Dnum; coll: Dnum },
): PositionEarn {
const collIndex = spDeposit.collateral.collIndex;
if (!isCollIndex(collIndex)) {
throw new Error(`Invalid collateral index: ${collIndex}`);
}
if (!isAddress(spDeposit.depositor)) {
throw new Error(`Invalid depositor address: ${spDeposit.depositor}`);
spDepositCompounded,
spCollGain,
].find((r) => r && r.status !== "success") ?? yieldGainsInBold;

if (
!account || collIndex === null
|| spDepositCompounded?.status !== "success"
|| spCollGain?.status !== "success"
|| yieldGainsInBold.status !== "success"
) {
return {
...useQueryResultBase,
data: null,
};
}

return {
type: "earn",
owner: spDeposit.depositor,
deposit: dnum18(spDeposit.deposit),
collIndex,
rewards,
...useQueryResultBase,
data: {
type: "earn" as const,
owner: account,
deposit: dnum18(spDepositCompounded.result),
collIndex,
rewards: {
bold: yieldGainsInBold.data ?? dnum18(0),
coll: dnum18(spCollGain.result),
},
},
};
}

Expand Down

0 comments on commit 67275e1

Please sign in to comment.