Skip to content

Deploy an Oracle for Morpho Markets

Oracle deployment is a critical step when creating lending markets in Morpho, as these smart contracts provide essential price information that powers core functionalities like collateral evaluation and liquidation triggers. This guide will walk you through the entire process of configuring, testing, and deploying an oracle using the Morpho ecosystem tools.

Understanding Oracles in Morpho

Before jumping into deployment, let's review what oracles do in the Morpho ecosystem:

  • Purpose: Oracles provide price data that determines what one token is worth relative to another
  • Implementation: Morpho takes an oracle-agnostic approach, allowing market creators to choose appropriate price feed mechanisms
  • Interface: All oracles implement the IOracle interface with a single standardized function: price()
  • Immutability: Once a market is deployed, its oracle address cannot be modified, making correct setup crucial

The Oracle Deployment Process

This guide covers the complete process of deploying a new oracle using:

  1. MorphoChainlinkOracleV2Factory: The contract used to create new oracles
  2. Oracle Testor Tool: A web interface to validate your configuration and prepare deployment
  3. Oracle Decoder: A tool to run additional checks on your configuration post-deployment

Step 1: Understanding the Oracle Parameters

The MorphoChainlinkOracleV2Factory requires several parameters that determine how the oracle will calculate prices. Let's break them down:

Key Parameters

ParameterDescription
baseVaultERC4626 vault for the collateral token (zero address if not applicable)
baseVaultConversionSampleAmount of base vault shares for conversion calculation (use 1 if no vault)
baseFeed1First price feed for the collateral token (zero address if not needed)
baseFeed2Second price feed for the collateral token (zero address if not needed)
baseTokenDecimalsDecimal precision of the base/collateral token
quoteVaultERC4626 vault for the loan token (zero address if not applicable)
quoteVaultConversionSampleAmount of quote vault shares for conversion calculation (use 1 if no vault)
quoteFeed1First price feed for the loan token (zero address if not needed)
quoteFeed2Second price feed for the loan token (zero address if not needed)
quoteTokenDecimalsDecimal precision of the quote/loan token
saltUnique identifier for deterministic address creation (typically "0x")

Common Oracle Configurations

Different asset pairs require different oracle configurations. Here are some common patterns:

  1. Standard tokens (ETH/USDC): Direct price feed with no vaults
  2. Wrapped tokens (wstETH/ETH): Requires special exchange rate adapter
  3. Yield-bearing tokens (sDAI/USDC): Requires vault configuration (sDAI -> DAI -> USD -> USDC or sDAI -> DAI -> USDC)

Step 2: Using the Oracle Testor Tool

The Oracle Testor tool helps you validate your configuration before deployment, saving gas and preventing errors. Here's how to use it:

Oracle Testor Interface

Accessing the Oracle Testor

Navigate

Jump on the Morpho Oracle Interface at oracles.morpho.dev

Testor section

Verify you are on the "Testor" tab in the navigation menu

Form section

You'll see a form for configuring and testing your oracle

Basic Steps

Select Network

Choose the blockchain where you'll deploy your oracle. All blockchains where Morpho contracts were deployed are supported. Verify the addresses here.

Select Assets

  • Choose the Collateral Asset (the token that will be used as collateral)
  • Choose the Loan Asset (the token that will be borrowed)
  • If your token isn't listed, click "Add New Asset" to add custom token information

Advanced Configuration

After selecting your assets, you'll need to fill in the detailed oracle parameters:

