Pricing Assets

Pricing assets is a key component to maintaing the security of the protocol

Single Sided Assets

Below is a list of all collateral assets for which we have oracle provider(s) for, as well as NECT (our stablecoin).

Asset
Oracle Provider(s)

UNIBTC

Chronicle

ylstETH

Chronicle

WBERA

Redstone

PUMPBTC

Redstone + Chronicle

SOLVBTC

Redstone

SOLVBTC.bbn

Redstone

BeraETH

Redstone

Stakestone ETH

Redstone

WETH

Redstone

RSETH

Redstone

NECT

Redstone + Chronicle + eOracle

Kodiak Islands

We currently support 3 Kodiak Islands as collateral. These are WBTC-HONEY, WETH-HONEY and WETH-WBTC. Below is a high level overview of how we price these assets, using our custom islandFeed contracts for each LP pair:

  • Combine Token Prices: We adjust each tokenโ€™s price so theyโ€™re measured on the same scale, accounting for differences in decimals for various tokens.

  • Smooth the Price Difference: We then take the square-root of the price ratio. In everyday terms, this step โ€œsmooths outโ€ the raw difference between token values, making it more reflective of how liquidity is actually balanced in the pool.

  • Value the LP Token: Finally, we determine the LP tokenโ€™s value by adding up the adjusted values of the tokens in the pool and dividing by the total number of LP tokens. This gives us a per-token price that reflects the combined market value of the underlying assets.

The relevant code snippet for the process above is here:

function fetchPrice() external view returns (uint) {
    uint priceFeed_token0 = priceFeed.fetchPrice(token0);
    uint priceFeed_token1 = priceFeed.fetchPrice(token1);

    uint decimalMultiplier;
    uint decimalDivider;
    uint decimalDifference = BeraborrowMath._getAbsoluteDifference(decimals0, decimals1);
    if (decimals0 >= decimals1) {
        decimalMultiplier = 1;
        decimalDivider = 10 ** decimalDifference;
    } else {
        decimalMultiplier = 10 ** decimalDifference;
        decimalDivider = 1;
    }

    uint priceRatio = (priceFeed_token0 * decimalMultiplier * 1e18) / (priceFeed_token1 * decimalDivider);

    uint160 price_sqrtRatioX96 = uint160((Math.sqrt(priceRatio) * (2 ** 96)) / 1e9);

    // Note: getUnderlyingBalancesAtPrice gets the reserves at a specified price based on UniV3 curve math + accumulated fees + token balances in contract
    // The token reserve math is as described here: https://docs.parallel.fi/parallel-finance/staking-and-derivative-token-yield-management/borrow-against-uniswap-v3-lp-tokens/uniswap-v3-lp-token-analyzer
    // As we use oracle price (rather than current bock pool balances) to get the reserves, this calculation isn't subject to flash loan exploit
    (uint reserve0, uint reserve1) = IKodiakIsland(island).getUnderlyingBalancesAtPrice(price_sqrtRatioX96);

    uint normalizedReserve0 = reserve0 * (10 ** (18 - decimals0));
    uint normalizedReserve1 = reserve1 * (10 ** (18 - decimals1));

    uint totalSupply = IKodiakIsland(island).totalSupply();

    if (totalSupply == 0) return 0;

    uint totalValue = normalizedReserve0 * priceFeed_token0 + normalizedReserve1 * priceFeed_token1;

    return totalValue / totalSupply;
}

BEX

Coming thooon...

Last updated