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