Base (Collateral) Configuration

  • Base Vault: If your collateral is an ERC4626 token, enter the vault address. Otherwise, use the default zero address (0x0000000000000000000000000000000000000000).

  • Base Vault Conv. Sample: Default is 1 if using zero address for Base Vault. For ERC4626 tokens, use a value like 1000000000000000000 (1e18) to ensure precision. This value is used to query the convertToAsset function on the Base Vault address you put thus needs enough precision.

    Click here to read more about vault conversion sample
    Understanding Vault Conversion Samples

    For ERC4626 tokens like sDAI, the Vault Conversion Sample is critical for accurate pricing:

    1. What it does: The conversion sample represents the amount of vault shares (e.g., sDAI) that will be passed to the vault's convertToAssets function to determine the equivalent amount of underlying tokens (e.g., DAI).

    2. Why it matters: The convertToAssets function returns how much of the underlying asset (e.g., DAI) you would receive if you redeemed a given amount of vault shares (e.g., sDAI).

    3. Choosing a value:

      • For non-vault tokens: Use 1
      • For ERC4626 tokens: Use a value with sufficient precision, typically 1000000000000000000 (1e18)
    4. Example with sDAI:

      • When we set baseVault to the sDAI vault address (0x83F20F44975D03b1b09e64809B757c47f942BEeA)
      • And baseVaultConversionSample to 1e18 (1 full share)
      • The oracle internally calls convertToAssets(1e18) on the sDAI vault
      • This returns the current amount of DAI that 1e18 sDAI shares are worth
      • This exchange rate is then used in the price calculation alongside the DAI/USD price feed
    5. Formula visualization: For a sDAI/USDC oracle, the pricing path is:

      sDAI → DAI (via vault conversion) → USD (via DAI/USD feed) → USDC (via USDC/USD feed)

      The vault conversion is the first step in establishing the price routing path for ERC4626 tokens, allowing accurate relative valuation between yield-bearing tokens and their non-yield-bearing counterparts.

  • Base Feed 1: The primary price feed for your collateral asset. This could be a Chainlink, Redstone, Pyth, or Chronicle, ...

  • Base Feed 2: If needed, a secondary price feed for route calculation. Often the zero address.

  • Base Token Decimals: The decimal precision of your collateral token. This MUST match the actual collateral token decimals. If a Base Vault is put, use the underlying asset decimals. (Eg: if sDAI is put in Base Vault, use DAI decimals)

Quote (Loan) Configuration

  • Quote Vault: If your loan token is an ERC4626 token, enter the vault address. Otherwise, use the zero address.
  • Quote Vault Conv. Sample: Similar to Base Vault Conversion Sample, default is 1.
  • Quote Feed 1: Primary price feed for the loan asset.
  • Quote Feed 2: Secondary price feed if needed.
  • Quote Token Decimals: The decimal precision of your loan token.

Salt Configuration

  • Salt: This is typically set to 0x for initial deployments. It's used to create deterministic addresses. This means that changing the salt, with the very same config, will create a different oracle address.

Scale Factor

Running Tests

After configuring all parameters, click the "Check" button to run a series of tests:

  1. Decimals Check: Verifies that the token decimals match what's expected
  2. ERC4626 Check: Confirms if the loan asset is an ERC4626 token
  3. Deployment Check: Checks if an oracle with these parameters already exists [Only on Ethereum and Base]
  4. Feeds Check: Feel free to ignore this one [Deprecated]
  5. Price Check: Compares the calculated oracle price with expected market prices from a USD comparison price

Each check will show a status indicator:

  • Green = Passed
  • ⚠️ Yellow = Warning or needs attention
  • Red = Failed check

Generating Deployment Payload

If all checks pass, click the "Generate Payload" button to create the transaction data you'll need for deployment. You can:

  1. View the payload details directly in the interface
  2. Download the payload as a JSON file
  3. Open a Safe transaction to deploy using the "Open Safe" button (for multisig deployments)

Step 3: Deploying the Oracle

Once you've validated your configuration, you have two options for deployment:

Option A: Deploying via Etherscan

Find the Factory Contract

Connect Your Wallet

  • Click "Connect to Web3" on Etherscan
  • Connect your wallet (MetaMask, WalletConnect, etc.)

Fill in the Parameters

  • Navigate to the createMorphoChainlinkOracleV2 function
  • Input all the parameters you validated with the Oracle Testor
  • Double-check all values against your test results

Write Contract

  • Click "Write" to send the transaction
  • Confirm the transaction in your wallet
  • Wait for the transaction to be confirmed

Verify Deployment

  • Check for the CreateMorphoChainlinkOracleV2 event in the transaction logs
  • Note the deployed oracle address for future reference

Option B: Deploying via Safe (Multisig)

Prepare the Safe Transaction

  • Click "Open Safe" in the Oracle Testor after generating the payload
  • This will open the Safe interface with the transaction data pre-filled

