This document explains how APY/APR is calculated for collateral pools and stability pools in the Harbor DApp. There are three main calculation methods used.
- On-chain call to stability pool contracts
- Returns:
[collateralTokenAPR, steamTokenAPR](both in 16 decimals, e.g.,1e16 = 1%) - Used for:
- Collateral Pool APR:
collateralPoolAPR.collateral + collateralPoolAPR.steam - Sail Pool APR:
sailPoolAPR.collateral + sailPoolAPR.steam
- Collateral Pool APR:
src/app/anchor/page.tsxlines 2044-2052 (Collateral Pool)src/app/anchor/page.tsxlines 2281-2289 (Sail Pool)
Collateral Pool APR:
// Location: src/app/anchor/page.tsx lines 2044-2052
const collateralAPRResult = reads?.[currentOffset + 1]
?.result as [bigint, bigint] | undefined;
collateralPoolAPR = collateralAPRResult
? {
collateral:
(Number(collateralAPRResult[0]) / 1e16) * 100,
steam: (Number(collateralAPRResult[1]) / 1e16) * 100,
}
: undefined;Sail Pool APR:
// Location: src/app/anchor/page.tsx lines 2281-2289
const sailAPRResult = reads?.[currentOffset + 1]
?.result as [bigint, bigint] | undefined;
sailPoolAPR = sailAPRResult
? {
collateral: (Number(sailAPRResult[0]) / 1e16) * 100,
steam: (Number(sailAPRResult[1]) / 1e16) * 100,
}
: undefined;ABI Definition:
// Location: src/abis/apr.ts
export const aprABI = [
{
inputs: [{ name: "account", type: "address" }],
name: "getAPRBreakdown",
outputs: [
{ name: "collateralTokenAPR", type: "uint256" },
{ name: "steamTokenAPR", type: "uint256" },
],
stateMutability: "view",
type: "function",
},
] as const;- On-chain call:
rewardData(tokenAddress)returns[lastUpdate, finishAt, rate, queued] - Client-side calculation: APR is calculated from the reward rate
- Used as: Fallback/addition when contract APR is 0 or missing
APR = (rewardRate * SECONDS_PER_YEAR / poolTVL) * (rewardTokenPrice / depositTokenPrice) * 100
Where:
- rewardRate = collateralRewardData[2] or sailRewardData[2] (the 'rate' field)
- SECONDS_PER_YEAR = 365 * 24 * 60 * 60 = 31,536,000
- poolTVL = collateralPoolTVL or sailPoolTVL
- rewardTokenPrice = peggedTokenPrice / 1e18 (USD)
- depositTokenPrice = peggedTokenPrice / 1e18 (USD)
src/hooks/usePoolRewardAPR.ts(lines 74-148) - Generic hook for any poolsrc/app/anchor/page.tsx(lines 2072-2132) - Collateral Pool calculationsrc/app/anchor/page.tsx(lines 2241-2302) - Sail Pool calculationsrc/hooks/anchor/useAnchorMarketData.ts(lines 350-412) - Market data processing
On-chain call:
// Location: src/hooks/usePoolRewardAPR.ts lines 74-81
// Get reward data (rate)
const [lastUpdate, finishAt, rate, queued] =
(await client.readContract({
address: poolAddress,
abi: STABILITY_POOL_ABI,
functionName: "rewardData",
args: [tokenAddress],
})) as [bigint, bigint, bigint, bigint];Client-side APR calculation:
// Location: src/hooks/usePoolRewardAPR.ts lines 132-148
// Calculate APR from reward rate
const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
const ratePerTokenPerSecond = Number(rate) / Number(poolTVL);
const annualRewards =
ratePerTokenPerSecond * Number(poolTVL) * SECONDS_PER_YEAR;
// Calculate USD values
const depositTokenPrice = peggedTokenPrice
? Number(peggedTokenPrice) / 1e18
: 1; // Default to $1 if price unavailable
const annualRewardsValueUSD = (annualRewards * tokenPrice) / 1e18;
const depositValueUSD = (Number(poolTVL) * depositTokenPrice) / 1e18;
let apr = 0;
if (depositValueUSD > 0) {
apr = (annualRewardsValueUSD / depositValueUSD) * 100;
}On-chain call:
// Location: src/app/anchor/page.tsx lines 2072-2084
// Read reward data for APR fallback calculation
const collateralRewardDataRead = currentPeggedTokenAddress
? reads?.[currentOffset + 4]
: undefined;
const collateralRewardData =
collateralRewardDataRead?.status === "success" &&
collateralRewardDataRead.result
? (collateralRewardDataRead.result as [
bigint,
bigint,
bigint,
bigint
]) // [lastUpdate, finishAt, rate, queued]
: undefined;Client-side APR calculation:
// Location: src/app/anchor/page.tsx lines 2086-2132
// Calculate APR from reward rate if contract APR is 0 or undefined
if (
collateralRewardData &&
collateralPoolTVL &&
collateralPoolTVL > 0n &&
peggedTokenPrice
) {
const rewardRate = collateralRewardData[2]; // rate
if (rewardRate > 0n) {
const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
const ratePerTokenPerSecond =
Number(rewardRate) / Number(collateralPoolTVL);
const annualRewards =
ratePerTokenPerSecond *
Number(collateralPoolTVL) *
SECONDS_PER_YEAR;
const rewardTokenPrice = Number(peggedTokenPrice) / 1e18; // pegged token price in USD
const depositTokenPrice = Number(peggedTokenPrice) / 1e18; // same for collateral pool
const annualRewardsValueUSD =
(annualRewards * rewardTokenPrice) / 1e18;
const depositValueUSD =
(Number(collateralPoolTVL) * depositTokenPrice) / 1e18;
if (depositValueUSD > 0) {
const calculatedAPR =
(annualRewardsValueUSD / depositValueUSD) * 100;
// Add to existing APR (don't replace, accumulate)
if (calculatedAPR > 0) {
if (!collateralPoolAPR) {
collateralPoolAPR = {
collateral: calculatedAPR,
steam: 0,
};
} else {
// Add to existing APR
collateralPoolAPR = {
collateral:
(collateralPoolAPR.collateral || 0) +
calculatedAPR,
steam: collateralPoolAPR.steam || 0,
};
}
}
}
}
}On-chain call:
// Location: src/app/anchor/page.tsx lines 2241-2254
// Read reward data for APR fallback calculation
const sailRewardDataRead = currentPeggedTokenAddress
? reads?.[currentOffset + 4]
: undefined;
const sailRewardData =
sailRewardDataRead?.status === "success" &&
sailRewardDataRead.result
? (sailRewardDataRead.result as [
bigint,
bigint,
bigint,
bigint
]) // [lastUpdate, finishAt, rate, queued]
: undefined;Client-side APR calculation:
// Location: src/app/anchor/page.tsx lines 2256-2302
// Calculate APR from reward rate if contract APR is 0 or undefined
if (
sailRewardData &&
sailPoolTVL &&
sailPoolTVL > 0n &&
peggedTokenPrice
) {
const rewardRate = sailRewardData[2]; // rate
if (rewardRate > 0n) {
const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
const ratePerTokenPerSecond =
Number(rewardRate) / Number(sailPoolTVL);
const annualRewards =
ratePerTokenPerSecond *
Number(sailPoolTVL) *
SECONDS_PER_YEAR;
const rewardTokenPrice = Number(peggedTokenPrice) / 1e18; // pegged token price in USD
const depositTokenPrice = Number(peggedTokenPrice) / 1e18; // same for sail pool
const annualRewardsValueUSD =
(annualRewards * rewardTokenPrice) / 1e18;
const depositValueUSD =
(Number(sailPoolTVL) * depositTokenPrice) / 1e18;
if (depositValueUSD > 0) {
const calculatedAPR =
(annualRewardsValueUSD / depositValueUSD) * 100;
// Add to existing APR (don't replace, accumulate)
if (calculatedAPR > 0) {
if (!sailPoolAPR) {
sailPoolAPR = {
collateral: calculatedAPR,
steam: 0,
};
} else {
// Add to existing APR
sailPoolAPR = {
collateral:
(sailPoolAPR.collateral || 0) + calculatedAPR,
steam: sailPoolAPR.steam || 0,
};
}
}
}
}
}On-chain call:
// Location: src/hooks/anchor/useAnchorMarketData.ts lines 350-362
const collateralRewardDataRead = currentPeggedTokenAddress
? reads?.[currentOffset + 5]
: undefined;
const collateralRewardData =
collateralRewardDataRead?.status === "success" &&
collateralRewardDataRead.result
? (collateralRewardDataRead.result as [
bigint,
bigint,
bigint,
bigint
]) // [lastUpdate, finishAt, rate, queued]
: undefined;Client-side APR calculation:
// Location: src/hooks/anchor/useAnchorMarketData.ts lines 364-412
// Calculate APR from reward rate if contract APR is 0 or undefined
let peggedTokenAPRForCollateral = 0;
if (
collateralRewardData &&
collateralPoolTVL &&
collateralPoolTVL > 0n &&
peggedTokenPrice
) {
const rewardRate = collateralRewardData[2]; // rate
if (rewardRate > 0n) {
const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
const ratePerTokenPerSecond =
Number(rewardRate) / Number(collateralPoolTVL);
const annualRewards =
ratePerTokenPerSecond *
Number(collateralPoolTVL) *
SECONDS_PER_YEAR;
const rewardTokenPrice = Number(peggedTokenPrice) / 1e18; // pegged token price in USD
const depositTokenPrice = Number(peggedTokenPrice) / 1e18; // same for collateral pool
const annualRewardsValueUSD =
(annualRewards * rewardTokenPrice) / 1e18;
const depositValueUSD =
(Number(collateralPoolTVL) * depositTokenPrice) / 1e18;
if (depositValueUSD > 0) {
peggedTokenAPRForCollateral =
(annualRewardsValueUSD / depositValueUSD) * 100;
// Add to existing APR (don't replace, accumulate)
if (peggedTokenAPRForCollateral > 0) {
if (!collateralPoolAPR) {
collateralPoolAPR = {
collateral: peggedTokenAPRForCollateral,
steam: 0,
};
} else {
// Add to existing APR
collateralPoolAPR = {
collateral:
(collateralPoolAPR.collateral || 0) +
peggedTokenAPRForCollateral,
steam: collateralPoolAPR.steam || 0,
};
}
}
}
}
}- Calculated from:
harvestable()from minter contract (on-chain)rewardData()- queued rewards (on-chain)- 7-day projection period
- Pool TVL (on-chain)
Projected APR = (harvestable + queued) / 7 days * 365 days / poolTVL * 100
Or more specifically:
- rewardsPer7Days = (harvestable + queued) / periodLength * periodLength
- rewardsValueUSD = (rewardsPer7Days / 1e18) * collateralPriceUSD
- depositValueUSD = (poolTVL / 1e18) * collateralPriceUSD
- Projected APR = (rewardsValueUSD / depositValueUSD) * (365 / 7) * 100
src/hooks/useProjectedAPR.ts(lines 452-465 for collateral pool, 472-494 for leveraged pool)
On-chain calls:
// Location: src/hooks/useProjectedAPR.ts lines 64-126
// Batch read: Basic contract data
const { data: basicReads, isLoading: isLoadingBasic } = useContractReads({
contracts: [
// Minter reads
{
address: minterAddress as `0x${string}`,
abi: MINTER_ABI,
functionName: "harvestable",
},
// Collateral pool reads
{
address: collateralPoolAddress as `0x${string}`,
abi: STABILITY_POOL_ABI,
functionName: "totalAssetSupply",
},
// Leveraged pool reads
{
address: leveragedPoolAddress as `0x${string}`,
abi: STABILITY_POOL_ABI,
functionName: "totalAssetSupply",
},
// ... more reads
],
// ...
});
// Get reward data from pools (for finishAt and queued)
const { data: rewardDataReads, isLoading: isLoadingRewardData } =
useContractReads({
contracts: [
{
address: collateralPoolAddress as `0x${string}`,
abi: STABILITY_POOL_ABI,
functionName: "rewardData",
args: wrappedCollateralToken ? [wrappedCollateralToken] : undefined,
},
{
address: leveragedPoolAddress as `0x${string}`,
abi: STABILITY_POOL_ABI,
functionName: "rewardData",
args: wrappedCollateralToken ? [wrappedCollateralToken] : undefined,
},
{
address: collateralPoolAddress as `0x${string}`,
abi: STABILITY_POOL_ABI,
functionName: "REWARD_PERIOD_LENGTH",
},
],
// ...
});Client-side calculation:
// Location: src/hooks/useProjectedAPR.ts lines 452-465 (Collateral Pool)
// Calculate APR for collateral pool
// APR = (rewardsValue / depositValue) * (365/7) * 100
let collateralPoolAPR: number | null = null;
if (safeCollateralPoolSupply > 0n && collateralPriceUSD > 0) {
const rewardsPer7Days = Number(projectedCollateralRate) * periodLength;
const rewardsValueUSD = (rewardsPer7Days / 1e18) * collateralPriceUSD;
const depositValueUSD =
(Number(safeCollateralPoolSupply) / 1e18) * collateralPriceUSD;
if (depositValueUSD > 0) {
collateralPoolAPR =
(rewardsValueUSD / depositValueUSD) * (DAYS_PER_YEAR / 7) * 100;
}
} else if (collateralHasRewardsNoTVL) {
// No TVL but rewards waiting - signal "10k%+"
collateralPoolAPR = 10000;
}
// Location: src/hooks/useProjectedAPR.ts lines 472-494 (Leveraged Pool)
// Calculate APR for leveraged pool
let leveragedPoolAPR: number | null = null;
if (safeLeveragedPoolSupply > 0n && collateralPriceUSD > 0) {
const rewardsPer7Days = Number(projectedLeveragedRate) * periodLength;
const rewardsValueUSD = (rewardsPer7Days / 1e18) * collateralPriceUSD;
const depositValueUSD =
(Number(safeLeveragedPoolSupply) / 1e18) * collateralPriceUSD;
if (depositValueUSD > 0) {
leveragedPoolAPR =
(rewardsValueUSD / depositValueUSD) * (DAYS_PER_YEAR / 7) * 100;
}
} else if (leveragedHasRewardsNoTVL) {
// No TVL but rewards waiting - signal "10k%+"
leveragedPoolAPR = 10000;
}| APR Type | Source | Calculation Method | Code Location |
|---|---|---|---|
| Contract APR | On-chain getAPRBreakdown() |
Direct contract return (16 decimals) | src/app/anchor/page.tsx lines 2044-2052, 2281-2289 |
| Reward Rate APR | On-chain rewardData() + client calc |
(rate * seconds_per_year / TVL) * price_ratio * 100 |
src/hooks/usePoolRewardAPR.ts lines 132-148src/app/anchor/page.tsx lines 2086-2132, 2256-2302src/hooks/anchor/useAnchorMarketData.ts lines 364-412 |
| Projected APR | On-chain harvestable() + rewardData() + client calc |
(harvestable + queued) / 7 days * 365 / TVL * 100 |
src/hooks/useProjectedAPR.ts lines 452-494 |
-
All three methods use on-chain data - Some calculations are done client-side, but all data originates from on-chain contract calls.
-
Priority order in UI:
- Projected APR is used when available (most accurate for future rewards)
- Falls back to Contract APR + Reward Rate APR when Projected APR is unavailable
-
APR accumulation:
- Contract APR and Reward Rate APR are accumulated (added together), not replaced
- Multiple reward tokens can contribute to the total APR
-
Decimal handling:
- Contract APR: 16 decimals (
1e16 = 1%) - Reward rates: 18 decimals (standard ERC20)
- All calculations convert to percentage (multiply by 100)
- Contract APR: 16 decimals (
-
Price sources:
peggedTokenPrice: From minter contract (18 decimals)collateralPrice: From price oracle (varies by decimals)- Token prices are used to calculate USD values for APR calculations
Contract addresses are stored in src/config/contracts.ts and can be accessed via the markets configuration. The addresses vary by market (ETH/fxUSD, BTC/fxUSD, BTC/stETH, etc.).
Location: src/config/contracts.ts lines 118-160
"eth-fxusd": {
addresses: {
minter: "0xd6E2F8e57b4aFB51C6fA4cbC012e1cE6aEad989F",
peggedToken: "0x7A53EBc85453DD006824084c4f4bE758FcF8a5B5", // haETH
leveragedToken: "0x0Cd6BB1a0cfD95e2779EDC6D17b664B481f2EB4C", // hsFXUSD-ETH
stabilityPoolCollateral: "0x1F985CF7C10A81DE1940da581208D2855D263D72",
stabilityPoolLeveraged: "0x438B29EC7a1770dDbA37D792F1A6e76231Ef8E06",
stabilityPoolManager: "0xE39165aDE355988EFb24dA4f2403971101134CAB",
priceOracle: "0x71437C90F1E0785dd691FD02f7bE0B90cd14c097",
collateralPrice: "0x71437C90F1E0785dd691FD02f7bE0B90cd14c097",
wrappedCollateralToken: "0x7743e50F534a7f9F1791DdE7dCD89F7783Eefc39", // fxSAVE
collateralToken: "0x085780639CC2cACd35E474e71f4d000e2405d8f6", // fxUSD
genesis: "0xC9df4f62474Cf6cdE6c064DB29416a9F4f27EBdC",
reservePool: "0x7A5c4ca972CE2168d5215d252946dDbd1cAd2015",
feeReceiver: "0xdC903fe5ebCE440f22578D701b95424363D20881",
}
}Location: src/config/contracts.ts lines 166-208
"btc-fxusd": {
addresses: {
minter: "0x33e32ff4d0677862fa31582CC654a25b9b1e4888",
peggedToken: "0x25bA4A826E1A1346dcA2Ab530831dbFF9C08bEA7", // haBTC
leveragedToken: "0x9567c243F647f9Ac37efb7Fc26BD9551Dce0BE1B", // hsFXUSD-BTC
stabilityPoolCollateral: "0x86561cdB34ebe8B9abAbb0DD7bEA299fA8532a49",
stabilityPoolLeveraged: "0x9e56F1E1E80EBf165A1dAa99F9787B41cD5bFE40",
stabilityPoolManager: "0x768E0a386e1972eB5995429Fe21E7aC0f22F516e",
priceOracle: "0x8F76a260c5D21586aFfF18f880FFC808D0524A73",
collateralPrice: "0x8F76a260c5D21586aFfF18f880FFC808D0524A73",
wrappedCollateralToken: "0x7743e50F534a7f9F1791DdE7dCD89F7783Eefc39", // fxSAVE
collateralToken: "0x085780639CC2cACd35E474e71f4d000e2405d8f6", // fxUSD
genesis: "0x42cc9a19b358a2A918f891D8a6199d8b05F0BC1C",
reservePool: "0xfDE46D4425138aA01319bB8587Cb935a0393DfE3",
feeReceiver: "0x70DdA12032335656b63435840Cd55ff7A19dDAb7",
}
}Location: src/config/contracts.ts lines 210-252
"btc-steth": {
addresses: {
minter: "0x[MINTER_ADDRESS]", // Check contracts.ts for actual address
peggedToken: "0x25bA4A826E1A1346dcA2Ab530831dbFF9C08bEA7", // haBTC (shared with BTC/fxUSD)
leveragedToken: "0x[LEVERAGED_TOKEN_ADDRESS]", // hsSTETH-BTC
stabilityPoolCollateral: "0x[COLLATERAL_POOL_ADDRESS]",
stabilityPoolLeveraged: "0x[LEVERAGED_POOL_ADDRESS]",
stabilityPoolManager: "0x5e9Bcaa1EDfD665c09a9e6693B447581d61A85A1",
priceOracle: "0x[PRICE_ORACLE_ADDRESS]",
collateralPrice: "0x[COLLATERAL_PRICE_ADDRESS]",
wrappedCollateralToken: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", // wstETH (Lido)
collateralToken: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", // wstETH
// ... other addresses
}
}Note: Contract addresses are retrieved from the market configuration:
const market = markets[marketId];
const stabilityPoolAddress = market.addresses.stabilityPoolCollateral;
const minterAddress = market.addresses.minter;Location: src/abis/apr.ts
export const aprABI = [
{
inputs: [{ name: "account", type: "address" }],
name: "getAPRBreakdown",
outputs: [
{ name: "collateralTokenAPR", type: "uint256" }, // 16 decimals (1e16 = 1%)
{ name: "steamTokenAPR", type: "uint256" }, // 16 decimals (1e16 = 1%)
],
stateMutability: "view",
type: "function",
},
] as const;Usage: Called on stability pool contracts (both collateral and leveraged pools).
Location: src/abis/shared.ts lines 195-377
export const STABILITY_POOL_ABI = [
// Reward data function (returns [lastUpdate, finishAt, rate, queued])
{
inputs: [{ name: "rewardToken", type: "address" }],
name: "rewardData",
outputs: [
{ name: "lastUpdate", type: "uint256" },
{ name: "finishAt", type: "uint256" },
{ name: "rate", type: "uint256" }, // Reward rate per second (18 decimals)
{ name: "queued", type: "uint256" }, // Queued rewards (18 decimals)
],
stateMutability: "view",
type: "function",
},
// Get all active reward tokens
{
inputs: [],
name: "activeRewardTokens",
outputs: [{ name: "", type: "address[]" }],
stateMutability: "view",
type: "function",
},
// Pool TVL functions
{
inputs: [],
name: "totalAssetSupply",
outputs: [{ name: "amount", type: "uint256" }],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "totalAssets",
outputs: [{ name: "assets", type: "uint256" }],
stateMutability: "view",
type: "function",
},
// User balance
{
inputs: [{ name: "account", type: "address" }],
name: "assetBalanceOf",
outputs: [{ name: "amount", type: "uint256" }],
stateMutability: "view",
type: "function",
},
// Reward period length (for projected APR)
{
inputs: [],
name: "REWARD_PERIOD_LENGTH",
outputs: [{ name: "", type: "uint256" }],
stateMutability: "view",
type: "function",
},
// Claimable rewards for a user
{
inputs: [
{ name: "account", type: "address" },
{ name: "rewardToken", type: "address" },
],
name: "claimable",
outputs: [{ name: "amount", type: "uint256" }],
stateMutability: "view",
type: "function",
},
// Additional functions (deposit, withdraw, claim, etc.)
// ... see src/abis/shared.ts for full ABI
] as const;Location: src/abis/shared.ts lines 456-588
export const MINTER_ABI = [
// Harvestable amount (for projected APR)
{
inputs: [],
name: "harvestable",
outputs: [{ name: "wrappedAmount", type: "uint256" }], // 18 decimals
stateMutability: "view",
type: "function",
},
// Token addresses
{
inputs: [],
name: "PEGGED_TOKEN",
outputs: [{ name: "", type: "address" }],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "LEVERAGED_TOKEN",
outputs: [{ name: "", type: "address" }],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "WRAPPED_COLLATERAL_TOKEN",
outputs: [{ name: "", type: "address" }],
stateMutability: "view",
type: "function",
},
// Price functions
{
inputs: [],
name: "peggedTokenPrice",
outputs: [{ type: "uint256" }], // 18 decimals
stateMutability: "view",
type: "function",
},
// Balance functions
{
inputs: [],
name: "collateralTokenBalance",
outputs: [{ type: "uint256", name: "" }],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "totalCollateralValue",
outputs: [{ type: "uint256", name: "" }],
stateMutability: "view",
type: "function",
},
// Ratio functions
{
inputs: [],
name: "collateralRatio",
outputs: [{ type: "uint256", name: "" }],
stateMutability: "view",
type: "function",
},
// Additional functions (mint, redeem, etc.)
// ... see src/abis/shared.ts for full ABI
] as const;Location: src/abis/shared.ts lines 382-404
export const STABILITY_POOL_MANAGER_ABI = [
{
inputs: [],
name: "harvestBountyRatio",
outputs: [{ name: "", type: "uint256" }],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "harvestCutRatio",
outputs: [{ name: "", type: "uint256" }],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "rebalanceThreshold",
outputs: [{ type: "uint256", name: "" }],
stateMutability: "view",
type: "function",
},
] as const;Usage: Used to determine how rewards are distributed from harvested amounts.
Location: src/abis/shared.ts lines 9-65
export const ERC20_ABI = [
{
inputs: [{ name: "account", type: "address" }],
name: "balanceOf",
outputs: [{ type: "uint256" }],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "symbol",
outputs: [{ type: "string" }],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "decimals",
outputs: [{ type: "uint8" }],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "totalSupply",
outputs: [{ type: "uint256" }],
stateMutability: "view",
type: "function",
},
// ... additional ERC20 functions
] as const;Usage: Used to fetch token metadata (symbol, decimals) and balances for reward tokens.
src/app/anchor/page.tsx- Main anchor page with APR displaysrc/hooks/useProjectedAPR.ts- Projected APR calculation hooksrc/hooks/usePoolRewardAPR.ts- Generic pool reward APR hooksrc/hooks/anchor/useAnchorMarketData.ts- Market data processing with APRsrc/hooks/anchor/useAnchorContractReads.ts- Contract reads setupsrc/abis/apr.ts- APR contract ABIsrc/abis/shared.ts- Shared ABIs including STABILITY_POOL_ABI, MINTER_ABI, ERC20_ABIsrc/config/contracts.ts- Contract addresses configurationsrc/config/markets.ts- Market configurations (references contracts.ts)src/config/contracts.index.ts- Contract configuration switcher (production/test2)
import { markets } from "@/config/markets";
// Get market configuration
const market = markets["eth-fxusd"];
// Access contract addresses
const stabilityPoolCollateral = market.addresses.stabilityPoolCollateral;
const stabilityPoolLeveraged = market.addresses.stabilityPoolLeveraged;
const minterAddress = market.addresses.minter;
const priceOracle = market.addresses.priceOracle;Last updated: [Current Date]