import { Provider, ZeroAddress, toBigInt } from "ethers"; import { MorphoBlue__factory } from "ethers-types"; import { MarketParamsStruct } from "ethers-types/dist/protocols/morpho/blue/MorphoBlue"; import { getChainAddresses } from "../addresses"; import { ChainId, ChainUtils } from "../chain"; import { UnknownMarketConfigError, _try } from "../errors"; import { Address, MarketId } from "../types"; import { MarketUtils } from "./MarketUtils"; export interface MarketParams extends MarketParamsStruct { loanToken: Address; collateralToken: Address; oracle: Address; irm: Address; } export class MarketConfig implements MarketParams { private static readonly _CACHE: Record = {}; static get(id: MarketId) { const marketConfig = MarketConfig._CACHE[id]; if (!marketConfig) throw new UnknownMarketConfigError(id); return marketConfig; } static async fetch( id: MarketId, runner: { provider: Provider }, chainId?: ChainId ) { let config = _try(() => MarketConfig.get(id), UnknownMarketConfigError); if (!config) { chainId ??= ChainUtils.parseSupportedChainId( (await runner.provider.getNetwork()).chainId ); const { morpho } = getChainAddresses(chainId); config = new MarketConfig( // Always fetch at latest block because config is immutable. await MorphoBlue__factory.connect(morpho, runner).idToMarketParams(id) ); } return config; } static idle(token: Address) { return new MarketConfig({ collateralToken: ZeroAddress, loanToken: token, oracle: ZeroAddress, irm: ZeroAddress, lltv: 0n, }); } /** * The market's collateral token address. */ public readonly collateralToken: Address; /** * The market's loan token address. */ public readonly loanToken: Address; /** * The market's oracle address. */ public readonly oracle: Address; /** * The market's interest rate model address. */ public readonly irm: Address; /** * The market's liquidation Loan-To-Value (scaled by WAD). */ public readonly lltv: bigint; constructor({ collateralToken, loanToken, oracle, irm, lltv }: MarketParams) { this.collateralToken = collateralToken; this.loanToken = loanToken; this.oracle = oracle; this.irm = irm; this.lltv = toBigInt(lltv); MarketConfig._CACHE[this.id] = this; } /** * The market's hex-encoded id, defined as the hash of the market's params. */ get id() { return MarketUtils.getMarketId(this); } get liquidationIncentiveFactor() { return MarketUtils.getLiquidationIncentiveFactor(this); } }