Review and Submit**:

  • Review all parameters in the Safe interface
  • Submit the transaction for signing by your multisig participants
  • Execute the transaction once you have the required signatures

Step 4: Final Validation

After deployment, it's crucial to validate that your oracle is working correctly:

Use the Oracle Decoder Tool

Check the Oracle Price

  • Call the price() function on your deployed oracle
  • Verify that the returned price is within expected ranges

Example Configurations

Here are detailed examples for common token pairs:

A. cbBTC/USDC Oracle

baseVault: "0x0000000000000000000000000000000000000000",  // No Base Vault
baseVaultConversionSample: 1,                             // Default to 1 as no Base Vault
baseFeed1: "0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c",  // BTC/USD Feed
baseFeed2: "0x0000000000000000000000000000000000000000",  // - Default to Zero Address
baseTokenDecimals: 18,                                    // BTC Decimals
quoteVault: "0x0000000000000000000000000000000000000000", // No Quote Vault
quoteVaultConversionSample: 1,                            // Default to 1 as no Quote Vault
quoteFeed1: "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6", // USDC/USD Feed
quoteFeed2: "0x0000000000000000000000000000000000000000", // -
quoteTokenDecimals: 6,                                    // USDC Decimals
salt: "0x0000000000000000000000000000000000000000000000000000000000000000", // one can put any bytes 32 different than a deployed oracle with the very same configuration
Oracle Testor Interface

Explanation:

  • This configuration uses a direct BTC/USD price feed for calculating the cbBTC/USD feed price.
  • It also uses a USDC/USD quote feed for calculating the USDC/USD feed price.

As USDC/USD is used in the quote section, the final route is: cbBTC -> USD -> USDC.

B. DAI/USDC Oracle - USDC Hardcoded

The particularity in this example is that removing the QuoteFeed1 as it was in previous example acts as if someone was hardcoding the USDC price to 1 in the oracle of the market, because the virtual path is:

baseVault: "0x0000000000000000000000000000000000000000",  // -
baseVaultConversionSample: 1,                             // - default
baseFeed1: "0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9",  // DAI/USD Feed
baseFeed2: "0x0000000000000000000000000000000000000000",  // -
baseTokenDecimals: 18,                                    // DAI Decimals (NOT sDAI decimals)
quoteVault: "0x0000000000000000000000000000000000000000", // -
quoteVaultConversionSample: 1,                            // -
quoteFeed1: "0x0000000000000000000000000000000000000000", // EMPTY Feed
quoteFeed2: "0x0000000000000000000000000000000000000000", // -
quoteTokenDecimals: 6,                                    // USDC Decimals
salt: "0x0000000000000000000000000000000000000000000000000000000000000000",
Oracle Testor Interface

Explanation: This configuration is using the chainlink price feed for the DAI -> USD part, and is not pricing USDC -> USD on purpose to showcase the USDC hardcoding method.

C. sDAI/USDC Oracle

baseVault: "0x83F20F44975D03b1b09e64809B757c47f942BEeA",  // sDAI Vault
baseVaultConversionSample: 1000000000000000000,           // 1e18
baseFeed1: "0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9",  // DAI/USD Feed
baseFeed2: "0x0000000000000000000000000000000000000000",  // -
baseTokenDecimals: 18,                                    // DAI Decimals (NOT sDAI decimals)
quoteVault: "0x0000000000000000000000000000000000000000", // -
quoteVaultConversionSample: 1,                            // -
quoteFeed1: "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6", // USDC/USD Feed
quoteFeed2: "0x0000000000000000000000000000000000000000", // -
quoteTokenDecimals: 6,                                    // USDC Decimals
salt: "0x0000000000000000000000000000000000000000000000000000000000000000",
Oracle Testor Interface

Explanation: This configuration handles a yield-bearing token (sDAI) by specifying its vault address and using a higher conversion sample to account for the share-to-asset conversion. The price feeds are standard Chainlink feeds for the underlying assets.

D. sDAI/USDC Oracle - USDC Hardcoded

