Docs

Deploy an Oracle for Morpho Markets

Deploy and validate a Morpho oracle for curators, covering Chainlink Oracle V2 parameters, price feeds, conversion samples, and post-deployment checks.

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 Tester 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
salt32-byte value for deterministic address creation (defaults to zero bytes32)

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 Tester Tool

The Oracle Tester tool helps you validate your configuration before deployment, saving gas and preventing errors. It is accessible in the Curator App here: curator.morpho.org/oracles/tester.

Basic Steps

Select Network

Choose the blockchain where you'll deploy your oracle. The Oracle Tester and Decoder are limited to the chains supported by the Curator App and Morpho API. Check the network selector for the available chains. A Morpho contract deployment on a chain does not by itself mean these tools support it.

Select Assets

  • Choose the Collateral token (the token that will be used as collateral).
  • Choose the Loan token (the token that will be borrowed).
  • Search by token name or paste its address in either selector.

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.

  • 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. In most of the case, it should 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: A 32-byte hex value. The form defaults to 0x0000000000000000000000000000000000000000000000000000000000000000 (zero bytes32). Changing the salt with the same configuration creates a different oracle address. Use Random salt when you need a new salt.

Scale Factor

Running Tests

After configuring all parameters, click Run checks. Review the results under Oracle review:

  1. Decimals: Verifies that the configured token decimals match the expected values.
  2. ERC-4626 loan asset: Checks whether the loan token is an ERC-4626 vault.
  3. Token behaviour: Checks for token behaviours that can affect compatibility with Morpho.
  4. Factory deployment: Simulates deploying the oracle and reports if the salt has already been used with these parameters.
  5. Price check: Compares the calculated oracle price with a USD reference price.

Each check shows its result. Review any warning, failed check, or unavailable result before deployment.

If the Tester reports that the salt has already been used with the same parameters, an oracle may already be deployed. This does not confirm that a market uses it. The Tester flags the collision but does not find the existing oracle for you.

Before deploying another oracle, check existing markets or the factory's CreateMorphoChainlinkOracleV2 events on the chain's explorer. Use the Oracle Decoder to verify the existing oracle's configuration and reuse it if it matches your requirements. Reuse an existing market when all its parameters match, rather than creating an otherwise identical market with a different oracle address. This helps avoid liquidity fragmentation.

Choose Random salt and run the checks again only if you intend to deploy a new oracle.

Generating Deployment Payload

When available, click Download Safe batch JSON to download the deployment transaction. The download is available only when Decimals and Factory deployment pass and no check has failed. Review any remaining warnings or unavailable checks before using the file.

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

Navigate to the MorphoChainlinkOracleV2Factory on your chain's explorer (addresses available here).

Fill in the Parameters

  • Navigate to the createMorphoChainlinkOracleV2 function
  • Input all the parameters you validated with the Oracle Tester
  • 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

  • Download the deployment transaction with Download Safe batch JSON in the Oracle Tester.
  • Import the JSON file into the Transaction Builder in your Safe.

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

  • Open the Oracle Decoder in the Curator App.
  • Enter your oracle address
  • Verify that it returns the expected price for your asset pair

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: 8,                                     // 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

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",

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",

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",
  • 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.

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: "0x0000000000000000000000000000000000000000000000000000000000000000",

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 Tester 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. Get in touch via the chatbox on help.morpho.org
  2. For complex setups, consider reaching out to the Morpho Association 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.