baseVault: "0x83F20F44975D03b1b09e64809B757c47f942BEeA",  // sDAI Vault
baseVaultConversionSample: 10000000000,                   // 1e10 - Explanation below
baseFeed1: "0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9",  // DAI/USD Feed
baseFeed2: "0x0000000000000000000000000000000000000000",  // -
baseTokenDecimals: 18,                                    // DAI Decimals (NOT sDAI decimals)
quoteVault: "0x0000000000000000000000000000000000000000", // -
quoteVaultConversionSample: 1,                            // -
quoteFeed1: "0x0000000000000000000000000000000000000000", // USDC/USD Feed
quoteFeed2: "0x0000000000000000000000000000000000000000", // -
quoteTokenDecimals: 6,                                    // USDC Decimals
salt: "0x0000000000000000000000000000000000000000000000000000000000000000",
Oracle Testor Interface
  • Explanation: This configuration handles a yield-bearing token (sDAI) by specifying its vault address and using a high conversion sample (1e10) to account for the share-to-asset conversion. The price feed used in Base Feed 1 is a standard Chainlink feed.

Why baseVaultConversionSample is 1e10 this time? Sometimes a vault conversion sample that is too high will result in a scale factor of 0 (or even cause a revert at deployment). A solution is to find a tradeoff by reducing the vault conversion sample value (base or quote) while keeping it high enough to maintain precision. Jump in this section for more details.

E. wstETH/ETH Oracle

baseVault: "0x0000000000000000000000000000000000000000",
baseVaultConversionSample: 1,
baseFeed1: "0x905b7dAbCD3Ce6B792D874e303D336424Cdb1421", // wstETH/stETH adapter
baseFeed2: "0x86392dC19c0b719886221c78AB11eb8Cf5c52812", // stETH/ETH price feed
baseTokenDecimals: 18,
quoteVault: "0x0000000000000000000000000000000000000000",
quoteVaultConversionSample: 1,
quoteFeed1: "0x0000000000000000000000000000000000000000",
quoteFeed2: "0x0000000000000000000000000000000000000000",
quoteTokenDecimals: 18,
salt: "0x",

Explanation: This configuration uses multiple feeds to establish a price path from wstETH to ETH. It requires a special adapter contract (WstEthStEthExchangeRateChainlinkAdapter) that handles the wstETH to stETH conversion, followed by a standard feed for stETH to ETH.

Troubleshooting Common Issues

Oracle Deployment Errors

IssueSolution
"Transaction reverted"Double-check all addresses and ensure they are valid contract addresses
"Gas estimation failed"Your configuration may be invalid or the contract cannot be executed properly
"Oracle with same parameters already deployed"Use the existing oracle (check the deployment check results)

Price Verification Issues

IssueSolution
Price significantly deviates from expectedCheck that your feeds are correctly configured and that the decimals are accurate
Price is zeroEnsure that all required feeds are working and that conversion samples are appropriate
Price overflow/underflowAdjust conversion samples to ensure mathematical operations don't exceed limits

Best Practices for Oracle Deployment

  1. Always test before deploying - Use the Oracle Testor tool to validate your configuration.
  2. Understand token decimals - Incorrect decimal configuration is a common source of errors.
  3. Use reliable price feeds - Choose established providers like Chainlink, Redstone, Chronicle, API3, Pyth ...
  4. Check for existing oracles - Reuse existing oracles when possible to save gas and ensure consistency.
  5. Document your configuration - Keep a record of all parameters for future reference.
  6. Verify after deployment - Always check that the deployed oracle returns expected prices.

Security Considerations

Since oracles are immutable once deployed and attached to a market, their security is paramount:

  1. Verify the source code of any adapter contracts you're using
  2. Understand the price path and how multiple feeds work together
  3. Consider failure modes in your price feeds and how they could affect the oracle
  4. Test with extreme market conditions to ensure robustness

Community Contributions

Getting Help

If you encounter issues during the oracle deployment process:

  1. Join the Morpho Discord to get community help
  2. For complex setups, consider reaching out to the Morpho Labs team or to a curator directly

By following this guide, you should be able to configure, test, and deploy oracles for your Morpho markets with confidence. Remember that careful setup is essential as oracles play a critical role in market safety and cannot be changed after market deployment.